In a old site, I was changing the way that CustomErrors works by adding redirectMode="ResponseRewrite"
(new in 3.5 SP1):
在一个旧的站点中,我通过添加redirectMode=“ResponseRewrite”(在3.5 SP1中新增)改变了CustomErrors的工作方式:
<customErrors mode="RemoteOnly" defaultRedirect="Error.aspx" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="404.aspx" />
</customErrors>
The thing is: it shows me the generic error page (the one that you get when you don't set customErrors
. If I remove theredirectMode="ResponseRewrite"
part, it works fine.
问题是:它向我显示了通用错误页面(在不设置customerror时得到的页面)。如果我移除它的directmode ="ResponseRewrite"部分,它会工作得很好。
I'm sure 3.5 SP1 is installed in the server, because I use the same setting on other sites hosted in the same server.
我确信3.5 SP1已经安装在服务器上,因为我在同一服务器上的其他站点上使用相同的设置。
Any ideas?
什么好主意吗?
9 个解决方案
#1
92
It is important to note for anyone trying to do this in an MVC application that ResponseRewrite
uses Server.Transfer
behind the scenes. Therefore, the defaultRedirect
must correspond to a legitimate file on the file system. Apparently, Server.Transfer
is not compatible with MVC routes, therefore, if your error page is served by a controller action, Server.Transfer
is going to look for /Error/Whatever, not find it on the file system, and return a generic 404 error page!
对于任何试图在ResponseRewrite使用服务器的MVC应用程序中这样做的人来说,有一点很重要。转移在幕后。因此,defaultRedirect必须对应于文件系统上的合法文件。显然,服务器。传输与MVC路由不兼容,因此,如果您的错误页面是由控制器操作服务器提供的。传输将查找/Error/什么的,在文件系统上找不到它,并返回一个通用的404错误页面!
#2
41
The only way that worked perfectly for me is to turn off custom errors and replace iis's error pages via web.config. It sends the correct status code with the response and has the benefit of not going through the mvc.
对我来说,唯一能完美工作的方法是关闭自定义错误,并通过web.config替换iis的错误页面。它用响应发送正确的状态代码,并且好处是不通过mvc。
here's the code
这是代码
-
Turn off custom errors
关闭自定义错误
<customErrors mode="Off" />
-
Replace error pages
取代错误页面
<httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="404" subStatusCode="-1" /> <remove statusCode="500" subStatusCode="-1" /> <error statusCode="404" path="Error404.html" responseMode="File" /> <error statusCode="500" path="Error.html" responseMode="File" /> </httpErrors>
Note. Use responsemode="file"
if the url is a direct link to a file
请注意。如果url是文件的直接链接,则使用responsemode="file"
info : http://tipila.com/tips/use-custom-error-pages-aspnet-mvc
信息:http://tipila.com/tips/use-custom-error-pages-aspnet-mvc。
#3
19
What's happening is IIS is seing the error status code and presenting it's own error page instead of yours. To solve you need to set this in the code behind page of your error page to prevent IIS from doing this:
正在发生的是,IIS正在处理错误状态代码并显示它自己的错误页面,而不是您的。要解决这个问题,需要在错误页面的后面的代码中设置这个,以防止IIS这样做:
Response.TrySkipIisCustomErrors = true;
This will only work in IIS7 or above, for earlier versions of IIS you'll need to play with the error page settings.
这只适用于IIS7或以上版本,对于早期版本的IIS,您需要使用错误页面设置。
#4
10
Due to the reliance on Server.Transfer
it seems that the internal implementation of ResponseRewrite
isn't compatible with MVC.
由于对服务器的依赖。ResponseRewrite的内部实现似乎与MVC不兼容。
This seems like a glaring functionality hole to me, so I decided to re-implement this feature using a HTTP module, so that it just works. The solution below allows you to handle errors by redirecting to any valid MVC route (including physical files) just as you would do normally.
这对我来说似乎是一个明显的功能漏洞,所以我决定使用HTTP模块重新实现这个特性,这样它就可以正常工作了。下面的解决方案允许您像往常一样重定向到任何有效的MVC路由(包括物理文件)来处理错误。
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="404.aspx" />
<error statusCode="500" redirect="~/MVCErrorPage" />
</customErrors>
This has been tested on the following platforms;
在以下平台上进行了测试;
- MVC4 in Integrated Pipeline Mode (IIS Express 8)
- MVC4集成管道模式(IIS Express 8)
- MVC4 in Classic Mode (VS Development Server, Cassini)
- 经典模式下的MVC4 (VS开发服务器,卡西尼)
- MVC4 in Classic Mode (IIS6)
- MVC4经典模式(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() {
}
}
}
Usage
使用
Include this as the final HTTP module in your web.config
将其作为web.config中的最后一个HTTP模块
<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>
#5
9
I know this question is a bit old, but I thought I should point out that it doesn't need to be a static file to get this working.
我知道这个问题有点过时了,但我想我应该指出,要使这个问题工作,不需要使用静态文件。
I ran into a similar thing, and it's just a matter of finding that error in your Error.aspx, in our case it was because the masterpage in use relied on a piece of session data and when ResponseRewrite was set the session is not available to our Error.aspx page.
我遇到了类似的事情,这只是找到错误的问题。aspx,在我们的例子中,这是因为使用的母版依赖于会话数据,当ResponseRewrite被设置时,会话对我们的错误无效。aspx页面。
I haven't worked out yet whether this unavailability of session is due to our specific app config or a "by design" part of ASP.net.
我还没有弄清楚这个会话的不可用性是由于我们特定的应用程序配置还是ASP.net的“按设计”部分。
#6
1
I found that the problem was in Error.aspx. Still can't find what was the actual error in error.aspx that causes the problem.
我发现问题出在Error.aspx。还是找不到误差的实际误差。导致问题的aspx。
Changing the page to a static html file solved the problem.
将页面更改为静态html文件解决了这个问题。
#7
1
I built an error page in aspx that transfers the query to an ASP.NET MVC controller. You can rewrite the query to this aspx page and it will transfer the query to your custom controller.
我在aspx中构建了一个错误页面,该页面将查询传输到ASP。净MVC控制器。您可以将查询重写到这个aspx页面,它将把查询转移到您的自定义控制器。
protected void Page_Load(object sender, EventArgs e)
{
//Get status code
var queryStatusCode = Request.QueryString.Get("code");
int statusCode;
if (!int.TryParse(queryStatusCode, out statusCode))
{
var lastError = Server.GetLastError();
HttpException ex = lastError as HttpException;
statusCode = ex == null ? 500 : ex.GetHttpCode();
}
Response.StatusCode = statusCode;
// Execute a route
RouteData routeData = new RouteData();
string controllerName = Request.QueryString.Get("controller") ?? "Errors";
routeData.Values.Add("controller", controllerName);
routeData.Values.Add("action", Request.QueryString.Get("action") ?? "Index");
var requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(requestContext, controllerName);
controller.Execute(requestContext);
}
Find more details here : https://*.com/a/27354140/143503
在这里找到更多细节:https://*.com/a/27354140/143503
#8
0
In my particular case, my error page had a master page that had a user control that tried to use Session. If Session isn't available, you get an HttpException: "Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive." Easiest fix is to switch to static html, second easiest fix is to use a simpler error page, hardest fix is to make incredibly sure that your error page makes no assumptions anywhere (like that Session won't throw an exception, for example) and can't possibly error out.
在我的特定情况下,我的错误页面有一个试图使用会话的用户控件的主页面。如果会话不可用,您将得到一个HttpException:“会话状态只能在enableSessionState被设置为true时使用,无论是在配置文件中还是在页面指令中。”最简单的解决方法是切换到静态html,第二个最简单的解决方法是使用一个更简单的错误页面,最困难的解决方法是确保您的错误页面在任何地方都没有任何假设(例如,会话不会抛出异常),并且不可能出错。
#9
0
I have found out that if you use redirectMode="ResponseRewrite" then you need to add something in the rewrite area of the web.config file. Problem is when your site is broken! You can't URL rewrite as your site can't call the "virtual.aspx" that handles your rewrite!
我发现,如果使用redirectMode=“ResponseRewrite”,那么您需要在web的重写区域中添加一些东西。配置文件。问题是当你的网站被破坏的时候!您不能重写URL,因为您的站点不能调用“virtual”。aspx“处理你的重写!
#1
92
It is important to note for anyone trying to do this in an MVC application that ResponseRewrite
uses Server.Transfer
behind the scenes. Therefore, the defaultRedirect
must correspond to a legitimate file on the file system. Apparently, Server.Transfer
is not compatible with MVC routes, therefore, if your error page is served by a controller action, Server.Transfer
is going to look for /Error/Whatever, not find it on the file system, and return a generic 404 error page!
对于任何试图在ResponseRewrite使用服务器的MVC应用程序中这样做的人来说,有一点很重要。转移在幕后。因此,defaultRedirect必须对应于文件系统上的合法文件。显然,服务器。传输与MVC路由不兼容,因此,如果您的错误页面是由控制器操作服务器提供的。传输将查找/Error/什么的,在文件系统上找不到它,并返回一个通用的404错误页面!
#2
41
The only way that worked perfectly for me is to turn off custom errors and replace iis's error pages via web.config. It sends the correct status code with the response and has the benefit of not going through the mvc.
对我来说,唯一能完美工作的方法是关闭自定义错误,并通过web.config替换iis的错误页面。它用响应发送正确的状态代码,并且好处是不通过mvc。
here's the code
这是代码
-
Turn off custom errors
关闭自定义错误
<customErrors mode="Off" />
-
Replace error pages
取代错误页面
<httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="404" subStatusCode="-1" /> <remove statusCode="500" subStatusCode="-1" /> <error statusCode="404" path="Error404.html" responseMode="File" /> <error statusCode="500" path="Error.html" responseMode="File" /> </httpErrors>
Note. Use responsemode="file"
if the url is a direct link to a file
请注意。如果url是文件的直接链接,则使用responsemode="file"
info : http://tipila.com/tips/use-custom-error-pages-aspnet-mvc
信息:http://tipila.com/tips/use-custom-error-pages-aspnet-mvc。
#3
19
What's happening is IIS is seing the error status code and presenting it's own error page instead of yours. To solve you need to set this in the code behind page of your error page to prevent IIS from doing this:
正在发生的是,IIS正在处理错误状态代码并显示它自己的错误页面,而不是您的。要解决这个问题,需要在错误页面的后面的代码中设置这个,以防止IIS这样做:
Response.TrySkipIisCustomErrors = true;
This will only work in IIS7 or above, for earlier versions of IIS you'll need to play with the error page settings.
这只适用于IIS7或以上版本,对于早期版本的IIS,您需要使用错误页面设置。
#4
10
Due to the reliance on Server.Transfer
it seems that the internal implementation of ResponseRewrite
isn't compatible with MVC.
由于对服务器的依赖。ResponseRewrite的内部实现似乎与MVC不兼容。
This seems like a glaring functionality hole to me, so I decided to re-implement this feature using a HTTP module, so that it just works. The solution below allows you to handle errors by redirecting to any valid MVC route (including physical files) just as you would do normally.
这对我来说似乎是一个明显的功能漏洞,所以我决定使用HTTP模块重新实现这个特性,这样它就可以正常工作了。下面的解决方案允许您像往常一样重定向到任何有效的MVC路由(包括物理文件)来处理错误。
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="404.aspx" />
<error statusCode="500" redirect="~/MVCErrorPage" />
</customErrors>
This has been tested on the following platforms;
在以下平台上进行了测试;
- MVC4 in Integrated Pipeline Mode (IIS Express 8)
- MVC4集成管道模式(IIS Express 8)
- MVC4 in Classic Mode (VS Development Server, Cassini)
- 经典模式下的MVC4 (VS开发服务器,卡西尼)
- MVC4 in Classic Mode (IIS6)
- MVC4经典模式(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() {
}
}
}
Usage
使用
Include this as the final HTTP module in your web.config
将其作为web.config中的最后一个HTTP模块
<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>
#5
9
I know this question is a bit old, but I thought I should point out that it doesn't need to be a static file to get this working.
我知道这个问题有点过时了,但我想我应该指出,要使这个问题工作,不需要使用静态文件。
I ran into a similar thing, and it's just a matter of finding that error in your Error.aspx, in our case it was because the masterpage in use relied on a piece of session data and when ResponseRewrite was set the session is not available to our Error.aspx page.
我遇到了类似的事情,这只是找到错误的问题。aspx,在我们的例子中,这是因为使用的母版依赖于会话数据,当ResponseRewrite被设置时,会话对我们的错误无效。aspx页面。
I haven't worked out yet whether this unavailability of session is due to our specific app config or a "by design" part of ASP.net.
我还没有弄清楚这个会话的不可用性是由于我们特定的应用程序配置还是ASP.net的“按设计”部分。
#6
1
I found that the problem was in Error.aspx. Still can't find what was the actual error in error.aspx that causes the problem.
我发现问题出在Error.aspx。还是找不到误差的实际误差。导致问题的aspx。
Changing the page to a static html file solved the problem.
将页面更改为静态html文件解决了这个问题。
#7
1
I built an error page in aspx that transfers the query to an ASP.NET MVC controller. You can rewrite the query to this aspx page and it will transfer the query to your custom controller.
我在aspx中构建了一个错误页面,该页面将查询传输到ASP。净MVC控制器。您可以将查询重写到这个aspx页面,它将把查询转移到您的自定义控制器。
protected void Page_Load(object sender, EventArgs e)
{
//Get status code
var queryStatusCode = Request.QueryString.Get("code");
int statusCode;
if (!int.TryParse(queryStatusCode, out statusCode))
{
var lastError = Server.GetLastError();
HttpException ex = lastError as HttpException;
statusCode = ex == null ? 500 : ex.GetHttpCode();
}
Response.StatusCode = statusCode;
// Execute a route
RouteData routeData = new RouteData();
string controllerName = Request.QueryString.Get("controller") ?? "Errors";
routeData.Values.Add("controller", controllerName);
routeData.Values.Add("action", Request.QueryString.Get("action") ?? "Index");
var requestContext = new RequestContext(new HttpContextWrapper(Context), routeData);
IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(requestContext, controllerName);
controller.Execute(requestContext);
}
Find more details here : https://*.com/a/27354140/143503
在这里找到更多细节:https://*.com/a/27354140/143503
#8
0
In my particular case, my error page had a master page that had a user control that tried to use Session. If Session isn't available, you get an HttpException: "Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive." Easiest fix is to switch to static html, second easiest fix is to use a simpler error page, hardest fix is to make incredibly sure that your error page makes no assumptions anywhere (like that Session won't throw an exception, for example) and can't possibly error out.
在我的特定情况下,我的错误页面有一个试图使用会话的用户控件的主页面。如果会话不可用,您将得到一个HttpException:“会话状态只能在enableSessionState被设置为true时使用,无论是在配置文件中还是在页面指令中。”最简单的解决方法是切换到静态html,第二个最简单的解决方法是使用一个更简单的错误页面,最困难的解决方法是确保您的错误页面在任何地方都没有任何假设(例如,会话不会抛出异常),并且不可能出错。
#9
0
I have found out that if you use redirectMode="ResponseRewrite" then you need to add something in the rewrite area of the web.config file. Problem is when your site is broken! You can't URL rewrite as your site can't call the "virtual.aspx" that handles your rewrite!
我发现,如果使用redirectMode=“ResponseRewrite”,那么您需要在web的重写区域中添加一些东西。配置文件。问题是当你的网站被破坏的时候!您不能重写URL,因为您的站点不能调用“virtual”。aspx“处理你的重写!