Страница пользовательской ошибки ASP.NET MVC 5
Я использую специальный атрибут authorize в приложении ASP.NET MVC 5, например:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
if (context.HttpContext.Request.IsAuthenticated)
{
context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
}
else
{
base.HandleUnauthorizedRequest(context);
}
}
}
В разделе system.web
моего web.config я упомянул пути ошибок, например:
<system.web>
<customErrors mode="On" defaultRedirect="/Error/Error">
<error statusCode="403" redirect="/Error/NoPermissions"/>
</customErrors>
</system.web>
Но я никогда не перенаправляюсь на страницу пользовательских ошибок в /Error/NoPermissions
. Вместо этого браузер отображает общую страницу с сообщением об ошибке "HTTP Error 403.0 - Forbidden" .
Ответы
Ответ 1
Спасибо всем, но проблема не в коде 403. На самом деле проблема была в том, как я пытался вернуть 403. Я только что изменил свой код, чтобы выбросить HttpException
вместо возврата HttpStatusCodeResult
, и теперь все работает. Я могу вернуть любой код состояния HTTP, выбрасывая исключение HttpException
, а моя конфигурация customErrors
улавливает все из них. Может быть, HttpStatusCodeResult
не выполняет точного задания, которое я ожидал от него.
Я только что заменил
context.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
с
throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "Forbidden");
Что это.
Счастливое кодирование.
Ответ 2
[1]: удалить все "customErrors" и "httpErrors" из Web.config
[2]: Проверить 'App_Start/FilterConfig.cs' выглядит так:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
[3]: в 'Global.asax' добавьте этот метод:
public void Application_Error(Object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Server.ClearError();
var routeData = new RouteData();
routeData.Values.Add("controller", "ErrorPage");
routeData.Values.Add("action", "Error");
routeData.Values.Add("exception", exception);
if (exception.GetType() == typeof(HttpException))
{
routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
}
else
{
routeData.Values.Add("statusCode", 500);
}
Response.TrySkipIisCustomErrors = true;
IController controller = new ErrorPageController();
controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
Response.End();
}
[4]: Добавить 'Controllers/ErrorPageController.cs'
public class ErrorPageController : Controller
{
public ActionResult Error(int statusCode, Exception exception)
{
Response.StatusCode = statusCode;
ViewBag.StatusCode = statusCode + " Error";
return View();
}
}
[5]: в разделе "Просмотры/Общие/Ошибка .cshtml"
@model System.Web.Mvc.HandleErrorInfo
@{
ViewBag.Title = (!String.IsNullOrEmpty(ViewBag.StatusCode)) ? ViewBag.StatusCode : "500 Error";
}
<h1 class="error">@(!String.IsNullOrEmpty(ViewBag.StatusCode) ? ViewBag.StatusCode : "500 Error"):</h1>
//@Model.ActionName
//@Model.ControllerName
//@Model.Exception.Message
//@Model.Exception.StackTrace
: D
Ответ 3
У меня также была эта проблема. Код в вопросе OPs отлично работает, кроме настраиваемого кода ошибки в разделе <system.web>
в файле web.config
. Чтобы исправить проблему, мне нужно добавить следующий код в <system.webServer>
. Обратите внимание, что ‘webserver’
вместо ‘web’
.
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>
Если кто-то использует следующую среду, вот полное решение:
Среда:
- Обновление Visual Studio 2013 4
- Microsoft.NET Framework 4.5.1 с ASP.NET MVC 5
- Проект: веб-приложение ASP.NET с MVC и аутентификация: индивидуальный шаблон учетной записи пользователя
Пользовательский класс атрибута:
Добавьте следующий класс в пространство имен по умолчанию для веб-сайтов. Причина, объясняемая здесь в принятом ответе Вопрос о переполнении стека: Почему AuthorizeAttribute перенаправляет на страницу входа для проверки подлинности и авторизации?
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}
Затем добавьте следующий код web.config
file
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="403" />
<error statusCode="403" responseMode="ExecuteURL" path="/Error/UnAuthorized" />
</httpErrors>
</system.webServer>
В следующей статье объясните подробнее об этом: ASP.NET MVC: Улучшение атрибута авторизации (403 Запрещено)
И httpErrors в разделе web.config в этой статье: Демистификация страниц ASP.NET MVC 5 и журнала ошибок
Затем добавьте папку ErrorController.cs в папку контроллеров
public class ErrorController : Controller
{
// GET: UnAuthorized
public ActionResult UnAuthorized()
{
return View();
}
public ActionResult Error()
{
return View();
}
}
Затем добавьте UnAuthorized.cshtml в папку View/Shared
@{
ViewBag.Title = "Your Request Unauthorized !"; //Customise as required
}
<h2>@ViewBag.Title.</h2>
Это покажет страницу с измененной ошибкой вместо страницы с ошибкой, созданной браузером.
Также обратите внимание, что для указанной выше среды не требуется комментировать код внутри метода RegisterGlobalFilters
, добавленный шаблоном, как предлагается в одном из ответов.
Обратите внимание, что я просто вырезал и вставлял код из моего рабочего проекта, поэтому я использовал Unauthorized
вместо OPs NoPermissions
в приведенном выше коде.
Ответ 4
так как я столкнулся с очень похожим вопросом, я хотел пролить больше света на него.
customErrors будет захватывать только фактические исключения для HTTP, созданные в вашем приложении ASP.NET. Однако HttpStatusCodeResult не генерирует исключение. Он просто пишет ответ с соответствующим кодом состояния, что имеет больше смысла в вашем примере.
Если вы работаете в IIS 7.0 или выше, вы должны теперь использовать httpErrors, так как во всех случаях будут отображаться страницы пользовательских ошибок. Это настройка уровня IIS.
Я написал целую запись в блоге об этом, чтобы объяснить различия:
http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging
Ответ 5
Обновление
Вам нужно только сделать это специальное перенаправление для 403 ошибок. Все остальные 500 ошибок должны вступить в силу через настройку defaultRedirect="/Error/Error"
в customErrors
. Однако вам нужно удалить или прокомментировать регистрацию HandleErrorAttribute в файле App_Start/FilterConfig.cs, чтобы пользовательские ошибки действительно работали. В противном случае этот атрибут перенаправляет все ошибки в файл Error.cshtml в каталоге Views/Shared.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
// remove this line below
//filters.Add(new HandleErrorAttribute());
}
}
Оригинальный ответ
Насколько я знаю, вы не можете использовать customErrors в web.config для обработки 403 ошибок по какой-либо причине. Я чувствую вашу боль, поскольку это похоже на то, что должно быть таким же простым, как и код, который у вас уже есть, но, видимо, 403 ошибки рассматриваются как проблема с веб-сервером.
Вместо этого вы можете просто перенаправить пользователя на нужную страницу "NoPermissions" следующим образом:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
if (context.HttpContext.Request.IsAuthenticated)
{
context.Result = new RedirectToRouteResult(new RouteValueDictionary(new
{
action = "NoPermissions",
controller = "Error",
area = ""
}));
}
else
{
base.HandleUnauthorizedRequest(context);
}
}
}
Запрос будет иметь код состояния 200 вместо 403, но если вы можете жить с этим, это будет непростым решением.
Вот аналогичный вопрос SO для получения дополнительной информации: Возврат пользовательских ошибок.
Кроме того, в этой статье объясняется, как перейти на маршрут IIS: http://kitsula.com/Article/MVC-Custom-Error-Pages