【问题标题】:Can I edit multiple models in ASP.NET MVC using Partial Views?我可以使用局部视图在 ASP.NET MVC 中编辑多个模型吗?
【发布时间】:2013-11-29 04:46:11
【问题描述】:

我是 ASP.NET MVC 4 的新手,我正在为一个在 web 表单中很容易的概念而苦苦挣扎。那么,如果我有一个客户类,并且一个客户有一个地址,我如何在同一个提交操作中在同一个表单上编辑客户和地址?我想为地址创建一个“_Edit”部分视图,但如果地址没有提交按钮,我不知道如何连接控制器。我只想要一个按钮来将所有模型保存在一个视图中。

所以,我可以创建一个新的 CompanyView 模型、视图和控制器,并按照这种方式进行操作。但是,如果我有许多具有地址的对象,那么继续创建视图模型以允许您以相同的形式编辑对象和地址似乎需要做很多工作。有没有办法创建地址部分编辑视图并以某种方式更新公司编辑控制器中的地址字段?或者,它是否以某种方式将 model.Address 传递回 Company Edit Controller 而不是 null?

编辑:

模型

public class Address
{
    public Int32 Id { get; set; }

    [Display(Name = "Address 1")]
    public String Address1 { get; set; }

    [Display(Name = "Address 2")]
    public String Address2 { get; set; }

    [Display(Name = "City")]
    public String City { get; set; }

    [Display(Name = "State")]
    public String State { get; set; }

    [Display(Name = "Postal Code")]
    public String PostalCode { get; set; }

    [Display(Name = "Country")]
    public String Country { get; set; }
}

public class Company
{
    public Int32 Id { get; set; }

    [Display(Name = "Company Name")]
    public String Name { get; set; }

    public Int32 AddressId { get; set; }

    public virtual Address Address { get; set; }
}

地址_编辑部分视图

@model Models.Address

<div class="well">
    <fieldset>
        <legend>Address</legend>

        @Html.EditorFor(model => model.Address1)
        @Html.EditorFor(model => model.Address2)
        @Html.EditorFor(model => model.City)
        @Html.EditorFor(model => model.State)
        @Html.EditorFor(model => model.PostalCode)
        @Html.EditorFor(model => model.Country)
    </fieldset>
</div>

公司编辑视图

@model Models.Company

@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/shared/ContentLayout.cshtml";
}


<div class="row">
    <div class="col-lg-12">
        <div class="page-header">
            <h2>Edit Company</h2>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-lg-8">
@using (Html.BeginForm("Edit", "Company", new { @class = "bs-example form-horizontal" })) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    @Html.HiddenFor(model => model.Id)

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

    @Html.HiddenFor(model => model.AddressId)

    @Html.Partial("~/Views/Address/_Edit.cshtml", Model.Address)

        <p>
            <button name="button" type="submit" class="btn btn-primary" value="submit">Submit</button>
        </p>
}

    </div>
</div>

公司编辑控制器

[HttpPost]
        public ActionResult Edit(Company model, int id)
        {
            if (ModelState.IsValid)
            {
                // model.Address = NULL here!

                Success("Record updated!");
                return RedirectToAction("Index");
            }
        }

