2013-03-12 107 views
0

我有这个模型有另一个模型的列表。然后在我看来,我的表格为我的主模型填充了几个字段。但我希望这种形式也能够添加其他类型的X模型,并且都是有线的,我想知道如何正确地做到这一点。具有模型列表的模型的MVC客户端验证

因此,这里有我的两个型号:

public class MyMainModel 
{ 

    public int MyMainId { get; set; } 

    [Required(ErrorMessage = "Groovy name required")] 
    [Display(Name = "MyMainModel's groovy name:")] 
    public string Name { get; set; } 

    public List<MySubModel> MySubModels { get; set; } 

} 

public class MySubModel 
{ 

    public int MySubId { get; set; } 

    [Required(ErrorMessage = "Cool name required")] 
    [Display(Name = "MySubModel's cool name:")] 
    public string Name { get; set; } 

} 

当我打我的控制器,我的“创造”的看法,我通过这个动作:

public ActionResult SomePageAboutCreating() 
{ 
    // [...] Some other stuff 
    return View(new MyMainModel()); 
} 

现在这个发送到我的强类型查看:

@model myFunProject.WebModels.MyMainModel 

<div> 
    <form id="my-create-form" onsubmit="CreateMyMainModel(this); return false;"> 
     @Html.AntiForgeryToken() 
     @Html.ValidationSummary() 

     <div class="result" style="background-color: silver;">This is the operation result box</div> 
     <img class="loading" src="/Images/ajax-loader.gif" alt="Loading..." width="16" height="16" style="display: none;" /> 

     <section> 
      @Html.LabelFor(m => m.Name) 
      @Html.TextBoxFor(m => m.Name) 
      @Html.ValidationMessageFor(m => m.Name) 
     </section> 

     <!-- Here begins the fields for my list of "MySubModel" --> 
     @Html.EditorFor(x => x.MySubModels) 

     <!-- Here I'm thinking about a javascript that will add the previous fields X times so that the user can create "MyMainModel" as well as x times "MySubModel"... --> 

     <input type="submit" class="btn-send" id="my-create-form-submit" value="Send" /> 
    </form> 
</div> 

所以我想我必须在这里使用EditorTemplates ...所以我安装在我的/ Views/EditorTemplates/MySub Models.cshtml(命名反对我“MyMainModel”的属性),然后当我写我的形式在那里,我很困惑...

@model myFunProject.WebModels.MyMainModel 

@*<section> 
    @Html.LabelFor(m => m.Name) 
    @Html.TextBoxFor(m => m.Name) 
    @Html.ValidationMessageFor(m => m.Name) 
</section>*@ 

所以在这里我不知道要放什么东西在这里...我希望我的名称属性是“MySubModel”之一。当用户看到这个表单时,比如说他会经历这种情况:

  1. 输入“MyMainModel”的名称。
  2. 转到其他人的名字框和在“MySubModel的第一个实例的名称罢了。
  3. 然后,他会点击一个特殊的按钮,将操作DOM追加另一MySubModel.Name场。
  4. 他会写在第二个“MySubModel”的名字。
  5. 他会点击提交。

AJAX调用我摆在那里我确定做配线,但我的困惑带有我编写的代码编辑器模板,然后我有点想知道我将如何创建一个新的领域(第二个“MySubModel”例如...)。

任何帮助将不胜感激,我已经通过了许多关于这个主题的文章,但还没有发现这种情况。谢谢!

编辑:

我会添加动作(过于简化的版本,嘿嘿)由我的阿贾克斯提交表单时调用。

public ActionResult CreateMyMainModel(MyMainModel myMainModel) { 

    // [...] Do stuff like save to database... 
    // var aGroovyNAme = myMainModel.Name; 

    foreach(var mySubModel in myMainModel.MySubModels) { 
     // Here I would have the sub models available to manipulate... 
     // var aCoolName = mySubModel.Name; 
    } 
    return Content("ok"); 

} 
+0

的[ASP.Net MVC4绑定“创建视图”到包含列表中选择模型]可能的复制(http://stackoverflow.com/questions/12974957/asp-net-mvc4-bind-a-create-view-to-a-model-that-c​​ontains-list) – halfer 2016-02-14 21:36:49

+0

我已经添加了一个dup建议基于来自@Savantes的回答。 – halfer 2016-02-14 21:37:09

回答

1

我已经通过有关科目接近这个文章很多了,但没有发现这种情况呢。

我真的建议你阅读从史蒂芬·桑德森的editing a variable length list文章这说明了一个非常不错的方法来处理这种情况。他提供了一个自定义的帮助程序,可以用来为输入字段名称生成非顺序索引(guid),从而允许动态地轻松移除元素,而不会在索引中留下。当用户决定添加另一个项目时,将对控制器操作进行AJAX调用,该操作只返回空模板(部分)。

你也可以纯粹在客户端使用javascript来完成此操作。 Steven Sanderson在this similar article中使用knockoutjs说明了这种方法。

这两篇文章实际上是动态编辑ASP.NET MVC中的变量长度列表项的最佳方法。阅读它们将有助于更好地理解ASP.NET MVC中模型绑定中的一些核心概念。

+0

嗨达林,感谢您的有用的链接,我更新了我的问题的更多细节,我可以看到与史蒂文的例子的区别是,我想收到一个模型时提交表单,而不是一个列表。 (我认为至少有所不同......) – 2013-03-12 23:24:15

+0

@不,没有什么不同。唯一改变的是,你不用'IEnumerable '工作,而是使用'MyMainModel',它具有'IEnumerable '类型的属性。但是完全一样的原则适用。 – 2013-03-13 06:40:15

0

我有一个项目类似的问题,我想验证在某些情况下某些字段 ,而不是对他人(即在保存不验证,但在提交验证一切。

最后我做的一切手动javascript和回发一个JSON对象。

经过思考我宁愿操纵JavaScript文件(MicrosoftMVCValidation.js)。

对于模型的结合问题,我建议在寻找客户定制模型绑定验证。

我发现使用EditorTemplates有点烦人,尤其是局部视图。

我发现asp.net mvc 3在模型绑定方面有点弱。我希望一些问题能够在mvc 4中得到解决,但从目前我所看到的情况来看,MVC4主要是用于创建Windows Phone应用程序的升级。

下面是模型中小数属性的自定义模型联编程序示例。

您可以对自己的自定义模型使用相同的逻辑。

我发现有些场合我想将大型网页上的实体集合与模型绑定,而不是仅仅绑定基本的属性集合。

public class DecimalModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     //return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) : Convert.ToDecimal(valueProviderResult.AttemptedValue); 


     if (valueProviderResult == null) 
      return base.BindModel(controllerContext, bindingContext); 
     else if (valueProviderResult.AttemptedValue == "") 
      return base.BindModel(controllerContext, bindingContext); 
     else 
      return Convert.ToDecimal(valueProviderResult.AttemptedValue); 

    } 
}