Posting / binding multiple forms on the backend ASP.NET MVC (MEF)

We are trying to submit multiple forms with one Ajax call (jQuery) to an ASP application.

We use the following jQuery code:

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

On the server, we get the following in the Request.Form property:

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

We usually use the following method, so ASP automatically creates an object with the correct property value:

 public ActionResult CreateModel(ClassForForm1 obj) 

But since the two forms are sent together, modelbinder cannot bind and build the class. Therefore, for this action, we want the builder to use the values ​​in Request.Form ["Form1"].

We cannot use a custom mediator, because we use an external library (DevExpress, they wrote their own implementation above this).

We use the MEF structure to add functionality (these functions are added as forms per view). For this reason, we do not know what to expect from the backend. Therefore, writing a ViewModel shell is unacceptable.

Functionality for processing data of other forms will be stored inside other modules.

Any solutions are welcome!

Thanks in advance.

+7
javascript jquery ajax asp.net-mvc model-binding
source share
3 answers

This is usually done using a combined representation model. Otherwise, you need to manually analyze the query parameters. Here is a fiddle showing how to combine data from multiple forms.

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

On the server, your view model will require:

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

And your action signature:

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

See Best way to clone scattered object properties for the CloneMatching extension method.

+1
source share

If you create a javascript object as follows:

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

The controller must match the name 'obj' that you created in javascript using 'obj' in your method ....

  public ActionResult CreateModel(ClassForForm1 obj) 
+1
source share

My previous sample worked only because my class has name and value details. I'm very regret about it. But now you can see 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) { } }); 

Operations with forms and form container should give you the following json line

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

And your connecting device can solve this problem if you change the action signature

Act

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

And that should work. it works in my test sample

+1
source share

All Articles