ASP.NET MVC 3: Creating HttpStatusCodeResult with view based body

My last posts described new action results in ASP.NET MVC 3 – HttpNotFoundResult and HttpStatusCodeResult. Unfortunately these result have no body to send to client but there are times we need it to inform our visitor about problems the way that we don’t go out of information context where visitor is. In this example I will show you how to write your own HttpStatusCodeResult that has also body.

We cannot use HttpStatusCodeResult because it doesn’t contain information about current view and there is no way how to attach views to this action result. Instead, I wrote my own implementation of HttpStatusCodeResult that extends ViewResult class and has therefore support for views. This is important thing because body of response is defined same way as other views in ASP.NET MVC framework.

Okay, here is my HttpStatusCodeWithBodyResult class in its very first form.

public class HttpStatusCodeWithBodyResult : ViewResult
{
   
private int
_statusCode;
   
private string
_description;

   
public HttpStatusCodeWithBodyResult(int
statusCode,
           
string description = null
)
        :
this(null
, statusCode, description)
    {

    }
   
public HttpStatusCodeWithBodyResult(string viewName, int
statusCode,
           
string description = null
)
    {
        _statusCode = statusCode;
        _description = description;
        ViewName = viewName;
    }

   
public override void ExecuteResult(ControllerContext
context)
    {
       
var
httpContext = context.HttpContext;
       
var
response = httpContext.Response;

        response.StatusCode = _statusCode;
        response.StatusDescription = _description;

       
base.ExecuteResult(context);
    }
}

And here is how you can use it in you controller methods. The examples are given for 404 – Not Found and 410 – Gone responses.

public ActionResult NotFound()
{
   
var msg = "I cannot find this resource!"
;

   
// there must be view called NotFound.aspx or NotFound.cshtml
    var result = new HttpStatusCodeResultWithBody("NotFound"
, 404, msg);
   
return
result;
}

public ActionResult
GoneForever()
{
   
var msg = "This resource is dead and buried!"
;

   
// there must be view called GoneForever.aspx or GoneForever.cshtml
    var result = new HttpStatusCodeResultWithBody
(410, msg);
   
return result;
}

You can read more about HttpNotFoundResult class from my posting ASP.NET MVC 3: Using HttpNotFoundResult action result and about HttpStatusCodeResult from my posting ASP.NET MVC 3: Using HttpStatusCodeResult.

Conclusion

In this posting I showed you how to create action result that works like HttpSthatusCodeResult but supports also body for result returned to browser. This way we can tell to both technical clients (browsers, search engine spiders etc) and visitors that there was problem and what one or another of them has to do now. Consider it also as good SEO and usability practices.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    4 thoughts on “ASP.NET MVC 3: Creating HttpStatusCodeResult with view based body

    • February 5, 2011 at 6:18 am
      Permalink

      Any ideas on returning a 401 without ASP taking over and trying to redirect to login page? I simply want to return a view with a content-type of application/xml and a statusCode of 401. There seems to be a hole here.

    • February 6, 2011 at 6:18 am
      Permalink

      Why doesn’t HttpStatusCodeResult include this ability? Is there some rationale for this or is it just not fully baked?

    • February 13, 2011 at 11:22 am
      Permalink

      Thanks for question, ChrisLamont. MVC framework just changes status code and let’s lower levels to manage the error. In my solution here, by example, Application_Error is not triggered and settings in web.config are ignored.

    • July 19, 2011 at 6:38 pm
      Permalink

      [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
      public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
      {
      protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
      {
      var user = filterContext.HttpContext.User;
      if (user.Identity.IsAuthenticated)
      {
      filterContext.Result = new RedirectResult(“Your Not Authorized page or ~/{controller}/{action}”);
      }
      else
      { base.HandleUnauthorizedRequest(filterContext);
      }
      }

      }

    Leave a Reply

    Your email address will not be published. Required fields are marked *