2014-07-11 10 views
7

Wir versuchen, mehrere Formulare mit einem Ajax (jQuery) Aufruf an eine ASP-Anwendung zu senden.Mehrere Formulare im Back-End schreiben/binden ASP.NET MVC (MEF)

Wir verwenden den folgenden jQuery-Code:

var formContainer = { 
     Form1 : form1.serialize(), 
     Form2 : form2.serialize() 
    } 
    $.ajax({ 
     type: "POST", 
     url: '@Url.Action("CreateModel", "Controller")', 

     data: formContainer, 
     success: function (result) { } 
    }); 

Auf dem Server wir folgendes in der Request.Form Eigenschaft erhalten:

Key : Value 
Form1 : All serialized form elements for Form1 
Form2 : All serialized form elements for Form2 

Normalerweise benutzen wir die folgende Methode so ASP automatisch schafft das Objekt mit dem richtigen Eigenschaftswert:

public ActionResult CreateModel(ClassForForm1 obj) 

Aber weil die beiden f Orms werden zusammen gesendet, der Modelbinder kann die Klasse nicht binden und erstellen. Für diese Aktion möchten wir, dass der Modellbauer die Werte in Request.Form ["Form1"] verwendet.

Wir können keinen benutzerdefinierten Modelbinder verwenden, da wir eine externe Bibliothek verwenden (DevExpress, sie haben darüber eine eigene Implementierung geschrieben).

Wir verwenden das MEF-Framework zum Hinzufügen von Funktionalitäten (diese Funktionen werden als Formulare in der Ansicht hinzugefügt). Aus diesem Grund wissen wir nicht, was auf dem Backend zu erwarten ist. Das Schreiben eines Wrapper ViewModel ist nicht akzeptabel.

Die Funktionalität zum Verarbeiten der anderen Formulardaten wird in anderen Modulen verarbeitet.

Alle Lösungen sind willkommen!

Vielen Dank im Voraus.

+0

Wenn Sie sagen "Also für diese Aktion möchten wir, dass der Modellbauer die Werte in Request.Form [" Form1 "] verwendet." Sie möchten, dass Form2-Werte für diese Anforderung ignoriert werden? Oder möchten Sie CreateModel für ** jedes Formular ** in der Anfrage aufrufen, so dass CreateModel, wenn 3 Formulare gesendet werden, dreimal für jedes Formular einmal ausgeführt wird? – AaronLS

+0

Ja, wir wollen die Werte in Request.Form ["Form2"] wie Sie sagten "ignorieren". –

+0

Ich habe versucht, die Request.Form-Werte in einem benutzerdefinierten Modelbinder zu ändern, aber es liest Werte von einem IUnvalidatedprovider. Obwohl es der letzte Code (in der statischen Funktion) auf dieser Seite war: http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/. Aber ich konnte nicht finden, wie man die Werte in diesem ändert. Dies ist, was ich selbst gefunden habe, andere Lösungen sind natürlich willkommen :). –

Antwort

1

Dies wird normalerweise mit einem kombinierten Ansichtsmodell durchgeführt. Andernfalls müssten Sie die Anforderungsparameter manuell analysieren. Hier ist eine fiddle zeigt, wie Sie die Daten aus mehreren Formularen kombinieren.

$(function() { 
    $('button').click(function(e) { 
     var form1 = $('#form1'); 
     var form2 = $('#form2'); 
     $.ajax({ 
      type: "POST", 
      url: '/echo/html/', 
      data: form1.serialize()+"&"+form2.serialize(), 
      success: function (result) { 
       alert(result); 
      } 
     }); 
    }); 
}); 

Auf dem Server wäre Ihrer Ansicht nach Modell benötigen:

public class IndexViewModel { 
    // properties from form1 
    public string first { get; set; } 

    // properties from form2 
    public string last { get; set; } 
} 

public class First { 
    public string first { get; set; } 
} 

public class Last { 
    public string last { get; set; } 
} 

Und Ihre Aktion Unterschrift: Methode

[HttpPost] 
public ActionResult Index(IndexViewModel model) { 
    var firstModel = (new First()).CloneMatching(model); 
    var lastModel = (new Last()).CloneMatching(model); 

    return RedirectToAction("Thanks"); 
} 

Siehe Best way to clone properties of disparate objects für die CloneMatching Erweiterung.

+0

Sie könnten auch composition für die View-Model-Klasse und '@ Html.EditorFor (model => model.Form1.first)' zum Beispiel verwenden. – B2K

1

Wenn Sie erstellen Sie Javascript-Objekt wie folgt:

var formContainer = { obj : { 
      Form1 : form1.serialize(), 
      Form2 : form2.serialize() 
     } 
} 

Der Controller sollte es mit dem Namen ‚obj‘ du mit dem ‚obj‘ in Ihrer Methode in Javascript erstellt passen ....

public ActionResult CreateModel(ClassForForm1 obj) 
1

Meine vorherige Probe funktionierte nur, weil meine Klasse Name und Wert Requisiten hat. Das tut mir wirklich leid.Aber jetzt können Sie sehen, arbeiten DEMO

JS

function mapForm(form) 
{ 
    var result = {}; 

    $.map($(form).serializeArray(), 
        function(el){ 
         mapFormProperty(result, el); 
          });  
    return result; 
} 

function mapFormProperty(form, property) 
{ 
    form[property.name] = property.value; 
} 

$('.submit').click(function(){ 

    var form1 = mapForm($('#form1')); 
    var form2 = mapForm($('#form2'));   

    var formContainer = { 
     'Form1': form1, 
     'Form2': form2}; 

    $.ajax({ 
     type: "POST", 
     url: '@Url.Action("CreateModel", "Controller")', 
     data: JSON.stringify(formContainer), 
     success: function (result) { } 
}); 

Operationen mit Formulare und Formular Behälter sollten Sie Zeichenfolge neben json geben

"{" Form1 ": {" Prop1" : "Wert1", "pROP2": "Value2"}, "Form2": { "Prop1": "Wert1", "pROP2": "Value2"}}“

Und Ihr m odel Bindemittel wird diese in der Lage zu lösen, wenn Sie Ihre Unterschrift Aktion ändern

Aktion

public ActionResult CreateModel(ClassForForm1 Form1) //argument name must be equal to data property 
                //but not equal to class name 

Und es sollte funktionieren. es funktioniert in meinem Testbeispiel

+0

Können Sie Ihr Beispielprojekt vielleicht hochladen? Wenn ich die Funktion serializeArray auf meinem Formular aufruft, erhalte ich ein Array von Objekten, und in Ihrem obigen Code geben Sie mehrere Eigenschaften pro Formular an (prop1 & prop2) –

+0

@StefanKoenen Ich habe meine Antwort und die dazugehörige Geige Demo aktualisiert – Baximilian