【问题讨论】:

    标签: asp.net-mvc-4 razor


    【解决方案1】:

    要使模型绑定正常工作,您只需将Company 发回控制器即​​可。只需将您的整个模型传递到您的部分:

    @model Models.Company
    
    @{
        ViewBag.Title = "Edit";
        Layout = "~/Views/shared/ContentLayout.cshtml";
    }
    
    <div class="row">
        <div class="col-lg-12">
            <div class="page-header">
                <h2>Edit Company</h2>
            </div>
        </div>
    </div>
    
    <div class="row">
        <div class="col-lg-8">
            @using (Html.BeginForm("Edit", "Company", new { @class = "bs-example form-horizontal" })) {
                @Html.AntiForgeryToken()
                @Html.ValidationSummary(true)
    
                @Html.HiddenFor(model => model.Id)
    
                @Html.EditorFor(model => model.Name)
    
                @Html.HiddenFor(model => model.AddressId)
    
                @Html.Partial("~/Views/Address/_Edit.cshtml", Model)
    
                <p>
                    <button name="button" type="submit" class="btn btn-primary" value="submit">Submit</button>
                </p>
            }
        </div>
    </div>
    

    _编辑

    @model Models.Company
    
    <div class="well">
        <fieldset>
            <legend>Address</legend>
            @Html.HiddenFor(model => model.Address.Id)
            @Html.EditorFor(model => model.Address.Address1)
            @Html.EditorFor(model => model.Address.Address2)
            @Html.EditorFor(model => model.Address.City)
            @Html.EditorFor(model => model.Address.State)
            @Html.EditorFor(model => model.Address.PostalCode)
            @Html.EditorFor(model => model.Address.Country)
        </fieldset>
    </div>
    

    控制器

    [HttpPost]
    public ActionResult Edit(Company model, int id)
    {
        if (ModelState.IsValid)
        {
            // model.Address should now be available
    
            Success("Record updated!");
            return RedirectToAction("Index");
        }
    }
    

    您现在应该看到模型的Address 导航属性正确绑定在帖子上。


    根据评论中的问题进行编辑

    如何设置视图和局部视图完全取决于您。要记住的重要一点是,模型绑定基于 HTML 助手给表单元素的名称工作。

    所以Html.HiddenFor(m =&gt; m.Id) 将导致&lt;input name="Id"&gt;Html.HiddenFor(m =&gt; m.Address.Id) 将导致&lt;input name="Address.Id"&gt;。第一个不会被模型绑定器拾取为Company 的导航属性,第二个会。

    简单的方法是复制局部视图。但是,如果它达到了您的部分变得非常大且具有大量字段的复杂程度,您可以创建两个实体都继承的部分基类。

    BaseEntityWithAddress.cs

    public partial class BaseEntityWithAddress
    {
        public virtual Address Address { get; set; }
    }
    

    客户.cs

    public class Customer : BaseEntityWithAddress
    {
        // your properties, no need to redefine Address here
    }
    

    Vendor.cs

    public class Vendor: BaseEntityWithAddress
    {
        // your properties, no need to redefine Address here
    }
    

    然后您的局部视图会将BaseEntityWithAddress 作为模型,您仍会将整个模型传递给该模型。

    _Edit.cshtml

    @model Models.BaseEntityWithAddress
    
    <div class="well">
        <fieldset>
            <legend>Address</legend>
            @Html.HiddenFor(model => model.Address.Id)
            @Html.EditorFor(model => model.Address.Address1)
            @Html.EditorFor(model => model.Address.Address2)
            @Html.EditorFor(model => model.Address.City)
            @Html.EditorFor(model => model.Address.State)
            @Html.EditorFor(model => model.Address.PostalCode)
            @Html.EditorFor(model => model.Address.Country)
        </fieldset>
    </div>
    

    这将生成具有正确名称的表单元素,供模型绑定器拾取。

    【讨论】:

    • 好的,行得通!所以,假设我有一个客户和供应商,都需要一个地址,你说你会为客户和供应商复制“_Edit”视图?您会将这些命名为 _EditCustomer 和 _EditVendor 还是仅命名为 _Edit?有没有办法为地址编写通用的部分编辑视图,以便我对所有具有地址的对象只有一个部分编辑视图?
    • 感谢您的深入解释!这帮助我了解模型绑定。
    • 如果公司有多个地址怎么办?并且它们被保存为公司模型中的地址集合?部分如何知道要加载哪一个?
    【解决方案2】:

    所以你会有 2 个类:

    class Address
    {
        public string street {get;set;}
        public string state {get;set;}
    }
    
    class Customer
    {
        public string name {get;set;}
        public Address address {get;set;} // links to the above class.
    }
    

    您的主要客户视图类似于:

    @model Models.Customer
    
    @using (Html.BeginForm() 
    {
    
       @Html.TextBoxFor(m => m.name)
    
       @Html.Partial("_Edit", Model.address)
    
       <button type="submit">Submit</button>
    
    }
    

    你的部分:

    @model Models.Address
    
    @Html.TextBoxFor(m => m.street)
    @Html.TextBoxFor(m => m.state)
    

    然后在你的控制器中:

    public ActionResult customer(Customer model)
    {
        // do whatever
    
    }
    

    【讨论】:

    • 这几乎是我尝试做的事情,除非我在控制器中检查 Customer 模型。 model.Address 为空。
    • 将您尝试过的内容添加到您的问题中很有用。这样人们就可以更好地了解您所处的位置。
    猜你喜欢
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    相关资源
    最近更新 更多