Brent
Brent

Reputation: 4876

Return Mvc.JsonResult plus set Response.StatusCode

Project: ASP MVC 4 running under .net 4.0 framework:

When running an application under VS 2010 express (or deployed and running under IIS 7.5 on my local machine) the following (pseudocode) result from an action works as expected

[HttpPost]
public ActionResult PostWord(Model model)
{
   ....
   Response.StatusCode = 400;
   Return new JsonResult { data = new {fieldName = "Word", error = "Not really a word!" } };

(and I have assigned ContentType and ContentEncoding properties of the JsonResult object, with no difference in behaviour)

When the deployable is moved onto a web host (using IIS 7), firebug is telling me that the response is as expected (400) but there is no JSON in the response (ie there is no text of any kind). If I remove the line

Response.StatusCode = 400;

from the action, the JSON is perfectly formed in the response, but of course the response status code is 200 (OK), which interferes with the consuming javascript and appropriate function call.

Any thoughts on what might be going on and how to fix this? Thank you

Upvotes: 43

Views: 23479

Answers (3)

arni
arni

Reputation: 2397

For anyone looking for this - in ASP.NET Core you can set the StatusCode property of JsonResult.

https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.jsonresult.statuscode

Upvotes: 0

Richard Garside
Richard Garside

Reputation: 89160

I've created a subclass of JsonResult that allows you to specify the HttpStatusCode.

public class JsonResultWithHttpStatusCode : JsonResult
{

    private int _statusCode;
    private string _statusDescription;

    public JsonResultWithHttpStatusCode(object data, HttpStatusCode status) 
    {
        var code = Convert.ToInt32(status);
        var description = HttpWorkerRequest.GetStatusDescription(code);
        Init(data, code, description);
    }

    public JsonResultWithHttpStatusCode(object data, int code, string description)
    {
        Init(data, code, description);
    }

    private void Init(object data, int code, string description)
    {
        Data = data;
        _statusCode = code;
        _statusDescription = description;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.StatusCode = _statusCode;
        context.HttpContext.Response.StatusDescription = _statusDescription;
        base.ExecuteResult(context);
    }
}

Then you can return this as your result and the status code will get set on the response. You can also test the status code on the result in your tests.

Upvotes: 3

Robert
Robert

Reputation: 1507

I had this exact same problem; in order to make sure that the correct answer is not buried in the comments (as it was for me), I want to reiterate @Sprockincat's comment:

For me at least, it was indeed an issue with IIS Custom errors, and can be solved with:

Response.TrySkipIisCustomErrors = true;

@Sprockincat - you should get credit for this. I'm just making it more visible because it's such a subtle fix to a problem that is quite difficult to diagnose.

Upvotes: 61

Related Questions