ASP MVC 3.0复杂视图

时间:2011-09-23 00:19:20

标签: asp.net-mvc razor

我正在使用ASP.NET MVC 3.0开发销售订单管理应用程序。我需要开发一个可以添加客户详细信息的页面。

客户详情包括

public class Customer
    {
        public int ID { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public string Alias { get; set; }
        public int DefaultCreditPeriod { get; set; }        
        public Accounts Accounts { get; set; }
        public IList<Address> Addresses { get; set; }
        public IList<Contact> Contacts { get; set; }
    }

public class Accounts
    {
        public int ID { get; set; }
        public string VATNo { get; set; }
        public string CSTNo { get; set; }
        public string PANNo { get; set; }
        public string TANNo { get; set; }
        public string ECCNo { get; set; }
        public string ExciseNo { get; set; }
        public string ServiceTaxNo { get; set; }
        public bool IsServiceTaxApplicable { get; set; }
        public bool IsTDSDeductable { get; set; }
        public bool IsTCSApplicable { get; set; }
    }

public class Address 
    {
        public int ID { get; set; }
        public AddressType Type { get; set; }        
        public string Line1 { get; set; }
        public string Line2 { get; set; }
        public string Line3 { get; set; }
        public string Line4 { get; set; }
        public string Country { get; set; }
        public string PostCode { get; set; }
    }

public class Contact
    {
        public int ID { get; set; }
        public ContactType Type { get; set; }
        public string Name { get; set; }
        public string Title { get; set; }
        public string PhoneNumber { get; set; }
        public string Extension { get; set; }
        public string  MobileNumber { get; set; }
        public string EmailId { get; set; }
        public string FaxNumber { get; set; }
        public string Website { get; set; }
    }

客户需要一个页面来填写所有客户详细信息(常规信息,帐户信息,地址信息和联系信息)。将有多个地址(结算,发货等)和多个联系人(销售,购买)。我是MVC的新手。如何创建上面的视图并动态添加多个地址?

3 个答案:

答案 0 :(得分:1)

我经常创建包装模型来处理这种情况,例如

public class CustomerWrapperModel
{
    public Customer Customer { get; set;}
    public Accounts Accounts { get; set;}
    public List<Address> AddressList { get; set}

    //Add
    public CustomerWrapperModel()
    {

    }

    //Add/Edit
    public CustomerWrapperModel(Customer customer, Accounts accounts, List<Address> addressList)
    {
        this.Customer = customer;
        this.Accounts = accounts;
        this.AddressList = addressList;
    }
}

然后将View声明为CustomerWrapperModel类型并使用如下编辑器:

@model MyNamespace.CustomerWrapperModel

@Html.EditorFor(model => model.Customer)
@Html.EditorFor(model => model.Accounts)
@Html.EditorFor(model => model.AddressList)

并有一个控制器来接收如下所示的帖子:

[HttpPost]
public ActionResult(Customer customer, Accounts accounts, List<Address> addressList)
{
   //Handle db stuff here
}

就动态添加地址而言,如果您使用MVC验证并希望使用正确的列表索引正确地保持列表结构,以便您可以在控制器中使用List参数,那么我找到了执行此操作的最佳方法。将当前地址发布到辅助控制器,如下所示:

[HttpPost]
public PartialResult AddAddress(List<Address> addressList)
{
   addressList.Add(new Address);

   return PartialView(addressList);
}

然后有一个局部视图,只是再次渲染地址字段:

@model List<MyNamespace.Address>

@{
    //Hack to get validation on form fields
    ViewContext.FormContext = new FormContext();
}

@Html.EditorForModel()

确保您的地址字段都在一个容器中,然后您可以使用返回的数据覆盖现有字段,并在底部附加新的地址字段。更新容器后,您可以执行以下操作来重新连接验证:

       var data = $("form").serialize(); 

       $.post("/Customer/AddAddress", data, function (data) {

            $("#address-container").html(data);

            $("form").removeData("validator");
            $("form").removeData("unobtrusiveValidation");
            $.validator.unobtrusive.parse("form");

        });

NB。我知道有些人有这样做的问题,因为它需要服务器端点击添加字段到一个页面,可以很容易地添加到客户端(我总是用它来做所有客户端但是尝试了一次这个方法,从来没有回去)。我这样做的原因是因为它是保持列表项上的索引正确的最简单方法,特别是如果你有插入和添加,你的对象有很多属性。此外,通过使用局部视图来呈现数据,您可以确保在开箱即用的新字段上生成验证,而不必手动为新添加的客户端字段进行验证。在大多数情况下,权衡是在ajax请求期间传输的少量数据。

您也可以选择使用发送到AddAddress控制器的字段进行更精炼,因为您可以看到我只是将整个表单发布到控制器并忽略除地址字段之外的所有内容,我使用的是快速服务器和附加服务器(较小的)不需要的表单字段的开销与我可能以更高带宽有效的方式浪费编码此类功能的时间相比可以忽略不计。

答案 1 :(得分:0)

您将根模型对象传递给控制器​​中的View调用,如下所示:

public ActionResult Index() {
   var customer = GetCustomer(); // returns a Customer
   return View(customer);
}

然后你的观点看起来像这样:

@model Customer

<!DOCTYPE html>
<!-- etc., etc. -->
<h1>Customer @Model.Name</h1>
<ul>
@foreach (var address in Model.Addresses) {
   <li>@address.Line1</li>
}
</ul>

一个人得到了照片。

上面的代码取决于@model指令,它是ASP.NET MVC 3中的新指令(参见this blog post)。

答案 2 :(得分:0)

这是一个很好的问题:对于正常的导航属性,例如Accounts执行此操作的D并不难:

@Html.EditorFor(model => model.Accounts.ID)

@Html.EditorFor(model => model.Accounts.VATNo)

会做你想做的事。但是对于集合导航属性(AddressesContacts),默认情况下不能在一个位置执行此操作。我建议你为Addresses使用不同的页面(Contacts使用一个页面)。因为这是最简单的方法。但是如果你想在一个地方(以及没有AJAX请求)这样做,你可以通过Customer创建视图,使用 scaffolding 来创建模型,它是简单导航属性,对于列表(AddressesContacts),您必须将 JavaScript 添加到input字段(对于添加的每个Address的示例,将其放入Array)并将字段发布到服务器。在服务器上,您可以通过默认的模型绑定器获取主模型和简单属性,对于列表,您可以1)创建自己的模型绑定器2)自己从输入的字符串中解析它们。好锁