Вопрос: почему пользовательская обработка ошибок не работает для несуществующих путей / каталогов?
Обновлено с исправленным кодом (спасибо всем за ваш вклад):
* Обновлен код для 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, и больно SEO).
Проблема в том, что когда пользователь вводит 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);
}
}
}
}