使用ASP.NET模型绑定在视图模型中绑定列表

时间:2014-06-10 05:02:39

标签: list asp.net-mvc-4 model-binding

我正在开发一个应用程序来跟踪通过Web应用程序发出的订单。该应用程序不会销售产品,它旨在通过电话跟踪订单。

我还是ASP.NET MVC的新手,所以我还在学习绳索。我正在尝试使用模型绑定来实现这一点。

这是我的视图模型

public class OrderDetailViewModel
    {
        public Order Order { get; set; }
        public List<OrderLine> OrderLinesList { get; set; }
        public OrderDetailViewModel()
        {
            this.Order = new Order();
            List<OrderLine> OrderLines = new List<OrderLine>();
            OrderLines = new List<OrderLine>();
            OrderLines.Add(new OrderLine());
            this.OrderLinesList = OrderLines;
        }
        public OrderDetailViewModel(Order order)
        {
            this.Order = order;
        }

        public string SalesRepName
        {
            get
            {
                ApplicationDbContext db = new ApplicationDbContext();
                ApplicationUser Rep = db.Users.First(u => u.UserName == Order.SalesRep);
                return Rep.FirstName + " " + Rep.LastName;
            }
        }

        public IEnumerable<SelectListItem> CustomerList
        {
            get
            {
                var Db = new OrderContext();
                var Customers = Db.Customers;
                var AllCustomers = Customers.Select(c => new SelectListItem
                {
                    Value = c.Id.ToString(),
                    Text = c.FirstName + " " + c.LastName
                });

                return AllCustomers;
            }
        }

        public IEnumerable<SelectListItem> ProductList
        {
            get
            {
                var Db = new OrderContext();
                var Products = Db.Products;
                var AllProducts = Products.Select(p => new SelectListItem
                {
                    Value = p.Id.ToString(),
                    Text = p.Name + ", " + p.Airshow + " - " + p.AirshowDate
                });

                return AllProducts;
            }
        }
    }

以下是OrderLine的数据模型:

public class OrderLine
{
    [Key]
    public int Id { get; set; }
    [Required, Display(Name="Order Number")]
    public int OrderId { get; set; }
    [Required]
    public int ProductId { get; set; }
    [Required]
    public int Quantity { get; set; }
    [Required]
    [DisplayFormat(ApplyFormatInEditMode=true, DataFormatString="{0:C}")]
    public float Price { get; set; }
    [Required, Display(Name="Tax Rate"), DisplayFormat(DataFormatString="{0:P}")]
    public float TaxRate { get; set; }
    public Nullable<float> Discount { get; set; }

    public virtual Product Product { get; set; }
    public virtual Order Order { get; set; }
}

这是视图:

@model AirshowCouponsMvc.Models.OrderDetailViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>OrderDetailViewModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <table class="table table-striped table-responsive table-hover">
            <tr>
                <th colspan="2">Order Date: @Html.Label(String.Format("{0:MMMM d, yyyy}", DateTime.Now))</th>
                <th colspan="2">Customer: @Html.DropDownListFor(model => model.Order.CustomerId, Model.CustomerList)</th>
            </tr>
            <tr>
                <th>
                    @Html.LabelFor(model => model.Order.OrderLines.FirstOrDefault().Product)
                </th>
                <th>
                    @Html.LabelFor(model => model.Order.OrderLines.FirstOrDefault().Quantity)
                </th>
                <th>
                    @Html.LabelFor(model => model.Order.OrderLines.FirstOrDefault().TaxRate)
                </th>
                <th>
                    @Html.HiddenFor(model => model.OrderLinesList)
                </th>
            </tr>
            @foreach (AirshowCouponsMvc.Models.OrderLine item in Model.OrderLinesList)
            {
                <tr>
                    <td>
                        @Html.DropDownListFor(model => item.ProductId, Model.ProductList)
                    </td>
                    <td>
                        @Html.EditorFor(model => item.Quantity)
                    </td>
                    <td>
                        @Html.EditorFor(model => item.TaxRate)
                    </td>
                    <td>
                        @Html.HiddenFor(model => item.Price)
                        @Html.HiddenFor(model => item.OrderId)
                        @Html.HiddenFor(model => item.Id)
                        @Html.HiddenFor(model => item.Discount)
                        @Html.HiddenFor(model => item.Order)
                        @Html.HiddenFor(model => item.Product)
                    </td>
                </tr>
            }
            <tr>
                <td></td>
                <td>@Html.ActionLink("Add line", "AddLine")</td>
                <td>@if (Model.OrderLinesList.Count > 1) { @Html.ActionLink("Remove line", "RemoveLine") }</td>
            </tr>
        </table>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10 pull-right">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

最后,这是控制器的代码:

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(OrderDetailViewModel model)
        {
            if (ModelState.IsValid)
            {
                OrderContext db = new OrderContext();
                model.Order.OrderDate = DateTime.Now;
                model.Order.SalesRep = User.Identity.Name;
                db.Orders.Add(model.Order);
                foreach (var line in model.Order.OrderLines)
                {
                    line.Price = line.Product.Price;
                    line.Discount = OrderDetailViewModel.DiscountRate(line.Quantity);
                    line.OrderId = model.Order.Id;
                    db.OrderLines.Add(line);
                }
                return RedirectToAction("Index");
            }
            return View(model);
        }

是的,我知道控制器不处理列表。我曾使用数据模型中的属性,然后我读到你需要在视图模型中将List定义为属性。我正在将其更改为此,但是当我在Create操作开始时休息时,我注意到OrderLinesList为null。

另外,我读到在早期版本的ASP.NET MVC中(至少我没有看到它参考更新版本的ASP.NET MVC)你必须使用for循环而不是foreach循环。我试过去那条路,但我仍然遇到了一个空列表的问题。

这是我在Create视图中尝试作为for循环的代码。插入此代替当前显示的foreach循环:

@for (int i = 0; i < Model.OrderLines.Count(); i++)
        {
            <tr>
                <td>
                    @Html.DropDownListFor(model => model.OrderLines[i].ProductId, Model.ProductList)
                </td>
                <td>
                    @Html.EditorFor(model => model.OrderLines[i].Quantity)
                </td>
                <td>
                    @Html.EditorFor(model => model.OrderLines[i].TaxRate)
                </td>
                <td>
                    @Html.HiddenFor(model => model.OrderLines[i].Id)
                    @Html.HiddenFor(model => model.OrderLines[i].Price)
                    @Html.HiddenFor(model => model.OrderLines[i].Discount)
                    @Html.HiddenFor(model => model.OrderLines[i].OrderId)
                    @Html.HiddenFor(model => model.OrderLines[i].Order)
                    @Html.HiddenFor(model => model.OrderLines[i].Product)
                </td>
            </tr>
        }

我的最终目标是能够跟踪每个订单的多个订单项,最好使用模型绑定。

我已经阅读了很多参考资料,试图让它发挥作用,包括:

http://seesharpdeveloper.blogspot.com/2012/05/mvc-model-binding-to-list-of-complex.html

Model binding generic list is null in asp.net mvc

MVC3 Non-Sequential Indices and DefaultModelBinder

ASP.NET MVC 4 - for loop posts model collection properties but foreach does not

我已经遵循了这些建议,但这对我不起作用。

我很感激有任何帮助解决这个问题。

0 个答案:

没有答案