Beim Posten über Ajax wird Bad Request anstelle des JSON-Ergebnisses zurückgegeben

Lesezeit: 7 Minuten

Benutzer-Avatar
Reitermansb

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

Im Chrom

Überschriften

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

Antwort

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

Funktioniert in Chrom!


Im IE8

Kopfzeilen (Anfrage)

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

Kopfzeilen (Antwort)

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

NICHT ARBEITEN!!

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

Auf GlobalFilterCollection anwenden

Regler

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

Verlängerung

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

Fragen

  • Warum nicht das xhr.resposeText-Objekt haben?
  • Wie kann ich JSON auf die gleiche Weise abrufen, wie ich es in Chrome wiederherstelle?

Ich brauche den JSON, um das Formular auszufüllen!

Hinweise: 11.03.2014

Wenn ich hinzufüge Response.TrySkipIisCustomErrors = true; In meinem Controller funktioniert es! responseText gibt den json zurück. Wieso den?

  • Wenn Sie einen anderen Inhaltstyp in festlegen $.ajax Es wäre ratsam, processData auf false zu setzen. Auch, warum bist du Mime-Typ überschreiben in vorherSenden? Sie haben die Kontrolle über den Rückgabetyp auf dem Server.

    – Kerry Liu

    11. März 2014 um 14:05 Uhr

  • Können Sie zeigen, was der Wert in data ist: ko.mapping.toJSON(data, map) sowohl im IE als auch im Chrome?

    – Lee Gary

    13. März 2014 um 3:31 Uhr

  • @KerryLiu Gerade Einstellung processData: false, tritt der Fehler auf. * Um beforeSend, es war nur ein Test. Auch wenn dieses Ereignis entfernt wird, tritt dieser Fehler immer noch auf!

    – ridermansb

    13. März 2014 um 11:08 Uhr

  • @LeeGary Die Daten: Im IE "{"Id":"0"}" , Im Chrom "{"Id":"0"}"

    – ridermansb

    13. März 2014 um 11:12 Uhr

  • Liegt es nur an mir, oder zeigen Ihre Chrome-Header (Antwort?) den Statuscode an 400 Bad Request auch?

    – Brian Norden

    15. März 2014 um 18:25 Uhr

Benutzer-Avatar
aravind

Denken Sie, dass dies ein Problem ist, wenn IIS versucht, eine benutzerdefinierte Fehlerantwort zu verwenden, anstatt die Fehlermeldung zu senden, die der Controller generiert.

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

Oder

Response.TrySkipIisCustomErrors = true;

Referenz – https://stackoverflow.com/a/4029197/1304559

Schauen Sie sich diesen Blogbeitrag an http://weblog.west-wind.com/posts/2009/Apr/29/IIS-7-Error-Pages-taking-over-500-Errors

Da der Antwortcode auf 400 festgelegt ist, ersetzt IIS Ihren Inhalt durch den Inhalt der benutzerdefinierten Fehlerseite

Das Problem, das ich sehe, ist, dass Sie versuchen, die Codierung des JSON auf UTF-8 festzulegen. Normalerweise funktioniert es gut, aber unter IIS gibt es einen benutzerdefinierten Fehler, der meldet, dass UTF-8 nicht erforderlich ist.

Einige andere Dinge zu beachten. Sie führen einen POST durch, daher erwartet der Server eine JSON-Datei. Wenn keine angegeben wird, weiß es nicht, was zu tun ist.

  • 1. Über UTF-8 macht keinen Sinn, weil es in Chrome funktioniert. Ich habe versucht, UTF-8 zu entfernen, und der Fehler tritt immer noch auf!

    – ridermansb

    13. März 2014 um 11:05 Uhr

  • 2. Ich sende JSON an den Server!

    – ridermansb

    13. März 2014 um 11:06 Uhr

  • Nun, was ist der json, den Sie senden? Sie zeigen nur die Antwort json, die Antwort ist das, was der Server dem Client sendet. Außerdem können Sie jeweils nur eine JSON-Datei senden. Wenn Sie also mehrere Formulare gleichzeitig übermitteln, müssen diese als eine JSON-Datei gepackt werden.

    – jemiloii

    13. März 2014 um 17:57 Uhr

