Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When performing post via ajax, Bad Request is returned instead of the JSON result

Tags:

Javascript

jqXHR = $.ajax({ url: $frm.attr("action"), type: "POST", dataType: "json", cache: false,   headers: headers, contentType: "application/json;charset=UTF-8", data: ko.mapping.toJSON(data, map),   beforeSend: function(x) {     if (x && x.overrideMimeType) {       return x.overrideMimeType("application/json;charset=UTF-8");     }   } });  jqXHR.fail(function(xhr, err, msg) {  /* xhr.responseText  NEED TO BE JSON!!! */ }); 

In Chrome

Headers

Request Method:POST Status Code:400 Bad Request Request Headersview source Accept:application/json, text/javascript, */*; q=0.01 Accept-Encoding:gzip,deflate,sdch Accept-Language:en-US,en;q=0.8,pt-BR;q=0.6,pt;q=0.4 Connection:keep-alive Content-Length:10 Content-Type:application/json;charset=UTF-8 User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36 X-Requested-With:XMLHttpRequest Request Payloadview source {Id:0} Response Headersview source Cache-Control:private Content-Length:54 Content-Type:application/json; charset=utf-8 Date:Thu, 27 Feb 2014 14:01:59 GMT Server:Microsoft-IIS/8.0 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.1 X-Powered-By:ASP.NET 

Response

[{"Name":"Nome","ErrorMessage":"campo obrigatório."}]

Works in chrome!


In IE8

Headers (Request)

POST /Motivos/Salvar HTTP/1.1 Accept: application/json, text/javascript, */*; q=0.01 Accept-Language: pt-br x-requested-with: XMLHttpRequest Content-Type: application/json;charset=UTF-8 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0) Content-Length: 10 Connection: Keep-Alive Pragma: no-cache 

Headers (Response)

HTTP/1.1 400 Bad Request Cache-Control: private Content-Type: text/html Server: Microsoft-IIS/8.0 X-AspNetMvc-Version: 5.1 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Thu, 27 Feb 2014 13:51:46 GMT Content-Length: 11  Bad Request 

NOT WORK!!

Asp.net MVC

Filter

public class HandleExceptionAttribute : HandleErrorAttribute {     public override void OnException(ExceptionContext filterContext)     {         if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)         {             filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;             var ex = filterContext.Exception.GetBaseException();             filterContext.Result = new JsonResult             {                 JsonRequestBehavior = JsonRequestBehavior.AllowGet,                 Data = new                 {                     ex.Message,                     ex.GetType().Name                 }             };             filterContext.ExceptionHandled = true;         }         else         {             base.OnException(filterContext);         }     } } 

Apply on GlobalFilterCollection

Controller

[ValidateJsonAntiForgeryToken, HttpPost] public virtual JsonResult Salvar(TViewModel viewModel) {     if (ModelState.IsValid)     {         TEntity model;         if (default(TKey).Equals(viewModel.Id))         {             model = Mapper.Map<TEntity>(viewModel);             AdicionarEntidade(model, viewModel);         }         else         {             model = Repositorio.Get(viewModel.Id);             Mapper.Map(viewModel, model, typeof(TViewModel), typeof(TEntity));             SalvarEntidade(model, viewModel);         }          return SalvarResult(model);     }      Response.StatusCode = 400;     return Json(ModelState.ToJson(), JsonRequestBehavior.AllowGet); } 

Extenssion

public static object ToJson(this ModelStateDictionary dic, params string[] othersMessages) {     var states = (from e in dic where e.Value.Errors.Count > 0                   select new { Name = e.Key, e.Value.Errors[0].ErrorMessage }).ToList();      if (othersMessages != null)         foreach (var message in othersMessages)             states.Add(new { Name = "", ErrorMessage = message });      return states; } 

Questions

  • Why not have the xhr.resposeText object?
  • How to retrieve JSON in the same way that I recover in Chrome?

I need the JSON to populate the form!

Notes: 03/11/2014

When I add Response.TrySkipIisCustomErrors = true; in my controler, it works! responseText returns the json. Why?

like image 539
ridermansb Avatar asked Feb 27 '14 14:02

ridermansb


2 Answers

Think this is an issue with IIS trying to use custom error response rather sending the error message that the controller is generating.

<system.webServer>     ...     <httpErrors existingResponse="PassThrough"></httpErrors>     ... </system.webServer> 

Or

Response.TrySkipIisCustomErrors = true; 

Reference - https://stackoverflow.com/a/4029197/1304559

Check out this blog post http://weblog.west-wind.com/posts/2009/Apr/29/IIS-7-Error-Pages-taking-over-500-Errors

Since response code is set to 400, IIS replaces your content with its custom error page content

like image 106
aravind Avatar answered Sep 30 '22 15:09

aravind


The issue I am seeing is that your trying to set the encoding of the JSON to UTF-8. Normally it works just fine, however, on IIS, it has a custom error to report that the UTF-8 is not necessary.

Few other things to note. You are doing a POST, so the server will be expecting a json file. If provided none, it will not know what to do.

like image 20
jemiloii Avatar answered Sep 30 '22 15:09

jemiloii