【问题标题】:Posting/Binding multiple forms on backend ASP.NET MVC (MEF)在后端 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/…。但我找不到如何改变那个值。这就是我自己发现的,当然欢迎其他解决方案:)。

标签: javascript jquery ajax asp.net-mvc model-binding


【解决方案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)
    猜你喜欢
    • 2011-06-29
    • 2017-01-18
    • 2023-04-09
    • 1970-01-01
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 2011-08-21
    相关资源
    最近更新 更多