2012-09-11 54 views
7

Tôi đang sử dụng một nhà máy windsor lâu đài để khởi tạo một đối tượng dựa trên url yêu cầu.Làm cách nào để kết thúc phản hồi và gửi lại mã HTTP 404?

Cái gì như:

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

     var currentContext = new HttpContextWrapper(HttpContext.Current); 

     // resolve actual view model. 

Trong một số trường hợp, tôi thực sự muốn ném một 404 và ngăn chặn các yêu cầu, hiện nay thích:

 throw new HttpException(404, "HTTP/1.1 404 Not Found"); 
     currentContext.Response.End(); 

Tuy nhiên, yêu cầu không kết thúc và nó vẫn chạm vào Hành động và cố gắng giải quyết chế độ xem?

My điều khiển sẽ giống như thế này:

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

Tôi nghĩ về điều này hoàn toàn sai? Hay có cách nào tôi có thể đạt được điều này?

Cách thay thế mà tôi đã nghĩ đến là thuộc tính trên hành động để kiểm tra trạng thái của thuộc tính Foo?

Trả lời

6

Tôi nghĩ rằng cách tiếp cận của việc sử dụng một bộ lọc hành động có thể đạt được những gì bạn đang mong muốn:

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

Sau đó, trên bộ điều khiển của bạn, bạn có thể làm:

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

Edit: Có lẽ sử dụng một bộ lọc toàn cầu để tôn trọng bất kỳ HttpExceptions bị ném nào?

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

Sau đó, trong Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
     filters.Add(new HonorHttpExceptionAttribute()); 
    } 
+0

yup, tôi đã thay đổi thành điều này, cho phép xem có đề xuất nào khác không. – shenku

+0

@shenku Tôi đã cập nhật phản hồi của mình với một cách tiếp cận khác, có thể điều đó sẽ hoạt động tốt hơn trong kịch bản của bạn? –

2

tùy chọn khác là trọng OnException trên Controller.

public ActionResult Index() 
    { 
     ViewBag.Message = "Welcome to ASP.NET MVC!"; 
     Get(); 
     return View(); 
    } 

    public int Get() 
    { 
     throw new HttpException(404, "HTTP/1.1 404 Not Found"); 
     // we don't need end the response here, we need go to result step 
     // currentContext.Response.End(); 

    } 

    protected override void OnException(ExceptionContext filterContext) 
    { 
     base.OnException(filterContext); 
     if (filterContext.Exception is HttpException) 
     { 
      filterContext.Result = this.HttpNotFound(filterContext.Exception.Message); 
     } 
    } 
Các vấn đề liên quan