在后端 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 的替代品

ASP.Net MVC 3 中的多项目区域

Asp.NET MVC 核心 CORS

C# ASP.NET MVC:动态更新视图

具有插件和多租户支持的 ASP.NET MVC 应用程序以及单独的 AppDomains?

防止在后端ASP.NET Core 3中提交双重形式的提交。*