gpt4 book ai didi

asp.net - 用于错误处理和丢失图像的 HttpModule

转载 作者:行者123 更新时间:2023-12-04 19:23:50 24 4
gpt4 key购买 nike

我有一个 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 应用程序提供的不同类型的上下文引起的。通过提供检查来确定我正在处理的上下文类型,我能够做出相应的响应。

我为 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, properties, 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 - 用于错误处理和丢失图像的 HttpModule,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1447350/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com