2016-03-27 9 views
0

Ich entwickle eine ASP.Net MVC5-Anwendung, in der ich versuche, JSON-Daten über eine AJAX-Anfrage an die Aktionsmethode des Controllers zu übergeben. Die JSON-Daten enthalten eine Reihe von Formularwerten. Da ich versuche, ein Master-Detail-Formular zu erstellen, welche Daten gebucht wird in einem Eins-zu-viele-Format in der Datenbank ich ein Objekt wie folgt erstellt:Wie übergeben Sie Array zu Aktionsmethode in ASP.Net MVC?

var salesmain = { 
    "SalesId": "", 
    "ReferenceNo": "", 
    "SalesDate": "", 
    "SalesPerson": "", 
    "SalesSubs": [] 
}; 

Beachten Sie, dass in den oben genannten Daten die SalesSubs Eigenschaft ist ein Array, das auf diese Weise deklariert ist:

var salessub = {  
    "SalesId": "", 
    "ItemName": "", 
    "Qty": "", 
    "UnitPrice":"" 
}; 

So, jetzt habe ich zu dem Punkt, wo man salesmain viele salessub oder ein Array von salessub enthalten. Nachdem ich einige Werte hineingedrückt und die AJAX-Anfrage an die Aktionsmethode übergeben habe, hat sie das SalesSubs Array als null. Ich habe habe es durch einen Haltepunkt setzt dort:

enter image description here

In dem obigen Bild salesmain.SalesSubs, die ein Array ist, ist null und das ist, wie ich versuche, die Daten an die Aktion zu übergeben:

$.ajax({ 
    url: '/Sales/Create', 
    data: addRequestVerificationToken(salesmain), 
    type: 'POST', 
    dataType: 'json', 
    traditional : true, 
    success: function (result) { 
     if (result.Success == "1") { 
      window.location.href = "/Sales/Index"; 
     } 
     else { 
      alert(result.ex); 
     } 
    } 
}); 

Dies ist, wie ich Werte in der SalesSubs Array bin drängen:

salesmain.SalesId = $("#SalesId").val(); 
salesmain.ReferenceNo = $("#ReferenceNo").val(); 
salesmain.SalesDate = $("#SalesDate").val(); 
salesmain.SalesPerson = $("#SalesPerson").val(); 

$('.tbl').DataTable().rows().data().each(function (value, index) { 
    salessub.ItemName = value[0]; 
    salessub.Qty = value[1]; 
    salessub.UnitPrice = value[2]; 
    salesmain.SalesSubs.push(salessub); 
}); 

Im obigen Code habe ich jQuerys Datatable-Plugin verwendet, um die gesamten saLessub-Daten von der DataTable zu holen. Ich denke, der Salesmain enthält eine vollständige gültige Daten, bevor die Ajax-Anfrage ausgeführt wird, aber irgendwie die Ajax-Anfrage nicht die Array-Daten (SalesSubs) des Salesmain-Objekts, nachdem es ausgeführt wird.

Ist irgendetwas mit meinem AJAX-Teil des Codes falsch? Was ist der richtige Weg, um JSON-Daten mit einer AJAX-Anfrage an die Aktionsmethode zu übergeben?

EDIT:

Hier ist SalesMain.cs Modell:

public class SalesMain 
{ 
    [Key] 
    public int SalesId { get; set; } 
    public string ReferenceNo { get; set; } 
    public DateTime SalesDate { get; set; } 
    public string SalesPerson { get; set; } 

    public virtual ICollection<SalesSub> SalesSubs { get; set; } 
} 

und SalesSub.cs Modell:

public class SalesSub 
{ 
    [Key, Column(Order = 0)] 
    public int SalesId { get; set; } 
    [Key, Column(Order = 1)] 
    public string ItemName { get; set; } 
    public int Qty { get; set; } 
    public decimal UnitPrice { get; set; } 
    public virtual SalesMain SalesMain { get; set; } 
} 

und SalesController erstellen Methode:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "SalesId,ReferenceNo,SalesDate,SalesPerson")] SalesMain salesmain) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 
       // Perform Update 
       if (salesmain.SalesId > 0) 
       { 

        var CurrentsalesSUb = db.SalesSubs.Where(p => p.SalesId == salesmain.SalesId); 

        foreach (SalesSub ss in CurrentsalesSUb) 
         db.SalesSubs.Remove(ss); 

        foreach (SalesSub ss in salesmain.SalesSubs) 
         db.SalesSubs.Add(ss); 

        db.Entry(salesmain).State = EntityState.Modified; 
       } 
       //Perform Save 
       else 
       { 
        db.SalesMains.Add(salesmain); 
       } 

       db.SaveChanges(); 
       return Json(new { Success = 1, SalesID = salesmain.SalesId, ex = "" }); 
      } 
     } 
     catch (Exception ex) 
     { 
      return Json(new { Success = 0, ex = ex.Message.ToString() }); 
     } 

     return Json(new { Success = 0, ex = new Exception("Unable to save").Message.ToString() }); 
    } 

und wenn ich console.log(salesmain) vor der Ajax-Anforderung gesendet wird, ist das, was ich bekomme:

enter image description here

Ich denke also, dass die oben genannten Daten durch die Ajax-Anforderung, in Ordnung ist aber jetzt zu bewegen, wenn es erreicht Die Aktion salesmain.SalesSubs wird null, und nur die SalesMain-Tabelle wird in der Datenbank aufgefüllt, und die SalesSub-Tabelle bleibt leer (keine Zuordnung erreicht).

