Asp.net mvc 4 是否可以使用局部视图在ASP.NET MVC中编辑多个模型?

Asp.net mvc 4 是否可以使用局部视图在ASP.NET MVC中编辑多个模型?,asp.net-mvc-4,razor,Asp.net Mvc 4,Razor,我是ASP.NETMVC4的新手,我正在努力解决一个在webforms中很容易实现的概念。因此,如果我有一个Customer类,并且一个Customer有一个Address,那么如何在同一个提交操作中编辑同一表单上的Customer和Address?我想为地址创建一个“_Edit”部分视图,但如果地址没有提交按钮,我不知道如何连接控制器。我只需要一个按钮就可以在一个视图中保存所有模型 因此,我可以创建一个新的CompanyView模型、视图和控制器,并以这种方式进行。但是,如果我有很多对象都有地

我是ASP.NETMVC4的新手,我正在努力解决一个在webforms中很容易实现的概念。因此,如果我有一个Customer类,并且一个Customer有一个Address,那么如何在同一个提交操作中编辑同一表单上的Customer和Address?我想为地址创建一个“_Edit”部分视图,但如果地址没有提交按钮,我不知道如何连接控制器。我只需要一个按钮就可以在一个视图中保存所有模型

因此,我可以创建一个新的CompanyView模型、视图和控制器,并以这种方式进行。但是,如果我有很多对象都有地址,那么继续创建视图模型以允许您以相同的形式编辑对象和地址似乎需要做很多工作。是否有方法创建地址部分编辑视图并以某种方式更新公司编辑控制器中的地址字段?或者,让它以某种方式将model.Address传递回公司编辑控制器,而不是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; }
}
地址\u编辑局部视图

@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>

因此,您将有两个类:

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>

}
然后在控制器中:

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

}

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

@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>
现在,您应该可以在post上正确绑定模型的
地址
导航属性


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

@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>
你如何设置你的观点和部分是由你自己决定的。需要记住的重要一点是,模型绑定是基于HTML帮助程序为表单元素指定的名称工作的

因此
Html.HiddenFor(m=>m.Id)
将导致
,而
Html.HiddenFor(m=>m.Address.Id)
将导致
。第一个将不会被模型绑定器作为
公司的导航属性拾取,第二个将被拾取

简单的方法就是复制你的局部视图。但是,如果您的分部变得非常大和复杂,并且字段数量很多,那么您可以创建一个分部基类,这两个实体都继承它

BaseEntityWithAddress.cs

public partial class BaseEntityWithAddress
{
    public virtual Address Address { get; set; }
}
Customer.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>
@model Models.BaseEntityWithAddress
地址
@Html.HiddenFor(model=>model.Address.Id)
@EditorFor(model=>model.Address.Address1)
@EditorFor(model=>model.Address.Address2)
@EditorFor(model=>model.Address.City)
@EditorFor(model=>model.Address.State)
@EditorFor(model=>model.Address.PostalCode)
@EditorFor(model=>model.Address.Country)

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

这是我几乎尝试过的,除了在控制器中检查客户模型时。model.Address为空。将您尝试的内容添加到问题中非常有用。这样人们就能更好地了解你的处境。好吧,那就行了!那么,假设我有一个客户和一个供应商,都需要一个地址,你说你要为客户和供应商复制“_Edit”视图?你会把它们命名为“客户”和“供应商”还是“编辑”?有没有办法为Address编写一个通用的部分编辑视图,以便我对所有有地址的对象只有一个部分编辑视图?@Sephrial这是一个很长的答案,需要在注释中键入,因此我编辑了我的原始答案,以向您展示如何完成。感谢您的深入解释!这有助于我了解模型绑定。若公司有多个地址怎么办?它们在公司模型中保存为地址集合?分部如何知道加载哪一个?
public class Customer : BaseEntityWithAddress
{
    // your properties, no need to redefine Address here
}
public class Vendor: BaseEntityWithAddress
{
    // your properties, no need to redefine Address here
}
@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>