Подтвердить что ты не робот

При выполнении сообщения через ajax возвращается неверный запрос вместо результата JSON

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!!! */ });

В Chrome

Заголовки

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": "campo obrigatório." }}

Работает в хроме!


В IE8

Заголовки (запрос)

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

НЕ РАБОТАЕТ!!

Asp.net MVC

Фильтр

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

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

Вопросы

  • Почему бы не создать объект xhr.resposeText?
  • Как получить JSON так же, как я восстановился в Chrome?

Мне нужно, чтобы JSON заполнил форму!

Примечания: 03/11/2014

Когда я добавляю Response.TrySkipIisCustomErrors = true; в мой контроллер, он работает! responseText возвращает json. Почему?

4b9b3361

Ответ 1

Подумайте, что это проблема с IIS, пытающейся использовать пользовательский ответ об ошибке, скорее отправляя сообщение об ошибке, которое генерирует контроллер.

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

или

Response.TrySkipIisCustomErrors = true;

Ссылка - fooobar.com/questions/238810/...

Отметьте этот пост в блоге http://weblog.west-wind.com/posts/2009/Apr/29/IIS-7-Error-Pages-taking-over-500-Errors

Так как для кода ответа установлено значение 400, IIS заменяет ваш контент на его содержимое страницы с ошибкой

Ответ 2

Проблема, которую я вижу, заключается в том, что вы пытаетесь установить кодировку JSON на UTF-8. Обычно это работает отлично, однако, в IIS, у него есть настраиваемая ошибка, чтобы сообщить, что UTF-8 не требуется.

Несколько других заметок. Вы выполняете POST, поэтому сервер будет ожидать json файл. Если этого не будет, он не будет знать, что делать.

Ответ 3

Ваш ответ возвращается с Content-Type: text/html http-заголовком, но он должен быть application/json. Это не проблема в Chrome (и вы не получаете предупреждений о несоответствиях в консоли), потому что вы полагаетесь на overrideMimeType... который, как вы догадались, не поддерживает IE. Фактически, в старых версиях IE никогда не выполняется следующее:

if (x && x.overrideMimeType) {
  return x.overrideMimeType("application/json;charset=UTF-8");
}

Ваше решение может заключаться в том, чтобы убедиться, что контент поддерживается с правильным типом контента. Если вы знакомы с инструментами несанкционированного доступа, такими как Burp Suite, вы можете добавить правильный заголовок на лету и посмотреть, устраняет ли это проблему, Я бы, вероятно, избегал использования таких методов, как AddHeader и посмотреть, есть ли способ, который можно зафиксировать на более высокой маршрутизации, возможно, уровне.

Ответ 4

Я заполнил тест сбоя, который должен помочь.

$.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.

Ответ 5

Это не ваш контроллер, который работает нормально. Вам не хватает обязательного поля: оба IE и Chrome возвращают код состояния 400 Bad Request - но только Chrome правильно обрабатывает responseText и дает вам [{"Name":"Nome","ErrorMessage":"campo obrigatório."}], что означает, что у вас отсутствует поле формы.

Хотя я искал все и не нашел ссылки на определенные ошибки IE при обработке XMLHttpRequest.responseText с не-200 кодами состояния, похоже, что IE заменяет тело ответа своим:

Headers (Response)

HTTP/1.1 400 Bad Request
...
Content-Length: 11

Bad Request

Указывает, что "контент", поскольку он относится к нему, представляет собой текст статуса "плохого запроса", а не правильный ответ json (который, например, Chrome читает как длина контента 54). Это может означать, что IE отбрасывает ваше тело ответа (я сомневаюсь, что это было бы чертовски невероятно) или просто не обрабатывается "правильно". Попробуйте сбросить остальную часть вашего объекта jqXHR и аргументы для вашего обработчика fail, чтобы узнать, можете ли вы найти его там где-нибудь.

Ответ 6

IE (все версии, включая IE11) помещают "Bad Request" в текст состояния и игнорируют JSON, который вы вставляете в качестве сообщения.

Чтобы использовать xhr.responseText в IE при ошибке, вам нужно выбросить исключение вместо возврата Json или JsonResult с помощью 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. Это не изящно, как и все необработанные исключения (или только исключения, если на то пошло), но он будет выполнять задание дать вам соответствующий ответ.