编码优先一对一关系和 MVC 创建问题
本文关键字:MVC 创建 问题 关系 一对一 编码 | 更新日期: 2023-09-27 18:30:27
我有一个代码优先数据库。导致我问题的表是
public class Deadline
{
public Deadline() { }
public Deadline(Year year)
{
this.Year = year;
}
public Guid Id { get; set; }
[Required]
public Year Year { get; set; }
[Required]
[DataType(DataType.Date)]
[DataAnnotationsExtensions.Date]
public DateTime From { get; set; }
[Required]
[DataType(DataType.Date)]
[DataAnnotationsExtensions.Date]
public DateTime To { get; set; }
}
public class Year
{
public Year(Int32 value) { this.Value = value; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
[Display(Name="Year")]
[DataAnnotationsExtensions.Year]
public Int32 Value { get; set; }
public virtual Deadline Deadline { get; set; }
}
我有一个具有创建获取方法的年度控制器
public ActionResult Create()
{
ViewBag.Id = new SelectList(db.Deadline, "Id", "Id");
var Year = new Year(db.Year.OrderByDescending(x => x.Value).FirstOrDefault().Value + 1);
Year.Deadline = new Deadline(Year);
return View(Year);
}
和发布方法
[HttpPost]
public ActionResult Create(Year year)
{
if (ModelState.IsValid)
{
if (db.Year.Select(x => x.Value).Contains(year.Value))
{
ModelState.AddModelError("AlreadyExists", "That year has already been added to the database, please edit instead");
return View(year);
}
db.Year.Add(year);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(year);
}
每当我尝试创建一个新的年份(设置了年份值和截止日期)时,它都会回到帖子并且模型状态无效并说
年份字段为必填字段。
我已经检查过并在邮政方法年。Deadline.Year 确实为空,我想知道的是为什么(以及我如何解决这个问题)它一直让我发疯,甚至把
@{ Model.Deadline.Year = Model; }
在观点中什么也没做。
编辑以下作品
using (ProjectSelectionAndAllocation.Models.DatabaseContext Context = new Models.DatabaseContext())
{
var h = new Models.Year(1001);
h.Deadline = new Models.Deadline(h);
Context.Year.Add(h);
Context.SaveChanges();
}
好的,关于这个问题,我有两个基本理论,但无论如何你都应该实现一个解决方案。
因此,我将从解决方案开始:使用视图模型。 这是一个小型、平面、轻量级类,仅包含视图要显示的字段。 它不应与数据层相同。 视图应该只是渲染内容,而视图模型应该只包含要显示的数据。
您将实际对象中的数据映射到ViewModel(AutoMapper在这方面非常流行。
现在,为什么这会有所帮助? 好吧,关于你的问题的理论是:
1) 模型绑定器可能不喜欢虚拟属性。 每当将表单返回到 MVC 中的函数时,都会有少量代码贯穿并尝试将表单中的所有值映射到它们的字段。 此模型绑定器可能无法找出虚拟字段,或者可能有一些很好的理由不自动映射到一个虚拟字段。 无论哪种方式,ViewModel 都会将其替换为常规公共属性。
2)另一种可能性,但我不太确定,是有一个循环引用(年->截止日期->年),模型活页夹处理得不好。 同样,ViewModel概念将摆脱它,并且您在ViewModel中只有一个年份字段。
当我的模型在视图中没有正确连接时,我遇到了这种情况。 这种事情将阻止模型绑定器在后期操作中实现模型。 要检查的一件事是确保在视图中使用良好的 asp.net mvc 命名约定。
这就是我的想法,当你不知道发生了什么时,它通常被证明是有用的......
参考包含更多详细信息的帖子:https://stackoverflow.com/a/10037334/417747
...
在类似情况下,当绑定无法按预期工作时,通常有助于调试 - 并且通过创建自定义绑定程序。
public class YearClassBinder : DefaultModelBinder
{
//public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
//{
//}
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var model = (Year)base.CreateModel(controllerContext, bindingContext, modelType);
// ...you change, inspect set etc.
return model;
}
}
。这是自定义绑定,调整"传递"值的方法 - 还可以检查它们是否有问题等。
(你需要测试,尝试几个选项,可能是BindModel更好,取决于)
(您可以在该链接中找到更多详细信息)
这不是一个确切的答案,但大多数时候会让你走上正确的轨道。
希望对您有所帮助。
编辑:补充一下,如果需要,您可以使用相同的方法来手动调整和创建 Year 实例,并且出现任何问题,例如提到的一张海报(周期性引用等)。