Weitere Edit:

contentType : 'application/json' und data : JSON.stringify(salesmain) Hinzufügen führt zu einem 500 interner Serverfehler, nach der Inspektion in Konsolenfenster, wird der Fehler sagt:

The required anti-forgery form field “__RequestVerificationToken” is not present. 

es ist wirklich nicht vorhanden ?, weil ich habe bereits eine Funktion dafür:

function addRequestVerificationToken(data) { 
     data.__RequestVerificationToken = $('input[name=__RequestVerificationToken]').val(); 
     return data; 
    }; 

der obige Code fügt das Token nicht zum salesmain hinzu, wenn ich contentType : "application/json" und JSON.stringify() verwende, fügt es hinzu, wenn diese zwei entfernt werden.

+1

Das klingt wie ein ModelBinder-Problem. Können Sie bitte die genaue JSON-Zeichenfolge, die Sie in der Anfrage senden, und auch die Signatur der empfangenen Aktion (zusammen mit den Klassenkonturen) hinzufügen –

+0

Danke für die Antwort :), Ich habe meine Frage aktualisiert, Bitte, schauen Sie. –

+0

add contentType: 'application/json, charset = utf-8' in ajax Anfrage –

Antwort

1

Konvertieren Sie Ihr js-Objekt mit der JSON.stringify-Methode in eine json-Zeichenkettenversion. Geben Sie den contentType auch als "application/json" an.

$.ajax({ 
     data: JSON.stringify(salesmain), 
     contentType : "application/json", 
     success: function (result) { alert(result); } 
     // Your existing code 
}); 

Ich schlage vor, auch Html Helfer wie Url.Action zu erzeugen, um den korrekten relativen Pfad zu Ihrer Aktion-Methode statt harter Kodierung mit ihnen.

url: '@Url.Action("Create","Sales")', 

Das obige sollte funktionieren, wenn Ihr Js-Code in einer Rasiereransicht ist. Wenn sich Ihr Code in einer externen js-Datei befindet, verwenden Sie die in this post beschriebene Lösung.

EDIT: Wenn Sie die Daten mit contentType='application/json' senden, Ihre RequestVerificationToken wird nicht funktionieren, weil der Code die Form erwarten als normal vorgelegt werden (wo content als default „application/x-www-form-urlencoded“ gesetzt ist). So können Sie entweder die [ValidateAntiForgeryToken] in Ihrer HttpPost-Aktionsmethode deaktivieren.

Auch ich sehe, Sie haben Bind-Attribut verwendet, um nur bestimmte Eigenschaften zu enthalten. Sie müssen der Einschlussliste die Eigenschaften SalesSubs hinzufügen, damit die Modellbindung auch für diese Eigenschaft funktioniert.

Der folgende Code sollte gut funktionieren.

Client-seitiger Code zum Senden der Daten.

var salesmain = { SalesSubs: [] }; 
salesmain.SalesId =33; 
salesmain.ReferenceNo ="Test"; 
salesmain.SalesDate ="12/12/2004"; 
salesmain.SalesPerson = "Shyju"; 

var salessub = {}; 
salessub.ItemName = "Test"; 
salessub.Qty = 2; 
salessub.UnitPrice = 25.33; 
salesmain.SalesSubs.push(salessub); 
console.log(salesmain); 

$.ajax({ 
    url: '/Sales/Create' , 
    data: JSON.stringify(salesmain), 
    type: 'POST', 
    contentType: 'application/json', 
    success: function (result) { 
     console.log('response'); 
     console.log(result); 
    } 
}); 

Und der Code-Server

[HttpPost] 
public ActionResult Create([Bind(Include = "SalesId,ReferenceNo,SalesDate,SalesPerson 
               ,SalesSubs")] SalesMain salesmain) 
{ 
    // do something with salesmain 
} 

Die best way to prevent over posting ist sein würden Sie unbedingt aus der Sicht erforderlich, um eine Ansichtsmodell mit Eigenschaften zu verwenden. Ich persönlich bevorzuge diesen Ansatz, um Daten zwischen Sichten und Aktionsmethoden zu übertragen, anstatt ORM-generierte Entitätsklassen mit Bind-Attribut zu verwenden.

+0

Danke für die Beantwortung, ich habe es bereits versucht, Hinzufügen von contentType: 'Anwendung/Json' übergibt nicht einmal die Daten an die Aktion, Fehler auf der Clientseite geben 'Das erforderliche Anti-Fälschungsformular Feld "__RequestVerificationToken" ist nicht vorhanden ', es liest nicht das Token-Feld, wenn ich die Daten auf Ihre Weise übergeben, habe ich' [ValidateAntiForgery] 'Aktion Filter entfernt, und dann überprüft, SalesSubs ist immer noch 'null', Außerdem habe ich bereits eine Funktion zum Anhängen erstellt '__RequestVerificationToken' (Meine Frage aktualisiert), Also, es hängt, wenn ich' contentType: "application/json" 'und' JSON.stringify' sonst nicht entfernen. –

+0

Das liegt an Ihrem Bindungsattribut. Siehe meine aktualisierte Antwort. – Shyju

+0

Das ist die Antwort, aber ich habe es noch geschafft, eine Klasse für die Validierung von JSON Anti-Fälschungs-Token zu erstellen, überprüfen Sie die Antwort von KEN Q [hier] (http://stackoverflow.com/questions/2906754/how-can-i-supply-an-antiforgerytoken -when-Posting-JSON-Daten-Verwendung-AJAX) –

Verwandte Themen