编码优先一对一关系和 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();
    }

编码优先一对一关系和 MVC 创建问题

好的,关于这个问题,我有两个基本理论,但无论如何你都应该实现一个解决方案。

因此,我将从解决方案开始:使用视图模型。 这是一个小型、平面、轻量级类,仅包含视图要显示的字段。 它不应与数据层相同。 视图应该只是渲染内容,而视图模型应该只包含要显示的数据。

您将实际对象中的数据映射到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 实例,并且出现任何问题,例如提到的一张海报(周期性引用等)。