Do sự phụ thuộc vào Server.Transfer
có vẻ như việc thực hiện nội bộ của ResponseRewrite
không tương thích với MVC.
Điều này có vẻ như một lỗ chức năng rõ ràng với tôi, vì vậy tôi quyết định triển khai lại tính năng này bằng mô-đun HTTP, để nó hoạt động. Giải pháp dưới đây cho phép bạn xử lý lỗi bằng cách chuyển hướng đến bất kỳ tuyến đường MVC hợp lệ nào (bao gồm cả tệp vật lý) giống như bạn thường làm.
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="404.aspx" />
<error statusCode="500" redirect="~/MVCErrorPage" />
</customErrors>
Điều này đã được thử nghiệm trên các nền tảng sau;
- MVC4 tại Integrated Pipeline Mode (IIS nhanh 8)
- MVC4 ở chế độ Cổ điển (VS Phát triển Server, Cassini)
- MVC4 trong Classic Mode (IIS6)
namespace Foo.Bar.Modules {
/// <summary>
/// Enables support for CustomErrors ResponseRewrite mode in MVC.
/// </summary>
public class ErrorHandler : IHttpModule {
private HttpContext HttpContext { get { return HttpContext.Current; } }
private CustomErrorsSection CustomErrors { get; set; }
public void Init(HttpApplication application) {
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
CustomErrors = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");
application.EndRequest += Application_EndRequest;
}
protected void Application_EndRequest(object sender, EventArgs e) {
// only handle rewrite mode, ignore redirect configuration (if it ain't broke don't re-implement it)
if (CustomErrors.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite && HttpContext.IsCustomErrorEnabled) {
int statusCode = HttpContext.Response.StatusCode;
// if this request has thrown an exception then find the real status code
Exception exception = HttpContext.Error;
if (exception != null) {
// set default error status code for application exceptions
statusCode = (int)HttpStatusCode.InternalServerError;
}
HttpException httpException = exception as HttpException;
if (httpException != null) {
statusCode = httpException.GetHttpCode();
}
if ((HttpStatusCode)statusCode != HttpStatusCode.OK) {
Dictionary<int, string> errorPaths = new Dictionary<int, string>();
foreach (CustomError error in CustomErrors.Errors) {
errorPaths.Add(error.StatusCode, error.Redirect);
}
// find a custom error path for this status code
if (errorPaths.Keys.Contains(statusCode)) {
string url = errorPaths[statusCode];
// avoid circular redirects
if (!HttpContext.Request.Url.AbsolutePath.Equals(VirtualPathUtility.ToAbsolute(url))) {
HttpContext.Response.Clear();
HttpContext.Response.TrySkipIisCustomErrors = true;
HttpContext.Server.ClearError();
// do the redirect here
if (HttpRuntime.UsingIntegratedPipeline) {
HttpContext.Server.TransferRequest(url, true);
}
else {
HttpContext.RewritePath(url, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(HttpContext);
}
// return the original status code to the client
// (this won't work in integrated pipleline mode)
HttpContext.Response.StatusCode = statusCode;
}
}
}
}
}
public void Dispose() {
}
}
}
Cách sử dụng
Bao gồm điều này làm mô-đun HTTP cuối cùng trong web.config
<system.web>
<httpModules>
<add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
</httpModules>
</system.web>
<!-- IIS7+ -->
<system.webServer>
<modules>
<add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
</modules>
</system.webServer>
Nguồn
2015-03-31 09:18:37
Có, bạn đúng. Trong trường hợp của tôi, tôi không thể tìm thấy lỗi, vì vậy tôi đi an toàn với một HTML tĩnh. –