如何结束响应并发回HTTP代码404?

she*_*nku 10 c# castle-windsor asp.net-mvc-3

我正在使用城堡windsor工厂根据请求网址实例化一个对象.

就像是:

    public FooViewModel Get()
    {
        if (HttpContext.Current == null)
        {
            return new FooViewModel();
        }

        var currentContext = new HttpContextWrapper(HttpContext.Current);

        // resolve actual view model.
Run Code Online (Sandbox Code Playgroud)

在某些情况下,我实际上想要抛出404并停止请求,目前如下:

        throw new HttpException(404, "HTTP/1.1 404 Not Found");
        currentContext.Response.End();
Run Code Online (Sandbox Code Playgroud)

但是请求没有结束,它仍然命中Action并尝试解析视图?

我的控制器看起来像这样:

public class HomeController : Controller
{
    public FooViewModel Foo { get; set; }

    public ActionResult Index()
    {
        ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

        return View();
    }
Run Code Online (Sandbox Code Playgroud)

我觉得这一切都错了吗?或者有没有办法实现这一目标?

我想到的另一种选择是检查Foo属性状态的动作属性?

arm*_*oon 10

我认为使用动作过滤器的方法可以达到你想要的效果:

public class RequiresModelAttribute : ActionFilterAttribute
{
    private readonly string _modelName;

    public RequiresModelAttribute(string modelName)
    {
        _modelName = modelName;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var property = filterContext.Controller.GetType().GetProperty(_modelName);
        var model = property.GetValue(filterContext.Controller);
        if (model == null)
        {
            filterContext.Result = new HttpStatusCodeResult(404);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的控制器上,您可以:

public class HomeController : Controller
{
    public FooViewModel Foo { get; set; }

    [RequiresModel("Foo")]
    public ActionResult Index()
    {
        ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:也许使用全局过滤器来兑现任何抛出的HttpExceptions?

public class HonorHttpExceptionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var httpException = filterContext.HttpContext.AllErrors.FirstOrDefault(x => x is HttpException) as HttpException;
        if (httpException != null)
        {
            filterContext.Result = new HttpStatusCodeResult(httpException.GetHttpCode());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在Global.asax中:

  public static void RegisterGlobalFilters(GlobalFilterCollection filters)
  {
      filters.Add(new HandleErrorAttribute());
      filters.Add(new HonorHttpExceptionAttribute());
  }
Run Code Online (Sandbox Code Playgroud)