6 ответов:
мы делаем это так; этот код находится в
BaseController/// <summary> /// returns our standard page not found view /// </summary> protected ViewResult PageNotFound() { Response.StatusCode = 404; return View("PageNotFound"); }называется так
public ActionResult ShowUserDetails(int? id) { // make sure we have a valid ID if (!id.HasValue) return PageNotFound();
HttpNotFoundResult является отличным первым шагом к тому, что я использую. Возврат HttpNotFoundResult-это хорошо. Тогда вопрос в том, что дальше?
Я создал фильтр действий с именем HandleNotFoundAttribute, который затем показывает страницу ошибки 404. Поскольку он возвращает представление, вы можете создать специальное представление 404 для каждого контроллера или использовать общее представление 404 по умолчанию. Это даже будет вызвано, когда контроллер не имеет указанного действия, потому что платформа бросает HttpException с кодом состояния 404.
public class HandleNotFoundAttribute : ActionFilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { var httpException = filterContext.Exception.GetBaseException() as HttpException; if (httpException != null && httpException.GetHttpCode() == (int)HttpStatusCode.NotFound) { filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; // Prevents IIS from intercepting the error and displaying its own content. filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.StatusCode = (int) HttpStatusCode.NotFound; filterContext.Result = new ViewResult { ViewName = "404", ViewData = filterContext.Controller.ViewData, TempData = filterContext.Controller.TempData }; } } }
используя ActionFilter и трудно поддерживать потому что всякий раз, когда мы выбрасываем ошибку, фильтр должен быть установлен в атрибуте. Что, если мы забудем его установить? Один из способов-получение
OnExceptionна базе контроллера. Вам нужно определить aBaseControllerполученные отControllerи все ваши контроллеры должны быть производными отBaseController. Лучше всего иметь базовый контроллер.Примечание при использовании
Exceptionкод состояния ответа 500, поэтому нам нужно изменить его на 404 не найдено и 401 несанкционированный. Так же, как я упоминал выше, используйтеOnExceptionпереопределяет наBaseControllerчтобы избежать использования атрибута фильтра.новый MVC 3 также делает более хлопотным, возвращая пустой вид в браузер. Лучшее решение после некоторых исследований основано на моем ответе здесь как вернуть представление для HttpNotFound () в ASP.Net MVC 3?
чтобы сделать более удобным я вставляю его здесь:
после некоторого изучения. Этот обходной путь для MVC 3 вот вывести все
HttpNotFoundResult,HttpUnauthorizedResult,HttpStatusCodeResultклассы и реализовать новая (перекрывая его)HttpNotFound() метод вBaseController.лучше всего использовать базовый контроллер, чтобы у вас был "контроль" над всеми производными контроллерами.
создать новый
HttpStatusCodeResultкласс, не производный отActionResultа отViewResultчтобы отобразить вид или любойViewнеобходимо указатьViewNameсобственность. Я следую за оригиналHttpStatusCodeResultустановитьHttpContext.Response.StatusCodeиHttpContext.Response.StatusDescriptionа тоbase.ExecuteResult(context)отобразит подходящий вид, потому что снова я получаю отViewResult. Достаточно просто, не так ли? Надеюсь, что это будет реализовано в ядре MVC.посмотреть мои
BaseControllerниже:using System.Web; using System.Web.Mvc; namespace YourNamespace.Controllers { public class BaseController : Controller { public BaseController() { ViewBag.MetaDescription = Settings.metaDescription; ViewBag.MetaKeywords = Settings.metaKeywords; } protected new HttpNotFoundResult HttpNotFound(string statusDescription = null) { return new HttpNotFoundResult(statusDescription); } protected HttpUnauthorizedResult HttpUnauthorized(string statusDescription = null) { return new HttpUnauthorizedResult(statusDescription); } protected class HttpNotFoundResult : HttpStatusCodeResult { public HttpNotFoundResult() : this(null) { } public HttpNotFoundResult(string statusDescription) : base(404, statusDescription) { } } protected class HttpUnauthorizedResult : HttpStatusCodeResult { public HttpUnauthorizedResult(string statusDescription) : base(401, statusDescription) { } } protected class HttpStatusCodeResult : ViewResult { public int StatusCode { get; private set; } public string StatusDescription { get; private set; } public HttpStatusCodeResult(int statusCode) : this(statusCode, null) { } public HttpStatusCodeResult(int statusCode, string statusDescription) { this.StatusCode = statusCode; this.StatusDescription = statusDescription; } public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.HttpContext.Response.StatusCode = this.StatusCode; if (this.StatusDescription != null) { context.HttpContext.Response.StatusDescription = this.StatusDescription; } // 1. Uncomment this to use the existing Error.ascx / Error.cshtml to view as an error or // 2. Uncomment this and change to any custom view and set the name here or simply // 3. (Recommended) Let it commented and the ViewName will be the current controller view action and on your view (or layout view even better) show the @ViewBag.Message to produce an inline message that tell the Not Found or Unauthorized //this.ViewName = "Error"; this.ViewBag.Message = context.HttpContext.Response.StatusDescription; base.ExecuteResult(context); } } } }чтобы использовать в вашем действии, как это:
public ActionResult Index() { // Some processing if (...) return HttpNotFound(); // Other processing }и в _Layout.cshtml (как главная страница)
<div class="content"> @if (ViewBag.Message != null) { <div class="inlineMsg"><p>@ViewBag.Message</p></div> } @RenderBody() </div>кроме того, вы можете использовать пользовательский вид, как
Error.shtmlили создать новыйNotFound.cshtmlкак я прокомментировано в коде, и вы можете определить модель представления для описания состояния и других объяснений.
Comments