public class HomeController : Controller
{
public ActionResult Index()
{
return new HttpNotFoundResult("This doesn't exist");
}
}
HTTP未找到结果:
using System;
using System.Net;
using System.Web;
using System.Web.Mvc;
namespace YourNamespaceHere
{
/// <summary>An implementation of <see cref="ActionResult" /> that throws an <see cref="HttpException" />.</summary>
public class HttpNotFoundResult : ActionResult
{
/// <summary>Initializes a new instance of <see cref="HttpNotFoundResult" /> with the specified <paramref name="message"/>.</summary>
/// <param name="message"></param>
public HttpNotFoundResult(String message)
{
this.Message = message;
}
/// <summary>Initializes a new instance of <see cref="HttpNotFoundResult" /> with an empty message.</summary>
public HttpNotFoundResult()
: this(String.Empty) { }
/// <summary>Gets or sets the message that will be passed to the thrown <see cref="HttpException" />.</summary>
public String Message { get; set; }
/// <summary>Overrides the base <see cref="ActionResult.ExecuteResult" /> functionality to throw an <see cref="HttpException" />.</summary>
public override void ExecuteResult(ControllerContext context)
{
throw new HttpException((Int32)HttpStatusCode.NotFound, this.Message);
}
}
}
// By Erik van Brakel, with edits from Daniel Schaffer :)
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
}
6条答案
按热度按时间nwwlzxa71#
从臀部射击(牛仔编码;- -译者注),我建议这样:
控制器:
HTTP未找到结果:
使用这种方法,您就符合了框架标准。那里已经有一个HttpUnauthorizedResult了,所以这只会在其他开发人员(知道您住在哪里的神经病)的眼中扩展框架。
您可以使用reflector查看程序集,以了解HttpUnauthorizedResult是如何实现的,因为我不知道这种方法是否遗漏了什么(它似乎太简单了)。
我刚才确实用reflector看了一下HttpUnauthorizedResult,好像他们把响应的StatusCode设置成0x 191(401)。虽然这对401有效,使用404作为新值,我在Firefox中看到的似乎只是一个空白页面,而InternetExplorer显示的是默认的404(不是ASP.NET版本)。使用WebDeveloper工具栏,我检查了FF中的头,它确实显示了404未找到响应。可能只是我在FF中配置错误。
话虽如此,我认为Jeff的方法是KISS的一个很好的例子。如果你真的不需要这个例子中的冗长,他的方法也很好用。
7ivaypg92#
我们这样做;此代码位于
BaseController
中这样称呼
jutyujz03#
wrrgggsh4#
HttpNotFoundResult是我正在使用的一个很好的第一步。返回一个HttpNotFoundResult是好的。那么问题是,下一步是什么?
我创建了一个名为HandleNotFoundAttribute的动作过滤器,它会显示一个404错误页面。因为它返回一个视图,所以你可以为每个控制器创建一个特殊的404视图,或者让它使用一个默认的共享404视图。甚至当控制器没有指定的动作时,也会调用这个过滤器,因为框架会抛出一个状态代码为404的HttpException。
83qze16e5#
请注意,从MVC3开始,您只能使用
HttpStatusCodeResult
。igetnqfo6#
使用ActionFilter*很难维护,因为每当我们抛出错误时,过滤器都需要在属性中设置。如果我们忘记设置它怎么办?一种方法是在基本控制器上派生
OnException
。您需要定义一个从Controller
派生的BaseController
,并且所有控制器都必须从BaseController
派生。拥有一个基本控制器是最佳实践。注意如果使用
Exception
,响应状态代码是500,所以我们需要将其更改为404表示Not Found,401表示Unauthorized。就像我上面提到的,在BaseController
上使用OnException
覆盖以避免使用filter属性。新的MVC3也会给浏览器返回一个空的视图,这也让问题变得更麻烦了。经过一些研究,最好的解决方案是基于我在这里的答案。
为了更方便,我把它贴在这里:
经过一些研究,MVC 3的解决方法是派生所有
HttpNotFoundResult
、HttpUnauthorizedResult
、HttpStatusCodeResult
类,并在BaseController
中实现new(覆盖它)HttpNotFound
()方法。最好的做法是使用基本控制器,这样您就可以“控制”所有派生的控制器。
我创建了新
HttpStatusCodeResult
类,不是从ActionResult
派生,而是从ViewResult
派生,以呈现视图或通过指定ViewName
属性所需的任何View
。我按照原始的HttpStatusCodeResult
设置HttpContext.Response.StatusCode
和HttpContext.Response.StatusDescription
,但base.ExecuteResult(context)
将呈现合适的视图,因为我再次从ViewResult
。足够简单了吧?希望这将在MVC核心中实现。看我的
BaseController
惨叫:要在你的行动中这样使用:
和in _Layout.cshtml(类似于母版页)
此外,您可以使用自定义视图(如
Error.shtml
)或创建新的NotFound.cshtml
(如我在代码中所注解的),并且可以为状态描述和其他解释定义视图模型。