Richtige Verwendung von AJAX Post in jquery, um das Modell aus einer stark typisierten MVC3-Ansicht zu übergeben

100

Ich bin ein unerfahrener Webprogrammierer. Bitte verzeihen Sie mir, wenn ein Teil meines "Jargons" nicht korrekt ist. Ich habe ein Projekt mit ASP.NET unter Verwendung des MVC3-Frameworks.

Ich arbeite an einer Administratoransicht, in der der Administrator eine Liste der Geräte ändert. Eine der Funktionen ist eine Schaltfläche "Aktualisieren", mit der ich den Eintrag auf der Webseite nach dem Senden eines Beitrags an den MVC-Controller mithilfe von jquery dynamisch bearbeiten möchte.

Ich gehe davon aus, dass dieser Ansatz in einer einzelnen Administratoreinstellung "sicher" ist, in der nur minimale Bedenken bestehen, dass die Webseite nicht mehr mit der Datenbank synchronisiert wird.

Ich habe eine stark typisierte Ansicht erstellt und hoffte, die Modelldaten mithilfe eines AJAX-Posts an das MVC-Steuerelement übergeben zu können.

Im folgenden Beitrag habe ich etwas gefunden, das dem ähnelt, was ich gerade mache: JQuery Ajax und ASP.NET MVC3 verursachen Nullparameter

Ich werde das Codebeispiel aus dem obigen Beitrag verwenden.

Modell:

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Regler:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

Skript in Ansicht:

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

Ich hatte noch keine Gelegenheit, das oben genannte zu verwenden. Aber ich habe mich gefragt, ob dies die "beste" Methode ist, um die Modelldaten mit AJAX an die MVC-Steuerung zurückzugeben.

Sollte ich mir Sorgen machen, die Modellinformationen offenzulegen?

John Stone
quelle

Antworten:

72

Sie können die var-Deklaration und die Zeichenfolge überspringen. Andernfalls funktioniert das einwandfrei.

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: {
        Address1: "423 Judy Road",
        Address2: "1001",
        City: "New York",
        State: "NY",
        ZipCode: "10301",
        Country: "USA"
    },
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
        alert(data.success);
    },
    error: function () {
        alert("error");
    }
});
Craig M.
quelle
Vielen Dank für den Hinweis auf die leichte Anpassung. Gibt es Bedenken, die Modellstruktur unter Sicherheitsgesichtspunkten verfügbar zu machen?
John Stone
Nichts Auffälliges fällt mir als Sicherheitsproblem auf. Wenn Sie sich darüber wirklich Sorgen machen, können Sie jederzeit einen benutzerdefinierten Modellordner auf der MVC-Seite erstellen.
Craig M
8
Das ist für mich gescheitert. Ich musste JSON.stringify ({...}) verwenden, damit der Aufruf in MVC5 funktioniert.
Johncl
Mir ist aufgefallen, dass ich bei der Arbeit mit API-Controllern dasselbe tun muss. Diese Antwort wurde jedoch vor 4 Jahren geschrieben, bevor es API-Controller gab.
Craig M
1
gott damit, ich hatte dataType statt contentType, das bekommt man immer immer !!
Phil
175

Ich habe 3 Möglichkeiten gefunden, dies umzusetzen:

C # -Klasse:

public class AddressInfo {
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

Aktion:

[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
    return Json(new { success = true });
}

JavaScript Sie können es auf drei Arten tun:

1) Abfragezeichenfolge:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serialize(),
    type: 'POST',
});

Daten hier sind eine Zeichenfolge.

"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"

2) Objektarray:

$.ajax({
    url: '/en/Home/Check',
    data: $('#form').serializeArray(),
    type: 'POST',
});

Daten hier sind ein Array von Schlüssel / Wert-Paaren:

=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]

3) JSON:

$.ajax({
      url: '/en/Home/Check',
      data: JSON.stringify({ addressInfo:{//missing brackets
          Address1: $('#address1').val(),
          Address2: $('#address2').val(),
          City: $('#City').val(),
          State: $('#State').val(),
          ZipCode: $('#ZipCode').val()}}),
      type: 'POST',
      contentType: 'application/json; charset=utf-8'
});

Daten hier sind eine serialisierte JSON-Zeichenfolge. Beachten Sie, dass der Name mit dem Parameternamen auf dem Server übereinstimmen muss !!

