Return Mvc.JsonResult plus set Response.StatusCode

2019-02-01 17:34发布

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

2条回答
我命由我不由天
2楼-- · 2019-02-01 17:38

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.

查看更多
看我几分像从前
3楼-- · 2019-02-01 17:51

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.

查看更多
登录 后发表回答