Где я могу уловить и обработать maxAllowedContentLength, превышенную в IIS7?
У меня есть страница aspx, где Im позволяет пользователю загружать файл, и я хочу ограничить максимальный размер загрузки файлов размером 10 МБ. IIS7,.NET 3.5. В моем файле web.config у меня есть следующее:
<location path="foo.aspx">
<system.web>
<!-- maxRequestLength: kbytes, executionTimeout:seconds -->
<httpRuntime maxRequestLength="10240" executionTimeout="120" />
<authorization>
<allow roles="customRole"/>
<!-- Deny everyone else -->
<deny users="*"/>
</authorization>
</system.web>
<system.webServer>
<security>
<requestFiltering>
<!-- maxAllowedContentLength: bytes -->
<requestLimits maxAllowedContentLength="10240000"/>
</requestFiltering>
</security>
<handlers accessPolicy="Read, Script">
<add name="foo" path="foo.aspx" verb="POST"
type="System.Web.UI.PageHandlerFactory"
preCondition="integratedMode" />
</handlers>
</system.webServer>
</location>
У меня есть настраиваемый модуль обработки ошибок, который реализует IHttpModule
. Ive обнаружил, что когда maxRequestLength
превышено, HttpApplication.Error
действительно поднимается. Однако, когда я играю с maxAllowedContentLength
, событие HttpApplication.Error
не поднимается, и пользователь перенаправляется на страницу 404.13. Я подключился к Visual Studio с первым шансом, что ничто не забрасывается.
Моя первая мысль - проверить длину содержимого заголовка в более раннем событии - есть ли рекомендации/лучшие практики, где я это делаю? PostLogRequest? EndRequest?
Ответы
Ответ 1
Посмотрев на Обзор жизненного цикла приложения ASP.NET для IIS 7.0 и сделав собственные эксперименты, я предполагаю, что проверка запроса выполняется внутри IIS до того, как какое-либо из событий будет поднято.
Похоже, что после внутренней проверки с этой ошибкой возникают только значения LogRequest, PostLogRequest, EndRequest, PreSendRequestContent и PreSendRequestHeaders.
Я решил подключить обработчик событий к событию HttpApplication.EndRequest
в моем настраиваемом обработчике ошибок и проверить код статуса 404.13 на POST и обработать, поскольку мне нужно, чтобы он обрабатывался, что в моем случае - перенаправление на вызывающую страницу, которая проверит Server.GetLastError()
и покажет дружественную ошибку конечному пользователю.
private void application_EndRequest(object sender, EventArgs e)
{
HttpRequest request = HttpContext.Current.Request;
HttpResponse response = HttpContext.Current.Response;
if ((request.HttpMethod == "POST") &&
(response.StatusCode == 404 && response.SubStatusCode == 13))
{
// Clear the response header but do not clear errors and
// transfer back to requesting page to handle error
response.ClearHeaders();
HttpContext.Current.Server.Transfer(
request.AppRelativeCurrentExecutionFilePath);
}
}
Я бы приветствовал отзывы об этом подходе и альтернативах.
Ответ 2
Самый простой способ - обработать его в методе OnError самой страницы.
Я думаю, что это работает только в .NET 4.0, так как свойство WebEventCode зарегистрировано как NEW в .NET 4.0.
protected override void OnError(EventArgs e)
{
Exception err = Server.GetLastError();
if (err is HttpException)
{
if ((err as HttpException).WebEventCode == 3004)
{
Context.Items["error"] = "File exceeded maximum allowed length.";
Server.Transfer( Context.Request.Url.LocalPath );
return;
}
}
base.OnError(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsPostBack)
{
string error = Context.Items["error"] as string;
if (!string.IsNullOrEmpty( error ))
showErrorMessage( error );
}
}
Что я сделал:
- получить последнюю ошибку с Server.GetLastError
- проверьте, что это "Максимальная длина запроса превышена". error (WebEventCode == 3004).
- добавлено значение в коллекции Context.Items, чтобы отметить запрос как ошибку.
- передать запрос обратно на страницу с помощью Server.Transfer(Context.Request.Url.LocalPath)
- страница Метод OnLoad проверяет флаг ошибки и отображает сообщение, если присутствует
Это гарантирует, что ошибка полностью обрабатывается на запрошенной странице, и страница способна сообщать об ошибках.
Также обратите внимание, что, хотя браузер в конечном итоге получит правильный ответ, браузер может занять свое время, загружая весь запрос, прежде чем обрабатывать ответ сервера и отображает его. Такое поведение, вероятно, определяется как часть взаимодействия между сервером и браузером в протоколе HTTP, поэтому, вероятно, не так много можно сделать по этому поводу.