【问题标题】:Passing data to an EditorTemplate将数据传递给 EditorTemplate
【发布时间】:2015-11-16 10:18:57
【问题描述】:

我是学习 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; }
}

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 razor


    【解决方案1】:

    您正在使用编辑器模板作为部分视图,因此 MVC 会为 inputs 生成错误的 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());
    }
    

    【讨论】:

    • 感谢您的回复。我以前试过这个。它确实有效。我唯一的问题是 ModelState.IsValid 是假的,因为它一直说 AddressId 是必需的。当您查看 FirmModel 时,AddressId 是一个空的 Guid。我尝试在回发期间更新 AddressId,然后调用 tryUpdateModel,但 ModelState.IsValid 仍然为 false。
    • 我设法使它工作的唯一方法是,如果在 HttpGet 中创建 FirmModel 的实例并将 AddressId 设置为新的 Guid。然后我将这个新的firmModel 实例传递给视图。然后一切正常,因为 AddressID 已经设置。但是我想知道这是否是最好的方法,或者我是否可以在调用 EditorFor 方法时设置一个新的 Guid。
    • 在 get 方法中创建对象的新实例比在编辑器模板中更好。我还在更新的帖子中提出了更好的方法。
    • 我重新审视了您对覆盖 AddressBinder 的建议。我必须说解决方案不好。这很棒。它干净、高效且有意义。小费帽子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 2018-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多