当前位置:  开发笔记 > 编程语言 > 正文

从ASP.NET MVC操作发送HTTP 404响应的正确方法是什么?

如何解决《从ASP.NETMVC操作发送HTTP404响应的正确方法是什么?》经验,为你挑选了6个好方法。

如果给出路线:

{FeedName}/{ItemPermalink}

例如:/ Blog/Hello-World

如果该项不存在,我想返回404.在ASP.NET MVC中执行此操作的正确方法是什么?



1> Erik van Bra..:

从臀部拍摄(牛仔编码;-)),我建议这样的事情:

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return new HttpNotFoundResult("This doesn't exist");
    }
}

HttpNotFoundResult:

using System;
using System.Net;
using System.Web;
using System.Web.Mvc;

namespace YourNamespaceHere
{
    /// An implementation of  that throws an .
    public class HttpNotFoundResult : ActionResult
    {
        /// Initializes a new instance of  with the specified .
        /// 
        public HttpNotFoundResult(String message)
        {
            this.Message = message;
        }

        /// Initializes a new instance of  with an empty message.
        public HttpNotFoundResult()
            : this(String.Empty) { }

        /// Gets or sets the message that will be passed to the thrown .
        public String Message { get; set; }

        /// Overrides the base  functionality to throw an .
        public override void ExecuteResult(ControllerContext context)
        {
            throw new HttpException((Int32)HttpStatusCode.NotFound, this.Message);
        }
    }
}
// By Erik van Brakel, with edits from Daniel Schaffer :)

使用此方法,您遵守框架标准.那里已经有一个HttpUnauthorizedResult,所以这只会在另一个开发人员眼中扩展框架,以便稍后维护你的代码(你知道,那个知道你住在哪里的心理学家).

您可以使用反射器来查看程序集以查看HttpUnauthorizedResult是如何实现的,因为我不知道这种方法是否遗漏了任何东西(它似乎过于简单).


我没有使用反射来看一看在HttpUnauthorizedResult刚才.似乎他们设置的响应0x191(401)中的StatusCode.虽然这适用于401,使用404作为新的价值,我似乎在Firefox中越来越只是一个空白页.Internet Explorer显示默认404(不是ASP.NET版本).使用webdeveloper工具栏我检查在FF头,其确实表现出404未找到响应.可能只是我在FF中配置错误的东西.


话虽如此,我认为Jeff的方法是KISS的一个很好的例子.如果你真的不需要这个样本中的详细程度,他的方法也可以正常工作.


MVC3中的HttpException或HttpNotFoundResult在很多方面都很有用.对于@Igor Brejc,只需在OnException中使用**if**语句来过滤掉未找到的错误.
抛出HttpException而不是仅设置HttpContext.Response.StatusCode = 404的一个问题是,如果你使用OnException Controller处理程序(就像我一样),它也会捕获HttpExceptions.所以我认为设置StatusCode是一种更好的方法.

2> Jeff Atwood..:

我们这样做; 这段代码可以在BaseController

/// 
/// returns our standard page not found view
/// 
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();


可以像这样运行它:protected override void HandleUnknownAction(string actionName){PageNotFound().ExecuteResult(this.ControllerContext); }

3> yfeldblum..:
throw new HttpException(404, "Are you sure you're in the right place?");



4> Brian Vallel..:

HttpNotFoundResult是我正在使用的第一步.返回HttpNotFoundResult很好.然后问题是,下一步是什么?

我创建了一个名为HandleNotFoundAttribute的动作过滤器,然后显示404错误页面.由于它返回一个视图,您可以为每个控制器创建一个特殊的404视图,或者让我们使用默认的共享404视图.当控制器没有指定的操作时,甚至会调用此方法,因为框架会抛出状态代码为404的HttpException.

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
                                        };
        }
    }
}



5> enashnash..:

请注意,从MVC3开始,您可以使用HttpStatusCodeResult.


或者,甚至更容易,`HttpNotFoundResult`

6> CallMeLaNN..:

使用ActionFilter很难维持的,因为每当我们抛出一个错误的过滤器需要在属性进行设置.如果我们忘了设置怎么办?一种方法是OnException在基础控制器上派生.您需要定义BaseController派生自,Controller并且所有控制器必须派生自BaseController.最佳实践是拥有一个基本控制器.

请注意,如果使用Exception响应状态代码为500,那么我们需要将其更改为404 for Not Found和401 for Unauthorized.就像我上面提到的那样,使用OnException覆盖BaseController来避免使用filter属性.

通过向浏览器返回一个空视图,新的MVC 3也会变得更加麻烦.一些研究后的最佳解决方案是基于我在这里的答案如何在ASP.Net MVC 3中返回HttpNotFound()的视图?

为了更方便,我将它粘贴在这里:


经过一番研究.对于解决办法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(如母版页)

@if (ViewBag.Message != null) {

@ViewBag.Message

} @RenderBody()

此外,您可以像我在代码中注释的那样使用自定义视图Error.shtml或创建新视图NotFound.cshtml,您可以为状态描述和其他解释定义视图模型.

推荐阅读
小色米虫_524
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有