将数据传递给 EditorTemplate

Passing data to an EditorTemplate

我是学习 MVC 的新手,非常感谢您的帮助。我有两个模型,公司和地址。我试图有一个简单的表格,有人可以在其中添加公司详细信息。

加载公司表单时,将呈现包含地址模型的编辑器模板。我遇到的问题很简单。我什至在堆栈溢出时看到了它的解决方案,但在我的情况下它不会工作(奇怪)。当我将新的 Innuendo.Models.AddressModel() 传递给地址模板时,在回发期间 ModelState.IsValid 为假并且 Model.Address 仍设置为空。我究竟做错了什么?

公司观点

@model Innuendo.Models.FirmModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>FirmModel</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        <div>
            @Html.Partial("~/Views/shared/EditorTemplates/_Address.cshtml", new Innuendo.Models.AddressModel())
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.LogoPath)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LogoPath)
            @Html.ValidationMessageFor(model => model.LogoPath)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

编辑器模板_地址

@model Innuendo.Models.AddressModel
<div class="editor-label">
    @Html.LabelFor(model => model.HouseName)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.HouseName)
    @Html.ValidationMessageFor(model => model.HouseName)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Street)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Street)
    @Html.ValidationMessageFor(model => model.Street)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Town)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Town)
    @Html.ValidationMessageFor(model => model.Town)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.County)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.County)
    @Html.ValidationMessageFor(model => model.County)
</div>

公司负责人

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(FirmModel firmmodel)
{
    if (ModelState.IsValid)
    {

        firmmodel.FirmId = Guid.NewGuid();    
        db.Firms.Add(firmmodel);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(firmmodel);
}

公司模型

[Table("Firms")]
public class FirmModel
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public Guid FirmId { get; set; }

    [Display(Name = "Firm Name")]
    [Required]
    [StringLength(250)]
    public string Name { get; set; }

    [Required]
    public virtual AddressModel Address { get; set; }

    [StringLength(250)]
    public string LogoPath { get; set; }
}

地址模型

[Table("Addresses")]
public class AddressModel
{
    [Key]
    [HiddenInput(DisplayValue = false)]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public Guid AddressId { get; set; }

    [Required]
    [Display(Name = "House Name/Number")]

    [StringLength(250)]
    public string HouseName { get; set; }

    [StringLength(250)]
    [Required]
    public string Street { get; set; }

    [StringLength(250)]
    [Required]
    public string Town { get; set; }

    [StringLength(250)]
    [Required]
    public string County { get; set; }
}

您正在使用编辑器模板作为局部视图,因此 MVC 为 input 生成了错误的 ID,并且模型绑定器无法绑定地址的属性。要解决此问题,请先将 _Address.cshtml 重命名为 Address.cshtml 以匹配类型名称。第二次替换

@Html.Partial("~/Views/shared/EditorTemplates/_Address.cshtml", new Innuendo.Models.AddressModel())

@Html.EditorFor(model=>model.Address)

或者如果您的视图名称与类型名称不匹配。您也可以显式设置模板名称:

@Html.EditorFor(model=>model.Address,"_Address")

如您所见,您无需编写模板或视图的完整路径,因为 MVC 知道在哪里可以找到它们。

并且如果 AddressId 生成模型状态错误,并且您不想使用没有 AddressId 的视图模型,您可以编写自定义模型绑定器以在绑定时注入新的 GUID。

public class AddressBinder:DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.PropertyType == typeof(Guid))
            ((Address)bindingContext.Model).ID = Guid.NewGuid();
        else
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
    }
}

并在 Global.asax.cs

中注册您的模型活页夹
protected void Application_Start()
{
    // other codes

    ModelBinders.Binders.Add(typeof(Address), new AddressBinder());
}