0

我有这个模型,其中包含另一个模型的列表。然后在我看来,我的表单填写了我的主要模型的几个字段。但我希望这个表单也能够添加其他类型的 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. 他会点击提交。

我放在那里的ajax调用我可以进行接线,但是我的困惑来自我必须为编辑器模板编写的代码,然后我有点想知道我将如何创建一个新的字段(例如,对于第二个“MySubModel”......)。

任何帮助将不胜感激,我已经阅读了许多有关与此相关的主题的文章,但尚未找到此案例。谢谢!

编辑:

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

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

}
4

3 回答 3

1

我已经浏览了许多有关与此相关的主题的文章,但尚未找到此案例。

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

您也可以仅在客户端仅使用 javascript 执行此操作。Steven Sanderson 在this similar article.

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

于 2013-03-12T22:07:48.243 回答
0

我最近在另一个线程上几乎回答了这个确切的问题:

ASP.Net MVC4 将“创建视图”绑定到包含列表的模型

于 2014-08-04T20:30:47.400 回答
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);

    }
}  
于 2013-03-12T23:46:45.540 回答