asp.net – 用于错误处理和丢失图像的HttpModule
我有一个HttpModule,我把它从一些不同的在线源码拼凑在一起,形成了(大部分)与传统的ASP.NET应用程序以及ASP.NET MVC应用程序一起工作的东西.其中最大的部分来自CodePlex上的kigg项目.我的问题是处理由于图像丢失导致的404错误.在下面的代码中,我必须通过HttpContext的Request对象中的AcceptedTypes集合显式查找请求的图像.如果我没有进行此检查,即使丢失的图像也会导致重定向到Web.config中我的部分中定义的404页面.
这种方法的问题是(除了它闻到的事实)是这只是图像.我基本上必须对可以想象的每种内容类型执行此操作,我不希望发生此重定向行为. 看看下面的代码,是否有人可以推荐某种重构,这可能会使非页面请求变得更宽松?我仍然希望它们在IIS日志中(所以我可能不得不删除ClearError()调用),但我不认为破坏的图像会影响用户体验,直到将它们重定向到错误页面. 代码如下: /// <summary> /// Provides a standardized mechanism for handling exceptions within a web application. /// </summary> public class ErrorHandlerModule : IHttpModule { #region Public Methods /// <summary> /// Disposes of the resources (other than memory) used by the module that implements /// <see cref="T:System.Web.IHttpModule"/>. /// </summary> public void Dispose() { } /// <summary> /// Initializes a module and prepares it to handle requests. /// </summary> /// <param name="context"> /// An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods,properties,and events /// common to all application objects within an ASP.NET application.</param> public void Init(HttpApplication context) { context.Error += this.OnError; } #endregion /// <summary> /// Called when an error occurs within the application. /// </summary> /// <param name="source">The source.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void OnError(object source,EventArgs e) { var httpContext = HttpContext.Current; var imageRequestTypes = httpContext.Request.AcceptTypes.Where(a => a.StartsWith("image/")).Select(a => a.Count()); if (imageRequestTypes.Count() > 0) { httpContext.ClearError(); return; } var lastException = HttpContext.Current.Server.GetLastError().GetBaseException(); var httpException = lastException as HttpException; var statusCode = (int)HttpStatusCode.InternalServerError; if (httpException != null) { statusCode = httpException.GetHttpCode(); if ((statusCode != (int)HttpStatusCode.NotFound) && (statusCode != (int)HttpStatusCode.ServiceUnavailable)) { // TODO: Log exception from here. } } var redirectUrl = string.Empty; if (httpContext.IsCustomErrorEnabled) { var errorsSection = WebConfigurationManager.GetSection("system.web/customErrors") as CustomErrorsSection; if (errorsSection != null) { redirectUrl = errorsSection.DefaultRedirect; if (httpException != null && errorsSection.Errors.Count > 0) { var item = errorsSection.Errors[statusCode.ToString()]; if (item != null) { redirectUrl = item.Redirect; } } } } httpContext.Response.Clear(); httpContext.Response.StatusCode = statusCode; httpContext.Response.TrySkipIisCustomErrors = true; httpContext.ClearError(); if (!string.IsNullOrEmpty(redirectUrl)) { var mvcHandler = httpContext.CurrentHandler as MvcHandler; if (mvcHandler == null) { httpContext.Server.Transfer(redirectUrl); } else { var uriBuilder = new UriBuilder( httpContext.Request.Url.Scheme,httpContext.Request.Url.Host,httpContext.Request.Url.Port,httpContext.Request.ApplicationPath); uriBuilder.Path += redirectUrl; string path = httpContext.Server.UrlDecode(uriBuilder.Uri.PathAndQuery); HttpContext.Current.RewritePath(path,false); IHttpHandler httpHandler = new MvcHttpHandler(); httpHandler.ProcessRequest(HttpContext.Current); } } } } 对于任何反馈,我们都表示感谢.我目前正在使用的应用程序是一个ASP.NET MVC应用程序,但就像我提到的那样,它被编写为与MVC处理程序一起使用,但仅当CurrentHandler属于该类型时. 编辑:我忘了在这种情况下提到“hack”将是OnError()中的以下行: var imageRequestTypes = httpContext.Request.AcceptTypes.Where(a => a.StartsWith("image/")).Select(a => a.Count()); if (imageRequestTypes.Count() > 0) { httpContext.ClearError(); return; } 解决方法
最终,问题是由于不区分传统ASP.NET应用程序和ASP.NET MVC应用程序提供的不同类型的Context.通过提供检查来确定我正在处理的上下文类型,我能够做出相应的回应.
我为HttpTransfer和MvcTransfer添加了单独的方法,允许我重定向到错误页面,特别是在需要时.我也改变了逻辑,以便我可以轻松地在我的本地和开发机器上获得我的YSOD,而不会让处理程序吞噬异常. 除了用于将异常记录到数据库的代码(由TODO注释表示)之外,我们使用的最终代码是: using System; using System.Net; using System.Security.Principal; using System.Web; using System.Web.Configuration; using System.Web.Mvc; using Diagnostics; /// <summary> /// Provides a standardized mechanism for handling exceptions within a web application. /// </summary> public sealed class ErrorHandlerModule : IHttpModule { #region Public Methods /// <summary> /// Disposes of the resources (other than memory) used by the module that implements /// <see cref="T:System.Web.IHttpModule"/>. /// </summary> public void Dispose() { } /// <summary> /// Initializes a module and prepares it to handle requests. /// </summary> /// <param name="context"> /// An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods,and events /// common to all application objects within an ASP.NET application.</param> public void Init(HttpApplication context) { context.Error += OnError; } #endregion #region Private Static Methods /// <summary> /// Performs a Transfer for an MVC request. /// </summary> /// <param name="url">The URL to transfer to.</param> /// <param name="currentContext">The current context.</param> private static void HttpTransfer(string url,HttpContext currentContext) { currentContext.Server.TransferRequest(url); } /// <summary> /// Performs a Transfer for an MVC request. /// </summary> /// <param name="url">The URL to transfer to.</param> /// <param name="currentContext">The current context.</param> private static void MvcTransfer(string url,HttpContext currentContext) { var uriBuilder = new UriBuilder( currentContext.Request.Url.Scheme,currentContext.Request.Url.Host,currentContext.Request.Url.Port,currentContext.Request.ApplicationPath); uriBuilder.Path += url; string path = currentContext.Server.UrlDecode(uriBuilder.Uri.PathAndQuery); HttpContext.Current.RewritePath(path,false); IHttpHandler httpHandler = new MvcHttpHandler(); httpHandler.ProcessRequest(HttpContext.Current); } #endregion #region Private Methods /// <summary> /// Called when an error occurs within the application. /// </summary> /// <param name="source">The source.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private static void OnError(object source,EventArgs e) { var httpContext = HttpContext.Current; var lastException = HttpContext.Current.Server.GetLastError().GetBaseException(); var httpException = lastException as HttpException; var statusCode = (int)HttpStatusCode.InternalServerError; if (httpException != null) { if (httpException.Message == "File does not exist.") { httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; httpContext.ClearError(); return; } statusCode = httpException.GetHttpCode(); } if ((statusCode != (int)HttpStatusCode.NotFound) && (statusCode != (int)HttpStatusCode.ServiceUnavailable)) { // TODO : Your error logging code here. } var redirectUrl = string.Empty; if (!httpContext.IsCustomErrorEnabled) { return; } var errorsSection = WebConfigurationManager.GetSection("system.web/customErrors") as CustomErrorsSection; if (errorsSection != null) { redirectUrl = errorsSection.DefaultRedirect; if (httpException != null && errorsSection.Errors.Count > 0) { var item = errorsSection.Errors[statusCode.ToString()]; if (item != null) { redirectUrl = item.Redirect; } } } httpContext.Response.Clear(); httpContext.Response.StatusCode = statusCode; httpContext.Response.TrySkipIisCustomErrors = true; httpContext.ClearError(); if (!string.IsNullOrEmpty(redirectUrl)) { var mvcHandler = httpContext.CurrentHandler as MvcHandler; if (mvcHandler == null) { try { HttpTransfer(redirectUrl,httpContext); } catch (InvalidOperationException) { MvcTransfer(redirectUrl,httpContext); } } else { MvcTransfer(redirectUrl,httpContext); } } } #endregion } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 在两个ASP.NET应用程序之间共享会话,其中一个嵌套在另一个A
- 在ASP.NET中查找重定向的原因?
- asp.net-core – 如何将POCO控制器作为控制器发现?
- Shadow Copying导致ASP.NET应用启动很慢的解决办法
- asp.net(c#)动态修改webservice的地址和端口(动态修改配置
- asp.net-mvc – ASP.NET MVC:部分知道它是否是从另一个页面
- asp.net – SignalR不再工作“找不到包含OwinStartupAttrib
- asp.net-mvc – 处理.NET MVC 2动作过滤器时的执行顺序是什
- ASP.NET – 使用WCF Web服务绑定w / AD组的IIS7部署错误500
- asp-classic – 经典ASP中500 Vs 500.100错误
- asp.net-mvc-4 – 使用信号器一对一,包括离线模式
- asp.net – 如何调用我的WCF服务构造函数?
- asp.net – UpdatePanel和ClientIDMode =“静态”
- ASP.NET Core应用中如何记录和查看日志
- asp.net – 如何从网络外部的外部站点允许内部MV
- asp.net-mvc-4 – WebAPI如何指定控制器将到达哪
- asp.net – 删除了css类还有效果
- asp.net – 如何为Bootstrap按钮创建Button_Clic
- asp.net – WebForm_DoPostBackWithOptions没有使
- asp.net-mvc-3 – 如何在MVC3中为iframe的src属性