2012-09-11 18 views
7

Estoy usando una fábrica de windsor de castillos para crear instancias de un objeto en función de la url de solicitud.¿Cómo puedo finalizar una respuesta y devolver el código HTTP 404?

Algo así como:

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

     var currentContext = new HttpContextWrapper(HttpContext.Current); 

     // resolve actual view model. 

En algunos casos, en realidad quiero lanzar un 404 y detener la solicitud, actualmente gustaría:

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

Sin embargo, la solicitud no termina y todavía golpea la acción e intenta resolver la vista?

Mi controlador sería algo como esto:

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

Estoy pensando en esto todo mal? ¿O hay alguna manera de que pueda lograr esto?

La alternativa que estaba pensando es un atributo de la acción para verificar el estado de la propiedad Foo?

Respuesta

6

creo que el enfoque de usar un filtro de acción podría lograr lo que usted está deseando:

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

Luego, en el controlador que podría hacer:

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

Editar: Tal vez el uso de un filtro global para honrar cualquier HttpExceptions arrojado?

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

Luego, en Global.asax:

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

yup, Ya lo cambié a esto, veamos si hay otras sugerencias. – shenku

+0

@shenku He actualizado mi respuesta con otro enfoque, ¿tal vez eso funcione mejor en su escenario? –

2

Otra opción es reemplazar OnException en el controlador.

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