我有一個HttpModule,我通過將幾個不同的源代碼聯機在一起放到一起(大部分)與傳統ASP.NET應用程序一起使用,以及ASP.NET MVC應用。其中最大的部分來自CodePlex上的kigg項目。我的問題是在處理404錯誤,由於缺少圖像。在下面的代碼中,我不得不通過HttpContext的Request對象中的AcceptedTypes集合顯式查找請求的圖像。如果我沒有放入此檢查,即使是丟失的圖像也會導致重定向到Web.config中我的部分中定義的404頁面。用於錯誤處理和丟失圖像的HttpModule
這種方法的問題是(超出它聞起來的事實)是,這只是圖像。我基本上必須做到這一點,每一個可以想象的內容類型,我不希望這種重定向行爲發生。
看看下面的代碼,有人可以推薦某種重構,可以允許它對非頁面請求更寬鬆嗎?我仍然希望他們在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屬於該類型時才適用。
編輯:我忘了提及的「黑客」,在這種情況下將是的OnError(以下線):
var imageRequestTypes =
httpContext.Request.AcceptTypes.Where(a => a.StartsWith("image/")).Select(a => a.Count());
if (imageRequestTypes.Count() > 0)
{
httpContext.ClearError();
return;
}
而不是建立自己的錯誤存入模塊,您是否考慮過使用其中一個現有的錯誤日誌記錄庫,例如ELMAH(http://code.google.com/p/elmah/)或ASP.NET Health Monitoring(http://msdn.microsoft.com/ EN-US /庫/ ms998306.aspx)? ELMAH有一個豐富的錯誤過濾API,如果需要,您可以在Web.config中或通過代碼聲明性地指定它。 – 2009-10-10 23:27:23
斯科特,我絕對考慮過它,並在過去使用過ELMAH。這比其他任何事都更像是一種編碼練習。 – 2009-10-23 16:51:55