0

我有一个代码优先数据库。引起我问题的表格是

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; }
}

我今年有一个控制器,它有 create get 方法

    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);
    } 

和 post 方法

    [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);
    }

每当我尝试创建一个新的年份(已设置年份值和截止日期)时,它都会返回帖子并且模型状态无效并说

年份字段是必需的。

我已经检查并在 post 方法 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();
    }
4

3 回答 3

1

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

所以我将从解决方案开始:使用 ViewModel。这是一个小型、扁平、轻量级的类,只包含视图想要显示的字段。它不应该与您的数据层相同。视图应该只是呈现内容,而 ViewModel 应该只包含要显示的数据。

您将数据从您的实际对象映射到 ViewModel(AutoMapper 在这方面非常受欢迎。)

现在,为什么这会有所帮助?好吧,我对您的问题的理论是:

1)模型绑定器可能不喜欢虚拟属性。每当您将表单返回到 MVC 中的函数时,都会有少量代码运行并尝试将表单中的所有值映射到它们的字段。此模型绑定器可能无法找出虚拟字段,或者可能有充分的理由不自动映射到虚拟字段。无论哪种方式,ViewModel 都会将其替换为常规的公共属性。

2)另一种可能性,但我不太确定,是有一个循环引用(Year -> Deadline -> Year )并且模型活页夹不能很好地处理。不过,ViewModel 概念再次摆脱了这一点,您只需在 ViewModel 中有一个 Year 字段。

于 2012-04-07T22:49:02.710 回答
0

当我的模型在视图中没有正确连接时,我就遇到过这种情况。这种事情会阻止模型绑定器在后期操作中实现模型。要检查的一件事是确保您在视图中使用良好的 asp.net mvc 命名约定。

于 2012-04-07T22:46:38.873 回答
0

这是我的想法,当您不知道发生了什么时,它通常会很有用...
参考包含更多详细信息的帖子: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 实例,以防出现任何问题,如提到的一张海报(循环引用等)。

于 2012-04-07T23:04:01.457 回答