@Darin Dimitrov 提供的有用信息表明 HttpNotFoundResult 实际上返回的是空结果。
经过一番研究。 MVC 3 的解决方法是派生所有 HttpNotFoundResult、HttpUnauthorizedResult、HttpStatusCodeResult 类并实现 new(覆盖它)HttpNotFound() 方法BaseController.
最佳实践是使用基本控制器,这样您就可以“控制”所有派生控制器。
我创建了新的HttpStatusCodeResult 类,不是从ActionResult 派生,而是从ViewResult 派生,以通过指定ViewName 属性来呈现视图或您想要的任何View。我按照原来的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,就像我在代码中评论的那样,您可以为状态描述和其他解释定义视图模型。