问题是:为什么自定义错误处理不适用于不存在的路径/目录?
更新了固定代码(感谢大家为您输入):
*更新了web.config和global.asax的代码 *
<httpErrors errorMode="Custom">
<remove statusCode="500" subStatusCode="-1" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL" />
<error statusCode="500" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL"/>
</httpErrors>
added this to the global.asax to stop IIS from handling my 500 errors
after @Kev's suggestions IIS handled my 500's these lines fixed that
HttpApplication myApplication = new HttpApplication();
myApplication.Response.TrySkipIisCustomErrors = true;
我们在web.config
和global.asax
中设置了自定义错误处理的网站设置(设置如下所示)。我们能够毫无问题地处理所有404和500。错误被Application_Error
中的global.asax
捕获,记录到数据库然后使用HttpContext
我们设置状态代码并使用Server.Transfer()
将用户移动到相应的错误页面(重定向导致302,并伤害搜索引擎优化)。
问题是当用户输入http://www.example.com/whatever
时,在Firefox中显示空白页面,在IE中显示IE 404页面。 Firebug没有显示被触发的状态代码,当我调试解决方案时,我设置的断点没有被global.asax
命中。奇怪的是,用户可以输入http://www.example.com/whatever/hmm.aspx
并且会遇到错误。它似乎只适用于不存在的页面而不是不存在的路径/目录。
以下是错误的web.config
代码和应用程序错误的global.asax
代码。
我已添加 * *来隐藏信息,其中包含有效的.aspx
个页面:
网络配置:
<customErrors defaultRedirect="~/******.aspx" mode="On"
redirectMode="ResponseRewrite">
<error statusCode="500" redirect="~/*****.aspx" />
<error statusCode="404" redirect="~/*****.aspx" />
</customErrors>
<httpErrors errorMode="Custom">
<remove statusCode="500" subStatusCode="-1" />
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL" />
<error statusCode="500" subStatusCode="-1" prefixLanguageFilePath="" path="/*****.aspx" responseMode="ExecuteURL"/>
</httpErrors>
代码:
protected void Application_Error(Object sender, EventArgs e)
{
// At this point we have information about the error
HttpContext ctx = HttpContext.Current;
// set the exception to the Context
Exception exception = ctx.Server.GetLastError();
// get the status code of the Error
int httpCode = ((HttpException)exception).GetHttpCode();
// get the IP Address
String strHostName = string.Empty;
String ipAddress_s = string.Empty;
strHostName = System.Net.Dns.GetHostName();
System.Net.IPHostEntry ipEntry = System.Net.Dns.GetHostByName(strHostName);
System.Net.IPAddress[] addr = ipEntry.AddressList;
for (int i = 0; i < addr.Length; i++)
{
ipAddress_s += "IP Address {" + (i + 1) + "} " +
addr[i].ToString() + Environment.NewLine;
}
// setup the error info one for user display and one for the DB Insert
string errorInfo =
"<br /><b>Error Location:</b> " + ctx.Request.Url.ToString() +
"<br /><br /><b>Error Source:</b> " + exception.Source +
"<br /><br /><b>Error Try/Catch:</b> " + exception.InnerException +
"<br /><br /><b>Error Info:</b> " + exception.Message +
"<br /><br /><b>Status Code:</b> " + httpCode +
"<br /><br /><b>Stack trace:</b> " + exception.StackTrace;
string errorInfoDB =
"||Error Location: " + ctx.Request.Url.ToString() +
"||Error Source: " + exception.Source +
"||Error Try/Catch: " + exception.InnerException +
"||Error Info: " + exception.Message +
"||HttpErrorCode: " + httpCode +
"||Stack trace: " + exception.StackTrace +
"||IP Address: " + ipAddress_s;
// clean the input befor you put it in the DB
char quote = (char)34;
char filler = (char)124;
char tick = (char)39;
char greaterThan = (char)60;
char lessThan = (char)62;
errorInfo = errorInfo.Replace(quote, filler);
errorInfo = errorInfo.Replace(tick, filler);
errorInfo = errorInfo.Replace(greaterThan, filler);
errorInfo = errorInfo.Replace(lessThan, filler);
errorInfoDB = errorInfoDB.Replace(quote, filler);
errorInfoDB = errorInfoDB.Replace(tick, filler);
errorInfoDB = errorInfoDB.Replace(greaterThan, filler);
errorInfoDB = errorInfoDB.Replace(lessThan, filler);
string pattern = string.Empty;
string replacement = "sQueEl";
pattern = "/cookie|SELECT|UPDATE|INSERT|INTO|DELETE|FROM|NOT IN|WHERE|TABLE|DROP|script*/ig";
errorInfoDB = Regex.Replace(errorInfoDB, pattern, replacement);
pattern = "/cookie|select|update|insert|into|delete|from|not in|where|table|drop|script*/ig";
errorInfoDB = Regex.Replace(errorInfoDB, pattern, replacement);
if (httpCode == 404)
{
InSert_To_DB_Class(*****, *****, *****, *****, *****, errorInfoDB);
}
else
{
InSert_To_DB_Class(*****, *****, *****, *****, *****, errorInfoDB);
}
// set the error info to the session variable to display to the allowed users
Application["AppError"] = errorInfo;
// clear the error now that is has been stored to a session
ctx.Server.ClearError();
ctx.Response.ClearHeaders();
// set the status code so we can return it for SEO
ctx.Response.StatusCode = httpCode;
ctx.Response.TrySkipIisCustomErrors = true;
HttpApplication myApplication = new HttpApplication();
myApplication.Response.TrySkipIisCustomErrors = true;
try
{
if (ctx.Request.RawUrl.Contains("/*****"))
{
// redirect to the error page
ctx.Server.Transfer("~/*****.aspx", false);
}
else if(ctx.Request.RawUrl.Contains("/*****"))
{
ctx.Server.Transfer("~/*****/*****.aspx", false);
}
else
{
// check the httpCode
if (httpCode == 404)
{
// set the page name they were trying to find to a session variable
// this will be cleared in the ****** page
Application["404_page"] = exception.Message;
// redirect to the 404 page
ctx.Server.Transfer("~/*****", false);
}
else
{
// redirect to the error page
ctx.Server.Transfer("~/*****", false);
}
}
}
}
答案 0 :(得分:25)
从评论到失望先生:
谢谢,我正在使用IIS 7本地和IIS 7.5。当您找到材料时,请告诉我。
如果您的应用程序在配置为在Classic Pipeline模式下运行的应用程序池中运行,则不适用于ASP.NET的内容将不会访问ASP.NET运行时。即不存在的文件夹。这些将由IIS直接处理。
您有几个选择:
将应用程序池设置为Integrated Pipeline模式。如果IIS的错误处理从ASP.NET“”占用“ASP.NET 404和500状态代码,则可能还需要配置以下设置:
<configuration>
<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
如果应用程序在“集成管道”模式下表现不佳,但您只关心为404响应显示页面,请配置以下内容:
<system.webServer>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath=""
path="/404.aspx" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
您需要在页面中设置404
状态代码,否则它只会返回200
。
如果您使用静态页面,例如:
<error statusCode="404" prefixLanguageFilePath=""
path="404.html" responseMode="File" />
这将返回404
。
如果应用程序在“集成管道”模式下表现不佳并且您必须通过错误处理程序传递404错误,那么您可能必须手动将通配符内容映射到ASP.NET HttpHandler,以便此类请求执行此操作打了管道。这将是次优解决方案。
答案 1 :(得分:4)
IIS永远不会调用ASP.NET。 IIS处理页面请求,发现页面不存在,ASP.NET永远不会被加载。
如果您希望加载ASP.NET而不管文件是否存在,则需要更改IIS配置。您使用的是IIS6还是IIS7 / 7.5?
答案 2 :(得分:3)
您需要设置通配符映射,以便所有请求都通过.Net
如果你使用IIS6以下链接应该帮助你:
通配符脚本映射和IIS 7集成管道:
http://learn.iis.net/page.aspx/508/wildcard-script-mapping-and-iis-7-integrated-pipeline/
答案 3 :(得分:0)
我找不到相关的源材料,但我认为问题在于它正在处理自定义错误页面和不 路径。
你的调查显示你遇到了这个,因为:
www.mysite.com/nonexistingpath/nonexistingpage.aspx
这应该是正确的错误页面。以下不会:
www.mysite.com/nonexistingpath/
这种情况重申你已经回答了自己的问题,但我会看看能否找到参考资料。最终,它不是页面请求,因此没有通过适当的处理程序处理ISAPI。