在后端 ASP.NET MVC (MEF) 上发布/绑定多个表单
Posted
技术标签:
【中文标题】在后端 ASP.NET MVC (MEF) 上发布/绑定多个表单【英文标题】:Posting/Binding multiple forms on backend ASP.NET MVC (MEF) 【发布时间】:2014-09-02 03:11:32 【问题描述】:我们正在尝试通过一次 Ajax (jQuery) 调用向 ASP 应用程序发送多个表单。
我们使用以下 jQuery 代码:
var formContainer =
Form1 : form1.serialize(),
Form2 : form2.serialize()
$.ajax(
type: "POST",
url: '@Url.Action("CreateModel", "Controller")',
data: formContainer,
success: function (result)
);
在服务器上,我们在 Request.Form 属性中收到以下内容:
Key : Value
Form1 : All serialized form elements for Form1
Form2 : All serialized form elements for Form2
通常我们使用以下方法,因此 ASP 会自动创建具有正确属性值的对象:
public ActionResult CreateModel(ClassForForm1 obj)
但是由于这两个表单是一起发送的,modelbinder 无法绑定和构建类。 因此,对于此操作,我们希望模型构建器使用 Request.Form["Form1"] 中的值。
我们不能使用自定义模型绑定器,因为我们使用外部库(DevExpress,他们在此之上编写了自己的实现)。
我们正在使用 MEF 框架来添加功能(这些功能作为表单添加到视图中)。出于这个原因,我们不知道对后端有什么期望。所以写封装 ViewModel 是不行的。
处理其他表单数据的功能将在其他模块中处理。
欢迎任何解决方案!
提前致谢。
【问题讨论】:
当您说“因此,对于此操作,我们希望模型构建器使用 Request.Form["Form1"] 中的值。”您本质上希望该请求忽略 Form2 值?还是你想在请求中为每个表单调用CreateModel,这样如果发送3个表单,CreateModel执行3次,每个表单执行一次? 是的,我们想像你说的那样“忽略” Request.Form["Form2"] 中的值。 我尝试更改自定义模型绑定器中的 Request.Form 值,但它正在从 IUnvalidatedprovider 读取值。虽然这是此页面上的最后一个代码(在静态函数中):blogs.taiga.nl/martijn/2011/09/29/…。但我找不到如何改变那个值。这就是我自己发现的,当然欢迎其他解决方案:)。 【参考方案1】:这通常使用组合视图模型来完成。否则,您将需要手动解析请求参数。这是一个fiddle,展示了如何组合来自多个表单的数据。
$(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);
);
);
);
在服务器上,您的视图模型需要:
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;
还有你的动作签名:
[HttpPost]
public ActionResult Index(IndexViewModel model)
var firstModel = (new First()).CloneMatching(model);
var lastModel = (new Last()).CloneMatching(model);
return RedirectToAction("Thanks");
请参阅 Best way to clone properties of disparate objects 了解 CloneMatching 扩展方法。
【讨论】:
你也可以在视图模型类上使用合成,例如@Html.EditorFor(model => model.Form1.first)
。【参考方案2】:
如果你像这样创建你的 javascript 对象:
var formContainer = obj :
Form1 : form1.serialize(),
Form2 : form2.serialize()
控制器应将其与您在 javascript 中创建的名称“obj”与方法中的“obj”相匹配....
public ActionResult CreateModel(ClassForForm1 obj)
【讨论】:
【参考方案3】:我之前的示例之所以有效,是因为我的班级有名称和价值道具。我真的很抱歉。但是现在你可以看到工作了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)
);
表单和表单容器的操作应该给你下一个 json 字符串
""Form1":"Prop1":"Value1","Prop2":"Value2","Form2":"Prop1":"Value1","Prop2":"Value2""
如果你改变你的动作签名,你的模型绑定器将能够解决这个问题
动作
public ActionResult CreateModel(ClassForForm1 Form1) //argument name must be equal to data property
//but not equal to class name
它应该可以工作。它适用于我的测试样本
【讨论】:
你能上传你的示例项目吗?当我在表单上调用 serializeArray 函数时,我得到一个对象数组,并且在上面的代码中,您为每个表单提供了多个属性(prop1 和 prop2)以上是关于在后端 ASP.NET MVC (MEF) 上发布/绑定多个表单的主要内容,如果未能解决你的问题,请参考以下文章
.NET Core(或 ASP.NET 5)中是不是有 MEF 的替代品