c# - MVC Html.DropDownListFor 返回具有空值的复杂类型
问题描述
我的控制器中有以下控制器创建操作。请注意选择列表中的显示名称将是“StoreName - StoreAddress”。Store complexType 存储在 Store 中。
// GET: Purchases/Create
public ActionResult Create()
{
ViewBag.Stores = db.Stores.Select(s => new { DisplayName = s.StoreName.ToString() + " - " + s.Address.ToString(), Store = s});
return View();
}
在 Create View 中,以下代码会确保正确显示。
<div class="form-group">
@Html.LabelFor(model => model.Store.StoreName, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.Store.StoreName, new SelectList(ViewBag.Stores, "Store", "DisplayName"), new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Store.StoreName, "", new { @class = "text-danger" })
</div>
</div>
它将转到控制器的 post 方法(如果我是正确的)。
// POST: Purchases/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Store,Price,Date")] Purchase purchase)
{
if (ModelState.IsValid)
{
Store store = purchase.Store;
db.Purchases.Add(purchase);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(purchase);
}
但是,Store store = purchase.Store 现在将给出一个复杂的 Store 类型,其中除 StoreName 之外的任何值都设置为 null。StoreName 将是一个字符串。
如何获得与所选 Store 对象相等的复杂类型返回?
编辑1:
public class Purchase
{
public int Id { get; set; }
public Store Store { get; set; }
public string Type { get; set; }
[DataType(DataType.Currency)]
[Column(TypeName = "money")]
public decimal Price { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime Date { get; set; }
}
public class PurchaseDBContext : DbContext
{
public DbSet<Purchase> Purchases { get; set; }
public DbSet<Store> Stores { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
public class Store
{
public int StoreId { get; set; }
public string StoreName { get; set; }
public string Address { get; set; }
public string City { get; set; }
[DataType(DataType.PhoneNumber)]
[RegularExpression(@"^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9])((\s|\s?-\s?)?[0-9])((\s|\s?-\s?)?[0-9])\s?[0-9]\s?[0-9]\s?[0-9]\s?[0-9]\s?[0-9]$", ErrorMessage = "This is not a valid phonenumber")]
public string PhoneNumber { get; set; }
}
我是否需要使用其他注释来设置导航属性?
解决方案
您的示例中有很多内容,但如果您使用导航属性并且您的模型以某种方式设置,则不需要传递复杂的对象。如果您为 Store/StoreId 设置导航属性,Entity Framework 应该为您推断事物,因此它将简化您的视图。
public class Purchase
{
public int StoreId { get; set; }
[ForeignKey("StoreId")]
public Store Store { get; set;}
}
我会将模型传递给类似于下面的视图。IMO,它比使用 ViewBag 更干净。
public class CreatePurchaseModel
{
//To populate a list
public List<Store> AvailableStores { get; set; }
//The actual object to be created
public Purchase Purchase { get; set; }
}
控制器方法:
// GET: Purchases/Create
public ActionResult Create()
{
var vm = new CreatePurchaseModel()
{
AvailableStores = db.Stores.ToList(),
Purchase = new Purchase()
};
return View(vm);
}
使用 AvailableStores 属性填充下拉列表以设置 Purchase.StoreId
@Html.DropDownListFor(m => m.Purchase.StoreId, Model.AvailableStores.Select(x => new SelectListItem { Text = x.StoreName.ToString(), Value = x.StoreId.ToString() }))
如果设置正确,您只需在 post 方法参数中购买
[ValidateAntiForgeryToken, HttpPost]
public ActionResult Create(Purchase purchase)
{
//purchase.StoreId should have a non zero value
db.Purchases.Add(purchase);
db.SaveChanges();
}
推荐阅读
- html - 正确使用 Bootstrap 的 justify-content-between 和 stack-to-horizontal col
- java - 我想将字符存储在一个字节数组中并将这个字节数组写入一个文件并将文件读回并输出到屏幕
- javascript - ContentEditable 没有更新虚拟 DOM
- docker - 微服务架构中 docker 容器之间的身份验证,绕过 JWT 身份验证进行内部调用
- android - 如何使用 Navigator 推送值并接收它们?
- xml - CameraX 和条码扫描仪 - 条码扫描仪无法读取
- scala - 无法将 java.util.List 转换为 Scala 列表
- xslt - 如何创建导致空节点序列的源
- javascript - 为什么 Angular 创建版本低于已安装版本的项目?
- xcode - Xcode 12 - 下载更多模拟器运行时为空