.NET EF 4.7.2 MVC Create方法转换子表单提交
.NET EF 4.7.2 MVC Create method converts child form submission
我正在尝试为我的 PC 组件 ASP.NET MVC 应用程序实现一个创建功能,使用 EF 4.7.2 和继承来在一个方法中处理所有派生的 classes。
问题是提交 Component_CreateCPU.cshtml
表单将 CPU
的派生 class 转换为其在 /Components/Create
中的基础 class Component
动作。
我测试了在 Index()
中实例化一个新的 CPU
对象并将其传递给 Create()
方法,它保留了派生的 class.
有什么方法可以提交视图表单并确保派生的 class 被传入?
型号classes:
public class Component : Interfaces.IComponent
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[DisplayName("Name")]
public string Name { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
[DisplayName("Price")]
public decimal Price { get; set; }
public Manufacturer Manufacturer { get; set; }
}
public class CPU : Component
{
[DisplayName("Core Count")]
public int CoreCount { get; set; }
[DisplayName("Core Clock")]
public string CoreClock { get; set; }
}
创建局部视图
_Component_CreateCPU.cshtml
:
@model PCDB.Models.Components.CPU
@using (Html.BeginForm("Create", "Components", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CPU</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CoreCount, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CoreCount, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CoreCount, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CoreClock, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CoreClock, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CoreClock, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
ComponentsController
:
public class ComponentsController : Controller
{
private readonly IComponentRepository<Component> _componentRepository;
public ComponentsController()
{
_componentRepository = new ComponentsRepository<Component>();
}
public ActionResult Index()
{
return View(_componentRepository.GetAll());
}
[Authorize(Roles = "Admin")]
public ActionResult Create()
{
return View(new ComponentCreateViewModel());
}
[Authorize(Roles = "Admin")]
[HttpPost]
public ActionResult Create(Component component)
{
if (ModelState.IsValid)
{
_componentRepository.Insert(component);
_componentRepository.Save();
}
return Content("Success");
}
}
当您 post 向控制器发送表单时,浏览器不会序列化实体,它只是传递与您的控制器方法接受的对象的属性相结合的字段,或者该控制器方法中参数的字段名称。
因此,在您的情况下,您的控制器需要一个基础 class 组件,这就是它将接收到的所有内容,而不是 CPU 或其他子 class 的实例。 (尽管可能值得测试如果创建组件 abstract
会发生什么)我的建议是每个子 class 实现方法。如果有适用于组件级别的位,请在 接收 subclass 后通过 传递给通用方法:
[Authorize(Roles = "Admin")]
[HttpPost]
public ActionResult CreateCPU(CPU cpu)
{
if (ModelState.IsValid)
{
_componentRepository.Insert(cpu);
_componentRepository.Save();
}
return Content("Success");
}
ComponentRepository 仍然可以接受 Insert(Component)
,前提是它最终可以确保引用正确的 DbSet
,或者 DbContext.Entity<T>
将解析传入的 CPU 与其他组件.
我正在尝试为我的 PC 组件 ASP.NET MVC 应用程序实现一个创建功能,使用 EF 4.7.2 和继承来在一个方法中处理所有派生的 classes。
问题是提交 Component_CreateCPU.cshtml
表单将 CPU
的派生 class 转换为其在 /Components/Create
中的基础 class Component
动作。
我测试了在 Index()
中实例化一个新的 CPU
对象并将其传递给 Create()
方法,它保留了派生的 class.
有什么方法可以提交视图表单并确保派生的 class 被传入?
型号classes:
public class Component : Interfaces.IComponent
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[DisplayName("Name")]
public string Name { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
[DisplayName("Price")]
public decimal Price { get; set; }
public Manufacturer Manufacturer { get; set; }
}
public class CPU : Component
{
[DisplayName("Core Count")]
public int CoreCount { get; set; }
[DisplayName("Core Clock")]
public string CoreClock { get; set; }
}
创建局部视图
_Component_CreateCPU.cshtml
:
@model PCDB.Models.Components.CPU
@using (Html.BeginForm("Create", "Components", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CPU</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Description, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CoreCount, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CoreCount, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CoreCount, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CoreClock, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CoreClock, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.CoreClock, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
ComponentsController
:
public class ComponentsController : Controller
{
private readonly IComponentRepository<Component> _componentRepository;
public ComponentsController()
{
_componentRepository = new ComponentsRepository<Component>();
}
public ActionResult Index()
{
return View(_componentRepository.GetAll());
}
[Authorize(Roles = "Admin")]
public ActionResult Create()
{
return View(new ComponentCreateViewModel());
}
[Authorize(Roles = "Admin")]
[HttpPost]
public ActionResult Create(Component component)
{
if (ModelState.IsValid)
{
_componentRepository.Insert(component);
_componentRepository.Save();
}
return Content("Success");
}
}
当您 post 向控制器发送表单时,浏览器不会序列化实体,它只是传递与您的控制器方法接受的对象的属性相结合的字段,或者该控制器方法中参数的字段名称。
因此,在您的情况下,您的控制器需要一个基础 class 组件,这就是它将接收到的所有内容,而不是 CPU 或其他子 class 的实例。 (尽管可能值得测试如果创建组件 abstract
会发生什么)我的建议是每个子 class 实现方法。如果有适用于组件级别的位,请在 接收 subclass 后通过 传递给通用方法:
[Authorize(Roles = "Admin")]
[HttpPost]
public ActionResult CreateCPU(CPU cpu)
{
if (ModelState.IsValid)
{
_componentRepository.Insert(cpu);
_componentRepository.Save();
}
return Content("Success");
}
ComponentRepository 仍然可以接受 Insert(Component)
,前提是它最终可以确保引用正确的 DbSet
,或者 DbContext.Entity<T>
将解析传入的 CPU 与其他组件.