我的创建操作的Post Controller存在一些问题。下面是我的模型,Round,Material,MaterialShape,RawMaterial。我的主要目标是将Round对象添加到数据库中。
public class Material
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Required]
[Display(Name="Material")]
public string MaterialName { get; set; }
}
材质形状的抽象类
public abstract class MaterialShape
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public virtual Material Material { get; set; }
}
MaterialShape中的Round Inherited Class
[Table("Rounds")]
public class Round : MaterialShape
{
[Required]
[Display(Name="Outside Diameter")]
public double OuterDiameter { get; set; }
}
下面是我创建的视图模型,用于将所有材质带到视图中。我使用IEnumerable从数据库中提取所有不同的材料。我还包含了一个MaterialId来保存我选择的项目。
public class VMRoundMaterial
{
public Round Round { get; set; }
[Display(Name="Material")]
public IEnumerable<SelectListItem> Materials { get; set; }
public int MaterialId { get; set; }
}
控制器创建操作
public ActionResult Create()
{
var model = new VMRoundMaterial();
using (var db = new DbContext())
{
model.Materials = db.Materials.ToList().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.MaterialName
});
}
return View(model);
}
创建视图
@model SetupSheet.Models.ViewModel.VMRoundMaterial
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Round</h4>
<hr />
@Html.ValidationSummary(true)
<div class="form-group">
@Html.LabelFor(model => model.Round.OuterDiameter, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Round.OuterDiameter)
@Html.ValidationMessageFor(model => model.Round.OuterDiameter)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Materials, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(m => m.MaterialId, Model.Materials)
</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>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
如您所见,我完成了将列表添加到数据库中。我在创建[发布]操作中将Viewmodel转换回我的Datamodel时遇到问题。
[HttpPost]
public ActionResult Create(VMRoundMaterial viewmodel)
{
try
{
if (ModelState.IsValid)
{
Round roundmaterial = new Round();
roundmaterial.OuterDiameter = viewmodel.Round.OuterDiameter;
roundmaterial.Material.ID = viewmodel.MaterialId;
db.Rounds.Add(roundmaterial);
db.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
我的[HttpPost]无法正常工作。我是否正确设置了?如何正确设置DropDownListFor参数?我是否将我的选择项正确转换为Round对象?由于某种原因,ModelState.IsValid返回false。可能是什么导致了这个?
代码失败roundmaterial.Material.ID = viewmodel.MaterialId;
数据库连接正常,但我没有收到结果。我愿意接受其他策略来找到有效的策略。
jstadnicki提出了解决方案
[HttpPost]
public ActionResult Create(ModelDTO viewmodel)
{
try
{
if (ModelState.IsValid)
{
Round roundmaterial = new Round();
roundmaterial.OuterDiameter = viewmodel.Round.OuterDiameter;
roundmaterial.Material.ID = viewmodel.MaterialId;
db.Rounds.Add(roundmaterial);
db.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
我理解你为什么要使用ModelDTO,但我仍然遇到问题。
ModelState仍然是假的。我想我们在这里仍然缺少一些东西。
答案 0 :(得分:1)
ModelState
无效,因为您在视图模型中使用了数据模型(Round
)而没有回发所需Material
属性的值。
通常,用于编辑数据的视图模型不应包含属于数据模型的属性,并且您的视图应为
public class VMRoundMaterial
{
[Required]
[Display(Name="Outside Diameter")]
public double OuterDiameter { get; set; }
[Display(Name="Material")]
public int MaterialId { get; set; }
public IEnumerable<SelectListItem> Materials { get; set; }
}
另请注意,您的展示属性需要位于int MaterialId
,而不是IEnumerable<SelectListItem> Materials
,以便创建与MaterialId
相关联的标签(目前,点击'标签'不会设置焦点到<select>
元素。那么视图将是
@Html.LabelFor(m => m.OuterDiameter)
@Html.EditorFor(m => m.OuterDiameter)
@Html.ValidationMessageFor(m => m.OuterDiameter)
@Html.LabelFor(m => m.MaterialId)
@Html.DropDownListFor(m => m.MaterialId, Model.Materials)
@Html.ValidationMessageFor(m => m.MaterialId)
旁注:您在POST方法中使用roundmaterial.Material.ID = viewmodel.MaterialId;
可能会抛出NullReferenceException
,因为您尚未初始化属性Material
答案 1 :(得分:0)
如果我理解你的问题是正确的:尝试将post方法中的VMRoundMaterial更改为ModelDTO,其中modeldto的定义如下:
public class ModelDTO
{
public Round Round {get;set;}
public int MaterialId { get; set; }
}
现在检查一下你是否会得到适当的水合模型。