views:

23

answers:

1

I have a custom ActionResult for returning certain HTTP Errors, like NotFoundResult and ForbiddenResult, they all derive from ViewResult.

I use them for instances like short circuiting actions with a 404 if an entity was not found in the database during the course of an action.

Within these result objects, I set the HTTP Status to the appropriate number. When I do that, the view that these ViewResults reference does not render. I have to leave the status as 200 OK in order for my view to be rendered.

How do I set an appropriate status AND render a view in ASP.NET MVC 2.0?

+2  A: 

I have a custom ActionResult for returning certain HTTP Errors, like NotFoundResult and ForbiddenResult, they all derive from ViewResult.

Allow me to suggest you an alternative error handling:

Start by creating an error controller and the corresponding views:

public class ErrorController : Controller
{
    public ActionResult General()
    {
        return View();
    }

    public ActionResult HttpError404()
    {
        return View();
    }

    public ActionResult HttpError500()
    {
        return View();
    }
}

In Global.asax define the Application_Error method:

protected void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    // TODO: Log the exception with your favorite logging framework

    Response.Clear();
    var httpException = exception as HttpException;

    var routeData = new RouteData();
    // Take the ErrorController
    routeData.Values.Add("controller", "error");

    if (httpException == null)
    {
        // Use the General action for any unhandled error
        routeData.Values.Add("action", "general");
    }
    else
    {
        switch (httpException.GetHttpCode())
        {
            case 404:
                routeData.Values.Add("action", "httpError404");
                break;
            case 500:
                routeData.Values.Add("action", "httpError500");
                break;
            default:
                routeData.Values.Add("action", "general");
                break;
        }
    }

    // Add the exception to route data so that the error controller 
    // could use it with RouteData.Values["error"]
    routeData.Values.Add("error", exception);

    Server.ClearError();
    IController errorController = new ErrorController();
    errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}

Finally throw appropriate exceptions:

public class HomeController: Controller
{
    public ActionResult Index(int id)
    {
        var model = _repository.GetModel(id);
        if (model == null)
        {
            throw new HttpException(404, "Model not found with id = " + id);
        }
        return View(model);
    }
}
Darin Dimitrov
Seemes like a cool way to consolidate error handling code. I'll get right back to you thanks!
BC
Still unsure as to why responses were empty, but this solved my problem while consolidating some error code together. Thanks for providing an implementation! One thing I would add is that custom errors should be turned off when doing this.
BC
@BC, tough to say as you haven't provided any source code.
Darin Dimitrov