='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'
Jazaret
quelle
1
Ich bin gerade auf diese großartige, gründliche Antwort gestoßen, die Fragen löste, von denen ich noch nicht wusste, dass ich sie hatte. +1, danke!
SeanKilleen
# 2 war das, wonach ich gesucht habe. Dies sollte die Antwort sein.
TheGeekZn
EDIT: musste data: $('input, textarea, select').serialize(),für meine arbeiten.
TheGeekZn
Hey Jazaret !! Wie übergebe ich das Datum dem Modell mit dem 3. Ansatz?
Guruprasad Rao
1
Entschuldigung für die Verzögerung @GuruprasadRao Um ein Datum zu übergeben, können Datum und Uhrzeit eine Zeichenfolge im Javascript-Code sein, und MVC übersetzt sie in ein DateTime-Objekt.
Jazaret
12

So hat es bei mir funktioniert:

$.post("/Controller/Action", $("#form").serialize(), function(json) {       
        // handle response
}, "json");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}
Sanchitos
quelle
8

Was Sie haben, ist in Ordnung - um jedoch einige Eingaben zu sparen, können Sie es einfach für Ihre Daten verwenden

Daten: $ ('# formId'). serialize ()

Weitere Informationen finden Sie unter http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ . Die Syntax ist ziemlich einfach.

Adam Tuliper - MSFT
quelle
Um die Serialisierungsfunktion verwenden zu können, muss meines Erachtens jedes Mitglied der Klasse in einem Formularobjekt verwendet werden. Wenn das richtig ist, kann ich SOL sein.
John Stone
1
ah ya .. wenn nicht, können Sie dann nicht serialize verwenden. Sie können das DOM jedoch jederzeit bearbeiten und ein Formular mit diesen Elementen erstellen und serialisieren - aber ... es wäre wahrscheinlich sauberer, wenn Sie die Felder dann nur manuell eingeben würden.
Adam Tuliper - MSFT
@TahaRehmanSiddiqui serialize funktioniert tatsächlich im IE, was funktioniert nicht? Erhalten Sie einen Fehler?
Adam Tuliper - MSFT
Jede Eigenschaft meines Modells kommt null heraus
Taha Rehman Siddiqui
@TahaRehmanSiddiqui Entspricht der 'Name' Ihrer Formularfelder den Namen Ihrer Modelleigenschaften?
MongooseNX
0

Wenn Sie MVC 5 verwenden, lesen Sie diese Lösung!

Ich kenne die Frage, die speziell für MVC 3 gestellt wurde, aber ich bin mit MVC 5 auf diese Seite gestoßen und wollte eine Lösung für alle anderen in meiner Situation veröffentlichen. Ich habe die oben genannten Lösungen ausprobiert, aber sie haben bei mir nicht funktioniert, der Aktionsfilter wurde nie erreicht und ich konnte nicht herausfinden, warum. Ich verwende Version 5 in meinem Projekt und habe den folgenden Aktionsfilter erhalten:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;

namespace SydHeller.Filters
{
    public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
            if (clientToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
            }

            string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
            if (serverToken == null)
            {
                throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
            }

            System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
        }

        private const string KEY_NAME = "__RequestVerificationToken";
    }
}

- Notieren Sie sich das using System.Web.Mvcund using System.Web.Mvc.Filtersnicht dashttp Bibliotheken (ich denke, das ist eines der Dinge, die sich mit MVC v5 geändert haben. -

Dann wenden Sie einfach den Filter an [ValidateJSONAntiForgeryHeader] auf Ihre Aktion (oder Ihren Controller) an und er sollte korrekt aufgerufen werden.

Auf meiner Layoutseite habe </body>ich oben@AntiForgery.GetHtml();

Schließlich mache ich auf meiner Razor-Seite den Ajax-Aufruf wie folgt:

var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();

$.ajax({
  type: "POST",
  url: serviceURL,
  contentType: "application/json; charset=utf-8",
  dataType: "json",
  data: requestData,
  headers: {
     "__RequestVerificationToken": formForgeryToken
  },
     success: crimeDataSuccessFunc,
     error: crimeDataErrorFunc
});
blubberbo
quelle
1
Rufen Sie alle Formularwerte manuell ab? Warum nicht data: $("#the-form").serialize()?
Sinjai
1
@Sinjai Ich müsste mir meinen Code noch einmal ansehen, aber ich glaube, ich mache dort auch eine andere Verarbeitung. ".serialize ()" würde auch funktionieren, wenn Sie nur die Eingabewerte benötigen
blubberbo
Keine Sorge, ich war nur neugierig.
Sinjai