Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I end a response and send HTTP code 404 back?

I am using a castle windsor factory to instantiate an object based on the request url.

Something like:

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

        var currentContext = new HttpContextWrapper(HttpContext.Current);

        // resolve actual view model.

In some cases, I actually want to throw a 404 and stop the request, currently like:

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

However the request doesn't end and it still hits the Action and tries to resolve the view?

My Controller would look something like this:

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

Am I thinking about this all wrong? Or is there a way I can achieve this?

The alternative I was thinking of is an attribute on the action to check the state of the Foo property?

like image 659
shenku Avatar asked Sep 11 '12 23:09

shenku


People also ask

How do I return a 404 response code?

Open or create the . htaccess-file and enter the relative path to the error page. First though, you have to create the error page (404. html, for example) on the first level of your website (the root-directory).

When should HTTP 404 be returned?

When a user requests a nonexistent URL on your website, you should return an individual error page that lets them know that the requested URL does not exist. You should also make sure that the server returns the correct HTTP status code “404“.

Should a search endpoint return 404?

Based on the code above, is it correct to return a NOT_FOUND status ( 404 ), or should I be returning 204 , or some other more appropriate code? If you would expect a resource to be there, because it is looked up using an ID, then a 404 is expected. Something goes wrong, the resource you need to be there is not found.

How do I return a node JS 404?

All you need to do is add a middleware function at the very bottom of the stack (below all other functions) to handle a 404 response: app. use((req, res, next) => { res. status(404).


2 Answers

I think the approach of using an action filter could achieve what you are wanting:

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

Then, on your controller you could do:

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: Perhaps using a global filter to honor any thrown 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());
        }
    }
}

Then in Global.asax:

  public static void RegisterGlobalFilters(GlobalFilterCollection filters)
  {
      filters.Add(new HandleErrorAttribute());
      filters.Add(new HonorHttpExceptionAttribute());
  }
like image 172
armen.shimoon Avatar answered Oct 19 '22 07:10

armen.shimoon


Another option is overriding OnException on 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);
        }
    }
like image 39
ivenxu Avatar answered Oct 19 '22 08:10

ivenxu