我正在开发一个应用程序来跟踪通过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
我已经遵循了这些建议,但这对我不起作用。
我很感激有任何帮助解决这个问题。