具有模型列表的Model的MVC客户端验证

时间:2013-03-12 22:06:07

标签: asp.net-mvc

我有这个模型,其中包含另一个模型的列表。然后在我看来,我的表单填充了我的主要模型的几个字段。但我希望这个表格能够添加其他类型的X模型并且全部接线,我想知道如何正确地做到这一点。

所以这是我的两个模型:

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/MySubModels.cshtml中设置(命名为我的“MyMainModel”的属性),然后当我在那里写我的表格时,我很困惑......

@model myFunProject.WebModels.MyMainModel

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

所以在这里我不知道该放什么......我希望我的Name属性是“MySubModel”。当用户看到这种形式时,比方说他会经历这种情况:

  1. 输入“MyMainModel”的名称。
  2. 转到其他名称框并填写“MySubModel”的第一个实例的名称。
  3. 然后他会点击一个特殊的按钮来操作dom来附加另一个MySubModel.Name字段。
  4. 他会写第二个“MySubModel”名称。
  5. 他会点击提交。
  6. 我放在那里的ajax调用我正在接线,但是我的困惑来自我必须为编辑器模板编写的代码然后我也想知道我将如何去创建一个新字段(例如第二个“MySubModel”)。

    任何帮助都会受到赞赏,我已经阅读了很多关于这个主题的文章,但还没有找到这个案例。谢谢!

    编辑:

    我将在提交表单时添加由我的ajax调用的操作(过于简化的版本hehe)。

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

3 个答案:

答案 0 :(得分:1)

  

我已经阅读了很多关于这个主题的文章,但还没有找到这个案例。

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

您也可以仅在客户端使用javascript执行此操作。 Steven Sanderson在this similar article中使用knockoutjs说明了这种方法。

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

答案 1 :(得分: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);

    }
}  

答案 2 :(得分:0)

我最近在另一个帖子上回答了这个确切的问题:

ASP.Net MVC4 bind a "create view" to a model that contains List