返回错误状态代码为MVC的JSON

Sar*_*ath 40 c# asp.net-mvc json

我试图按照此链接中的建议向控制器调用返回错误, 以便客户端可以采取适当的操作.控制器由javascript通过jquery AJAX调用.只有在我没有将状态设置为错误时才会返回Json对象.这是示例代码

if (response.errors.Length > 0)
   Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(response);
Run Code Online (Sandbox Code Playgroud)

如果我没有设置状态代码,我会得到Json.如果我设置了状态代码,我会返回状态代码但不会返回Json错误对象.

更新 我想将一个Error对象作为JSON发送,以便可以处理ajax的错误回调.

Sar*_*ath 32

我在这里找到了解决方案

我必须创建一个动作过滤器来覆盖MVC的默认行为

这是我的异常课程

class ValidationException : ApplicationException
{
    public JsonResult exceptionDetails;
    public ValidationException(JsonResult exceptionDetails)
    {
        this.exceptionDetails = exceptionDetails;
    }
    public ValidationException(string message) : base(message) { }
    public ValidationException(string message, Exception inner) : base(message, inner) { }
    protected ValidationException(
    System.Runtime.Serialization.SerializationInfo info,
    System.Runtime.Serialization.StreamingContext context)
        : base(info, context) { }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我有构造函数初始化我的JSON.这是动作过滤器

public class HandleUIExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public virtual void OnException(ExceptionContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }
        if (filterContext.Exception != null)
        {
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
            filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
            filterContext.Result = ((ValidationException)filterContext.Exception).myJsonError;
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在我有了动作过滤器,我将用filter属性装饰我的控制器

[HandleUIException]
public JsonResult UpdateName(string objectToUpdate)
{
   var response = myClient.ValidateObject(objectToUpdate);
   if (response.errors.Length > 0)
     throw new ValidationException(Json(response));
}
Run Code Online (Sandbox Code Playgroud)

当抛出错误时,调用实现IExceptionFilter的动作过滤器,并在错误回调时返回客户端上的Json.

  • 如果读者正在考虑"是否有必要?",答案是"不". - 我和@Sarath的情况相同,想要返回一个HTTP错误代码和一些描述错误的JSON数据.事实证明,我可以使用清除响应的行,跳过IIS自定义错误并且状态代码为sat.我将这3行放在我的控制器上的Action中,在这3行后,我正常返回我的JSON数据.工作就像一个魅力. (16认同)
  • 确实这是真的,但是为了可以重复使用,你会想要这样做,因为答案表明而不是将相同的代码复制/过去到每个动作中. (7认同)
  • @René 我非常希望看到基于该评论的答案。我不明白你说的是哪三行。 (2认同)

Ric*_*ide 28

我发现最好的解决方案是创建自己的JsonResult,扩展原始实现并允许您指定HttpStatusCode:

public class JsonHttpStatusResult : JsonResult
{
    private readonly HttpStatusCode _httpStatus;

    public JsonHttpStatusResult(object data, HttpStatusCode httpStatus)
    {
        Data = data;
        _httpStatus = httpStatus;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        context.RequestContext.HttpContext.Response.StatusCode = (int)_httpStatus;
        base.ExecuteResult(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以在控制器操作中使用它,如下所示:

if(thereWereErrors)
{
    var errorModel = new { error = "There was an error" };
    return new JsonHttpStatusResult(errorModel, HttpStatusCode.InternalServerError);
}
Run Code Online (Sandbox Code Playgroud)


Gab*_*ius 25

这个问题有一个非常优雅的解决方案,只需通过web.config配置您的站点:

<system.webServer>
    <httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough"/>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)

资料来源:https://serverfault.com/questions/123729/iis-is-overriding-my-response-content-if-i-manually-set-the-response-statuscode

  • 繁荣!我一直在寻找的答案.它在本地工作正常,但在远程服务器中没有.我知道可以通过一些配置设置来完成.干杯! (3认同)

小智 7

一种向 Json 发送错误的简单方法是控制响应对象的 Http 状态码并设置自定义错误消息。

控制器

public JsonResult Create(MyObject myObject) 
{
  //AllFine
  return Json(new { IsCreated = True, Content = ViewGenerator(myObject));

  //Use input may be wrong but nothing crashed
  return Json(new { IsCreated = False, Content = ViewGenerator(myObject));  

  //Error
  Response.StatusCode = (int)HttpStatusCode.InternalServerError;
  return Json(new { IsCreated = false, ErrorMessage = 'My error message');
}
Run Code Online (Sandbox Code Playgroud)

JS

$.ajax({
     type: "POST",
     dataType: "json",
     url: "MyController/Create",
     data: JSON.stringify(myObject),
     success: function (result) {
       if(result.IsCreated)
     {
    //... ALL FINE
     }
     else
     {
    //... Use input may be wrong but nothing crashed
     }
   },
    error: function (error) {
            alert("Error:" + erro.responseJSON.ErrorMessage ); //Error
        }
  });
Run Code Online (Sandbox Code Playgroud)


Lee*_*des 6

基于Richard Garside的答案,这是ASP.Net核心版本

public class JsonErrorResult : JsonResult
{
    private readonly HttpStatusCode _statusCode;

    public JsonErrorResult(object json) : this(json, HttpStatusCode.InternalServerError)
    {
    }

    public JsonErrorResult(object json, HttpStatusCode statusCode) : base(json)
    {
        _statusCode = statusCode;
    }

    public override void ExecuteResult(ActionContext context)
    {
        context.HttpContext.Response.StatusCode = (int)_statusCode;
        base.ExecuteResult(context);
    }

    public override Task ExecuteResultAsync(ActionContext context)
    {
        context.HttpContext.Response.StatusCode = (int)_statusCode;
        return base.ExecuteResultAsync(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的控制器中,返回如下:

// Set a json object to return. The status code defaults to 500
return new JsonErrorResult(new { message = "Sorry, an internal error occurred."});

// Or you can override the status code
return new JsonErrorResult(new { foo = "bar"}, HttpStatusCode.NotFound);
Run Code Online (Sandbox Code Playgroud)

  • 无需将此添加到ASP.NETCore,此功能存在-/sf/ask/2965209761/ (2认同)

Ste*_*aly 5

设置StatusCode后,您必须自己返回JSON错误对象,就像这样...

if (BadRequest)
{
    Dictionary<string, object> error = new Dictionary<string, object>();
    error.Add("ErrorCode", -1);
    error.Add("ErrorMessage", "Something really bad happened");
    return Json(error);
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是拥有一个JsonErrorModel并填充它

public class JsonErrorModel
{
    public int ErrorCode { get; set;}

    public string ErrorMessage { get; set; }
}

public ActionResult SomeMethod()
{

    if (BadRequest)
    {
        var error = new JsonErrorModel
        {
            ErrorCode = -1,
            ErrorMessage = "Something really bad happened"
        };

        return Json(error);
    }

   //Return valid response
}
Run Code Online (Sandbox Code Playgroud)

这里也看看答案

  • 我已经在响应对象中出现错误。问题是我收到“错误请求”,而不是JSON对象。如果我没有设置状态,我将得到带有错误的JSON,但是客户端不知道这是一个异常情况。 (4认同)

Phi*_*ppe 5

对我有用的东西(我从另一个 stackoverflow 响应中获取的)是设置标志:

Response.TrySkipIisCustomErrors = true;
Run Code Online (Sandbox Code Playgroud)


小智 5

一些响应依赖于抛出异常并在 OnException 重写中对其进行处理。就我而言,如果用户传递了错误的 ID,我想返回错误请求等状态。对我有用的是使用 ControllerContext:

var jsonResult = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = "whoops" };

ControllerContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;

return jsonResult;
Run Code Online (Sandbox Code Playgroud)