我可以使用部分视图在ASP.NET MVC中编辑多个模型吗?

时间:2013-11-29 04:46:11

标签: asp.net-mvc-4 razor

我是ASP.NET MVC 4的新手,我正在努力学习一个在webforms中很容易的概念。因此,如果我有一个Customer类,并且客户有一个地址,那么如何在同一个提交操作中编辑同一表单上的客户和地址?我想为地址创建一个'_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; }
}

地址_编辑部分视图

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

2 个答案:

答案 0 :(得分:4)

要使模型绑定正常工作,您只需将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>

<强> _Edit

@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 => m.Id)会产生<input name="Id">Html.HiddenFor(m => m.Address.Id)会产生<input name="Address.Id">。第一个不会被模型绑定器选为Company的导航属性,第二个将。

简单的路线就是复制你的局部视图。但是如果它达到你的部分变得非常庞大且复杂且具有大量字段的程度,那么你可以创建一个你的实体都继承的部分基类。

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>

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

答案 1 :(得分:1)

所以你将有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

}