如何在ASP.Net MVC 3中返回HttpNotFound()的视图?
是否有一种方法可以在每次从控制器返回HttpNotFoundResult时返回相同的视图?如何指定此视图?我猜在web.config中配置404页面可能会有用,但我想知道是否有更好的方法来处理这个结果 编辑/跟进:如何在ASP.Net MVC 3中返回HttpNotFound()的视图?,asp.net,asp.net-mvc-3,Asp.net,Asp.net Mvc 3,是否有一种方法可以在每次从控制器返回HttpNotFoundResult时返回相同的视图?如何指定此视图?我猜在web.config中配置404页面可能会有用,但我想知道是否有更好的方法来处理这个结果 编辑/跟进: 最后,我使用了这个问题的第二个答案中的解决方案,对ASP.Net MVC 3进行了一些微调,以处理我的404s:HttpNotFoundResult不呈现视图。它只是将状态代码设置为404,并返回一个空结果,这对AJAX之类的事情很有用,但是如果您想要自定义404错误页面,您可以抛出
最后,我使用了这个问题的第二个答案中的解决方案,对ASP.Net MVC 3进行了一些微调,以处理我的404s:
HttpNotFoundResult
不呈现视图。它只是将状态代码设置为404,并返回一个空结果,这对AJAX之类的事情很有用,但是如果您想要自定义404错误页面,您可以抛出新的HttpException(404,“未找到”)
,它将自动在web.config中呈现配置的视图:
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="/Http404.html" />
</customErrors>
来自@Darin Dimitrov的有用信息,
HttpNotFoundResult
实际上返回的是空结果
经过一些研究。MVC 3的解决方法是在BaseController
中派生所有HttpNotFoundResult
、HttpUnauthorizedResult
、HttpStatusCodeResult
类,并实现新的(覆盖它)HttpNotFound
()方法
最好使用基本控制器,这样您就可以“控制”所有派生控制器
我创建新的HttpStatusCodeResult
类,不是从ActionResult
派生,而是从ViewResult
派生,通过指定ViewName
属性来呈现视图或任何所需的视图。我按照原始的HttpStatusCodeResult
设置HttpContext.Response.StatusCode
和HttpContext.Response.StatusDescription
,但是base.ExecuteResult(context)
将呈现合适的视图,因为我再次从ViewResult
派生。够简单吗?希望这将在MVC核心中实现
请参见下面的myBaseController
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中(如母版页)
@如果(ViewBag.Message!=null)
{
@查看包。留言
}
@RenderBody()
此外,您可以使用自定义视图,如Error.shtml
,或创建新的NotFound.cshtml
,如我在代码中的注释,您可以为状态描述和其他解释定义视图模型。此解决方案结合了IResultFilter和IEExceptionFilter来捕获抛出的HttpException或返回的HttpExceptionHttpStatusCodeResult来自操作中
public class CustomViewForHttpStatusResultFilter: IResultFilter, IExceptionFilter
{
string viewName;
int statusCode;
public CustomViewForHttpStatusResultFilter(HttpStatusCodeResult prototype, string viewName)
: this(prototype.StatusCode, viewName) {
}
public CustomViewForHttpStatusResultFilter(int statusCode, string viewName) {
this.viewName = viewName;
this.statusCode = statusCode;
}
public void OnResultExecuted(ResultExecutedContext filterContext) {
HttpStatusCodeResult httpStatusCodeResult = filterContext.Result as HttpStatusCodeResult;
if (httpStatusCodeResult != null && httpStatusCodeResult.StatusCode == statusCode) {
ExecuteCustomViewResult(filterContext.Controller.ControllerContext);
}
}
public void OnResultExecuting(ResultExecutingContext filterContext) {
}
public void OnException(ExceptionContext filterContext) {
HttpException httpException = filterContext.Exception as HttpException;
if (httpException != null && httpException.GetHttpCode() == statusCode) {
ExecuteCustomViewResult(filterContext.Controller.ControllerContext);
// This causes ELMAH not to log exceptions, so commented out
//filterContext.ExceptionHandled = true;
}
}
void ExecuteCustomViewResult(ControllerContext controllerContext) {
ViewResult viewResult = new ViewResult();
viewResult.ViewName = viewName;
viewResult.ViewData = controllerContext.Controller.ViewData;
viewResult.TempData = controllerContext.Controller.TempData;
viewResult.ExecuteResult(controllerContext);
controllerContext.HttpContext.Response.TrySkipIisCustomErrors = true;
}
}
您可以注册此筛选器,以便指定HttpException的http状态代码或要显示其自定义视图的具体HttpStatusCodeResult
GlobalFilters.Filters.Add(new CustomViewForHttpStatusResultFilter(new HttpNotFoundResult(), "Error404"));
// alternate syntax
GlobalFilters.Filters.Add(new CustomViewForHttpStatusResultFilter(404, "Error404"));
它处理操作中引发或返回的异常和HttpStatusCodeResult。它不会处理在MVC选择合适的操作和控制器之前发生的错误,如常见问题:
- 未知路线
- 未知控制器
- 未知动作
要处理这些类型的NotFound错误,请将此解决方案与结合起来,这里是一个真正的答案,它允许在单个位置完全自定义错误页面。
无需修改web.confog或创建复杂的类和代码。
也适用于MVC5
将此代码添加到控制器:
if (bad) {
Response.Clear();
Response.TrySkipIisCustomErrors = true;
Response.Write(product + I(" Toodet pole"));
Response.StatusCode = (int)HttpStatusCode.NotFound;
//Response.ContentType = "text/html; charset=utf-8";
Response.End();
return null;
}
基于如果希望在控制器中发现httpnotfound错误,请遵循此步骤
public ActionResult Contact()
{
return HttpNotFound();
}
如果是这样的话。。。返回HttpNotFound()的目的是什么?有点不相关,但您建议如何处理有人试图使用错误id访问页面的情况?例如,stackoverflow上的错误问题id?404 HttpException?@Rifk,这是一种方法。您还可以尝试在IIS中为不同的状态代码配置自定义错误页,然后使用HttpNotFoundResult
@Rifk。其目的是:假设站点管理员已删除该用户,但该用户仍被搜索引擎索引。因此,在这种情况下,您可以从用户配置文件页面返回“HttpNotFound”,以便搜索引擎更新其结果。那么自定义错误页面呢?无法定义“错误”控制器并为每种错误创建关联视图吗?(例如404、500等)??我将这里提供的解决方案与结合起来,以处理各种错误(未知路由、未知控制器、未知操作、控制器操作返回的HttpNotFound()结果以及控制器引发的HttpException)。我实现了所有这些,同时根据错误代码的类型实现了正确的状态代码(404500)。
if (bad) {
Response.Clear();
Response.TrySkipIisCustomErrors = true;
Response.Write(product + I(" Toodet pole"));
Response.StatusCode = (int)HttpStatusCode.NotFound;
//Response.ContentType = "text/html; charset=utf-8";
Response.End();
return null;
}
public ActionResult Contact()
{
return HttpNotFound();
}