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!!! */ });
接头
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
响应
[{“Name”:“Nome”,“ErrorMessage”:“campoobrigatório。”}]
适用于Chrome!
标题(请求)
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
标题(响应)
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
不工作!!
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);
}
}
}
在GlobalFilterCollection上应用
[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);
}
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;
}
我需要JSON来填充表单!
当我在我的控制器中添加Response.TrySkipIisCustomErrors = true;
时,它可以正常工作!
responseText返回json。
为什么呢?
答案 0 :(得分:32)
认为这是IIS尝试使用自定义错误响应而不是发送控制器正在生成的错误消息的问题。
<system.webServer>
...
<httpErrors existingResponse="PassThrough"></httpErrors>
...
</system.webServer>
或者
Response.TrySkipIisCustomErrors = true;
参考 - https://stackoverflow.com/a/4029197/1304559
查看此博文http://weblog.west-wind.com/posts/2009/Apr/29/IIS-7-Error-Pages-taking-over-500-Errors
由于响应代码设置为400,因此IIS会使用其自定义错误页面内容替换您的内容
答案 1 :(得分:2)
我看到的问题是您尝试将JSON的编码设置为UTF-8。通常它工作正常,但是,在IIS上,它有一个自定义错误报告UTF-8不是必需的。
很少有其他注意事项。您正在进行POST,因此服务器将需要一个json文件。如果没有提供,它将不知道该怎么做。
答案 2 :(得分:2)
您的回复带有Content-Type: text/html
http标头,但应该是application/json
。这不是Chrome中的问题(并且您不会在控制台中获得mismatch warnings)因为您依赖于overrideMimeType
...您猜对了,这不是IE -友好。实际上,以下内容从未在旧版本的IE上执行:
if (x && x.overrideMimeType) {
return x.overrideMimeType("application/json;charset=UTF-8");
}
您的解决方案可能是确保以正确的内容类型提供内容。如果您熟悉Burp Suite等篡改工具,则可以即时添加正确的标头,看看是否能解决问题。我可能会避免内联像AddHeader
这样的方法,看看是否有一种方法可以修复更高的路由,也许是级别。
答案 3 :(得分:1)
我已经填写了一个应该有帮助的失败测试。
$.post($frm.attr("action"), ko.mapping.toJSON(data, map))
.done(function (dataVal) {
//process dataVal
var mystruct = GenerateCache($.parseJSON(dataVal));
})
.fail(function (jqxhr, textStatus, error) {
if (jqxhr.responseText.indexOf("YourMoniker") != -1) {
parseData($.parseJSON(jqxhr.responseText));
} else {
var err = textStatus + ', ' + error;
console.log("Request Failed: " + err);
}
});
function GenerateCache(data) {
var obj = function () { };
obj.prototype = data;
return new obj();
}
具体看一下.fail
部分中的错误处理。
答案 4 :(得分:0)
这不是你的控制器,这工作正常。您缺少必填字段:IE和Chrome都返回状态代码400 Bad Request
- 但只有Chrome正在正确处理responseText
,并且您[{"Name":"Nome","ErrorMessage":"campo obrigatório."}]
表示您缺少表单字段。
虽然我已经搜索过并且在使用非200状态代码处理XMLHttpRequest.responseText
时没有找到任何特定IE错误的引用,但看起来IE正在用自己的代替您的响应主体:
Headers (Response)
HTTP/1.1 400 Bad Request
...
Content-Length: 11
Bad Request
表示处理它的“内容”是“错误请求”状态文本,而不是正确的json响应(例如,Chrome将其读取为内容长度54)。这可能意味着IE正在放弃你的响应主体(我怀疑它,这是令人难以置信的血腥)或者它只是没有被“正确处理”。尝试转储jqXHR
对象的其余部分以及fail
处理程序的参数,看看是否可以在某处找到它。
答案 5 :(得分:0)
IE(所有版本,包括IE11)都会在状态文本中放入“错误请求”,并忽略您输入的JSON作为消息。
为了在IE中使用xhr.responseText时出错,你需要抛出一个异常,而不是用HttpStatusCode.BadRequest;
所以...之前:
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { Message = "There is already a distribution set which covers part or all of this period" });
这适用于Chrome,FF和任何理智的浏览器。 后:
throw new Exception("You have posted invalid datas.");
作为未处理的例外,它会作为响应传递给浏览器,这可以在Chrome,FF甚至IE中使用。它不是优雅的,与所有未处理的异常(或仅仅是异常)相同,但是它可以帮助您收到适当的响应。