Benutzer-Avatar
Oleg

Ihre Antwort kommt zurück mit Content-Type: text/html http-Header, aber es sollte sein application/json. Dies ist kein Problem in Chrome (und Sie erhalten keine Nichtübereinstimmungswarnungen in der Konsole), weil Sie sich darauf verlassen overrideMimeType… was, Sie haben es erraten, nicht IE-freundlich ist. Tatsächlich wird Folgendes niemals auf älteren Versionen von IE ausgeführt:

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

Ihre Lösung könnte darin bestehen, sicherzustellen, dass der Inhalt mit dem richtigen Inhaltstyp bereitgestellt wird. Wenn Sie mit Manipulationswerkzeugen wie z Burp-Suite, könnten Sie den richtigen Header on-the-fly hinzufügen und sehen, ob das Problem dadurch behoben wird. Ich würde wahrscheinlich Inlining-Methoden wie vermeiden AddHeader und prüfen Sie, ob es eine Möglichkeit gibt, dies auf einer höheren – vielleicht Routing – Ebene zu beheben.

Benutzer-Avatar
KapitänBli

Ich habe einen Fehlertest ausgefüllt, der helfen sollte.

$.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();
}

Schauen Sie sich insbesondere die Fehlerbehandlung in der an .fail Sektion.

Es ist nicht Ihr Controller, das funktioniert gut. Ihnen fehlt ein erforderliches Feld: Sowohl IE als auch Chrome geben den Statuscode zurück 400 Bad Request – aber nur Chrome verarbeitet das richtig responseText und dir geben [{"Name":"Nome","ErrorMessage":"campo obrigatório."}] was bedeutet, dass Sie ein fehlendes Formularfeld haben.

Obwohl ich überall gesucht habe und keinen Hinweis auf bestimmte IE-Fehler bei der Verarbeitung gefunden habe XMLHttpRequest.responseText mit Nicht-200-Statuscodes sieht es so aus, als würde IE Ihren Antworttext durch seinen eigenen ersetzen:

Headers (Response)

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

Bad Request

Gibt an, dass der „Inhalt“, wie er behandelt wird, der Statustext „Bad Request“ ist, nicht die richtige JSON-Antwort (die Chrome beispielsweise als Inhaltslänge 54 liest). Dies könnte bedeuten, dass IE Ihren Antworttext verwirft (ich bezweifle es, das wäre verdammt unglaublich) oder dass er einfach nicht “richtig” verarbeitet wird. Versuchen Sie, den Rest Ihrer abzuladen jqXHR Objekt und die Argumente für Ihre fail Handler, um zu sehen, ob Sie es dort irgendwo finden können.

Benutzer-Avatar
Nenner

IE (alle Versionen, einschließlich IE11) fügt “Bad Request” in den Statustext ein und ignoriert den JSON, den Sie als Nachricht eingegeben haben.

Um den xhr.responseText im IE im Fehlerfall zu verwenden, müssen Sie eine Ausnahme auslösen, anstatt ein Json oder JsonResult mit zurückzugeben HttpStatusCode.BadRequest;

Also … vorher:

Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { Message = "There is already a distribution set which covers part or all of this period" });

Dies funktioniert wirklich in Chrome, FF und jedem vernünftigen Browser. Nach:

throw new Exception("You have posted invalid datas.");

Als unbehandelte Ausnahme wird es als Antwort an den Browser weitergegeben, dies funktioniert in Chrome, FF und sogar im IE. Es ist nicht anmutig, genau wie alle nicht behandelten Ausnahmen (oder nur Ausnahmen, was das betrifft), aber es wird die Aufgabe erfüllen, Ihnen eine angemessene Antwort zu geben.

1099040cookie-checkBeim Posten über Ajax wird Bad Request anstelle des JSON-Ergebnisses zurückgegeben

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy