sharptooth
sharptooth

Reputation: 170509

How do I return a status code, status description and text together in MVC3?

From my MVC3 controller action I want to return HTTP 403, set "status description" to some specific string and also return that string in the result content so that it is visible in the browser.

I can return ContentResult to specify content, but not a status code (such as 403) and not a status description. I can use HttpStatusCodeResult to specify a status code and status description but not the result content.

How do I craft an action result that contains all three?

Upvotes: 17

Views: 34176

Answers (3)

drch
drch

Reputation: 3070

Commonly you would see this done by setting the response code then returning a regular ActionResult

public ActionResult Foo() 
{ 
    Response.StatusCode = 403;
    Response.StatusDescription = "Some custom message";

    return View(); // or Content(), Json(), etc
}

If you really need this to be an ActionResult, you create your own.

Example:

public class HttpStatusContentResult : ActionResult
{
    private string _content;
    private HttpStatusCode _statusCode;
    private string _statusDescription;

    public HttpStatusContentResult(string content, 
                                   HttpStatusCode statusCode = HttpStatusCode.OK,
                                   string statusDescription = null)
    {
        _content = content;
        _statusCode = statusCode;
        _statusDescription = statusDescription;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var response = context.HttpContext.Response;
        response.StatusCode = (int) _statusCode;
        if (_statusDescription != null)
        {
            response.StatusDescription = _statusDescription;
        }

        if (_content != null)
        {
            context.HttpContext.Response.Write(_content);
        }
    }
}

Upvotes: 19

MadReasonable
MadReasonable

Reputation: 61

I went crazy trying to get this code to work before I realized it was the GetAwaiter().OnCompleted(...) that was the problem. Here's the version I got working:

public class ApiControllerBase : ApiController
{
   ...
   // Other code
   ...

   public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
   {
      return base
         .ExecuteAsync(controllerContext, cancellationToken)
         .ContinueWith(t =>
         {
            t.Result.Headers.CacheControl = new CacheControlHeaderValue()
            {
               NoStore = true,
               NoCache = true,
               MaxAge = new TimeSpan(0),
               MustRevalidate = true
            };
            t.Result.Headers.Pragma.Add(new NameValueHeaderValue("no-cache"));
            t.Result.Content.Headers.Expires = DateTime.Parse("01 Jan 1990 00:00:00 GMT");

            return t.Result;
         }, cancellationToken);
   }
}

Upvotes: -1

Andrei
Andrei

Reputation: 56716

If this is not too dirty

Response.Clear();
Response.Write("Some specific string");
return new HttpStatusCodeResult(403, "another specific string");

Upvotes: 11

Related Questions