2012-09-11 15 views
7

Używam fabryki windsor zamku do utworzenia instancji obiektu na podstawie adresu URL żądania.Jak mogę zakończyć odpowiedź i wysłać kod HTTP 404?

Coś jak:

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

     var currentContext = new HttpContextWrapper(HttpContext.Current); 

     // resolve actual view model. 

W niektórych przypadkach, tak naprawdę chcą rzucić 404 i zatrzymać żądanie, obecnie lubię:

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

Jednak wniosek nie kończy się i nadal uderza w akcję i próbuje rozwiązać ten widok?

moim kontroler będzie wyglądać mniej więcej tak:

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

ja myślę o tym wszystkim stało? Czy istnieje sposób, w jaki mogę to osiągnąć?

Alternatywa, o której myślałem, to atrybut działania, aby sprawdzić stan właściwości Foo?

Odpowiedz

6

Myślę, że podejście z wykorzystaniem filtru działania mogą osiągnąć to, czego chce:

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

Następnie na kontrolerze można zrobić:

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: Może stosując filtr globalny uhonorować wszystkie wyrzucone wyjątki HttpException?

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

Następnie w Global.asax:

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

Tak, zmieniłem już to, zobaczmy, czy są jakieś inne sugestie. – shenku

+0

@shenku Zaktualizowałem swoją odpowiedź z innym podejściem, może to będzie działać lepiej w twoim scenariuszu? –

2

Inną opcją jest nadrzędne onException na kontrolerze.

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); 
     } 
    } 
Powiązane problemy