2014-07-11 5 views
7

Si sta tentando di inviare più moduli con una chiamata Ajax (jQuery) a un'applicazione ASP.Registrazione/binding di più moduli sul back-end ASP.NET MVC (MEF)

Usiamo il seguente codice jQuery:

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

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

Sul server che riceviamo il seguente nella proprietà Request.Form:

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

Normalmente si usa il seguente metodo in modo ASP è automaticly creando l'oggetto con il giusto valore di proprietà:

public ActionResult CreateModel(ClassForForm1 obj) 

Ma perché i due f gli orms vengono inviati insieme al modelbinder non è possibile associare e creare la classe. Quindi per questa azione vogliamo che il modelbuilder usi i valori in Request.Form ["Form1"].

Non possiamo usare un modelbinder personalizzato, perché usiamo una libreria esterna (DevExpress, hanno scritto una propria implementazione sopra questo).

Stiamo utilizzando il framework MEF per aggiungere funzionalità (queste funzionalità sono aggiunte come moduli nella vista). Per questo motivo non sappiamo cosa aspettarsi dal back-end. Quindi scrivere un wrapper ViewModel non è accettabile.

La funzionalità per l'elaborazione degli altri dati dei moduli verrà gestita all'interno di altri moduli.

Tutte le soluzioni sono benvenute!

Grazie in anticipo.

+0

Quando si dice "Quindi per questa azione si desidera che il modelbuilder utilizzi i valori in Request.Form [" Form1 "]." essenzialmente vuoi che i valori di Form2 vengano ignorati per quella richiesta? Oppure è necessario chiamare CreateModel per ** ogni modulo ** nella richiesta, in modo tale che se vengono inviati 3 moduli, CreateModel viene eseguito tre volte, una volta per ogni modulo? – AaronLS

+0

Sì, vogliamo "ignorare" i valori in Request.Form ["Form2"] come hai detto tu. –

+0

Ho provato a modificare i valori Request.Form in un modelbinder personalizzato, ma sta leggendo i valori da un IUnvalidatedprovider. Sebbene fosse l'ultimo codice (nella funzione statica) in questa pagina: http://blogs.taiga.nl/martijn/2011/09/29/custom-model-binders-and-request-validation/. Ma non sono riuscito a trovare come modificare i valori in quello. Questo è quello che mi sono trovato, altre soluzioni sono benvenute naturalmente :) –

risposta

1

Questo in genere viene eseguito utilizzando un modello di visualizzazione combinato. Altrimenti, avresti bisogno di analizzare manualmente i parametri della richiesta. Ecco un fiddle che mostra come combinare i dati da più moduli.

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

Sul server, il tuo modello di vista richiederebbe:

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

E la tua firma azione:

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

    return RedirectToAction("Thanks"); 
} 

Vedere Best way to clone properties of disparate objects per il metodo di estensione CloneMatching.

+0

È anche possibile utilizzare la composizione sulla classe del modello di visualizzazione e '@ Html.EditorFor (model => model.Form1.first)' ad esempio. – B2K

1

Se si crea JavaScript oggetto come questo:

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

Il regolatore deve corrispondere in su con il nome di 'obj' creato nel javascript con il 'obj' nel metodo ....

public ActionResult CreateModel(ClassForForm1 obj) 
1

Il mio esempio precedente ha funzionato solo perché la mia classe ha il nome e il valore di oggetti di scena. Mi dispiace davvero per quello.Ma ora si può vedere lavorare 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) { } 
}); 

Operazioni con le forme e contenitori forma dovrebbe darvi prossima JSON stringa

"{" Form1 ": {" Prop1" : "Value1", "prop2": "Value2"}, "Form2": { "Prop1": "Value1", "prop2": "Value2"}}"

E il vostro m odel legante sarà in grado di risolvere questo, se si cambia la vostra firma azione

azione

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

e dovrebbe funzionare. funziona nel mio esempio di prova

+0

Puoi caricare il tuo progetto di esempio, forse? Quando chiamo la funzione serializeArray sul mio modulo ottengo una matrice di oggetti, e nel tuo codice sopra hai dato più proprietà per modulo (prop1 e prop2) –

+0

@StefanKoenen Ho aggiornato la mia risposta e ho allegato la demo di fiddle – Baximilian

Problemi correlati