Return JSON with error status code MVC

前端 未结 11 1700
隐瞒了意图╮
隐瞒了意图╮ 2020-11-27 13:23

I was trying to return an error to the call to the controller as advised in This link so that client can take appropriate action. The controller is called by javascript via

相关标签:
11条回答
  • 2020-11-27 14:00

    Several of the responses rely on an exception being thrown and having it handled in the OnException override. In my case, I wanted to return statuses such as bad request if the user, say, had passed in a bad ID. What works for me is to use the ControllerContext:

    var jsonResult = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = "whoops" };
    
    ControllerContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
    
    return jsonResult;
    
    0 讨论(0)
  • 2020-11-27 14:02

    I found the solution here

    I had to create a action filter to override the default behaviour of MVC

    Here is my exception class

    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) { }
    }
    

    Note that I have constructor which initializes my JSON. Here is the action filter

    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;
            }
        }
    

    Now that I have the action filter, I will decorate my controller with the filter attribute

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

    When the error is thrown the action filter which implements IExceptionFilter get called and I get back the Json on the client on error callback.

    0 讨论(0)
  • 2020-11-27 14:02

    You have to return JSON error object yourself after setting the StatusCode, like so ...

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

    Another way is to have a JsonErrorModel and populate it

    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
    }
    

    Take a look at the answer here as well

    0 讨论(0)
  • 2020-11-27 14:04

    Building on the answer from Richard Garside, here's the ASP.Net Core version

    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);
        }
    }
    

    Then in your controller, return as follows:

    // 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);
    
    0 讨论(0)
  • 2020-11-27 14:06

    A simple way to send a error to Json is control Http Status Code of response object and set a custom error message.

    Controller

    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');
    }
    

    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
            }
      });
    
    0 讨论(0)
提交回复
热议问题