5

在我发布后,我无法弄清楚如何让我的模型 (EF4) 的导航属性不为空。我在几个基本页面上遇到了同样的问题。

即,我有一个外键为 LoginID 的 Estimate 表(来自 Login 表)。

在我的 HTTPGet Edit 方法中,我找到了我想要的具体估计:

Estimate estimate = db.Estimates.Find(id)

从这里我可以访问登录导航属性和登录表中该记录的任何属性。

我通过这个估计作为我的强类型视图的模型。当我的 HTTPPost Edit 方法被调用(并且模型作为参数传递给它)时,我的 Login 导航属性为 null,我无法访问其中的任何内容。我当然可以绕过它,因为我的估算类中确实有 LoginID 字段,但感觉真的很笨重,就像我错过了实体框架的一个关键好处。

我在多个页面上遇到同样的问题,我将带有导航属性的模型传递给我的视图,并且视图正在返回带有空导航属性的模型。

以下是我遇到问题的代码示例:

    [HttpPost]
    public ActionResult Edit(Estimate estimate)
    {

        var test = estimate.Login.CompanyProfileID;
        ...

我可以在视图中访问 Model.Login 及其所有属性,所以我知道它正在正确地传递给视图。当我的表单提交时,它只是不会将导航属性传递回控制器。

4

4 回答 4

6

正在发生的事情是 MVC 使用称为“模型绑定”的东西,它将 POST 在页面请求中传递的所有字段与您的操作参数的匹配属性相匹配。

因此,如果该属性未包含在POST页面的输入字段中,则它不会绑定到您的POST操作中的参数,因此将为空。

因此,您可以为 中的每个属性包含一个隐藏字段Login,例如

@Html.HiddenFor(m => m.Login.ID)
@Html.HiddenFor(m => m.Login.Name)

或者,就像您在解决方法中描述的那样 - 即根据 Id 重新查询数据库。尽管这可能看起来很笨重,但这是一种完全有效的做事方式,因为它避免了在各处传递隐藏字段。

于 2012-07-11T04:18:48.240 回答
1

您返回的 Estimate 对象受视图字段(以及任何任何 Bind 属性)的限制。为您想要的属性添加隐藏字段或从上下文重新加载对象。

需要注意的一点(我将这个答案发布到一个长期死问题的全部原因)是对于 EF6,如果您在部分 EntityState.Modified 上的 .SaveChanges 之后从上下文重新加载对象(因为您很聪明)它将为您提供实体的缓存和不完整版本。您必须执行 context.Entity(estimate).Reload() 而不是 .Find 或 .Where

于 2015-02-26T18:02:20.150 回答
0

MVC 没有任何视图状态的概念,或者视图中自动持久化数据的概念。您希望通过 POST 返回给您的任何属性都必须作为表单字段存在于表单中。在这种情况下,您需要一个隐藏字段来存储LoginID.

@Html.HiddenFor(m => m.LoginID)
于 2012-07-10T23:48:46.607 回答
0

我有与您类似的情况,在后期操作中,我从数据库中提取原始项目,然后根据我需要做什么,将所有已编辑的属性复制到我拉出的项目并使用复制的属性保存原始属性(可能被编辑的属性)由用户),或者用缺失的属性填充发布的模型,然后保存它。我不确定这是否是正确的做法,但它对我有用。当您从数据库中提取原始项目时,您可以访问您想要的任何属性(假设用户无法更改它)。

例子:

 [Authorize]
        public ActionResult Edit(int id)
        {
            var movie = movieService.GetMovieById(id);
            if (new UserService().Current().UserId == movie.UserID)
            {
                EditMovieModel model = new EditMovieModel(id);
                return View(model);
            }
            else
            {
                throw new System.Web.HttpException(403, "403 Forbidden");
            }
        }

        [HttpPost]
        [Authorize]
        public ActionResult Edit(Movie movie)
        {
            var realMovie = movieService.GetMovieById(movie.ID);
            if (new UserService().Current().UserId == realMovie.UserID)
            {
                realMovie.Text = HtmlSanitizer.sanitize(movie.Plot);
                realMovie.CategoryID = movie.CategoryID;
                movieService.Update(realMovie);
            }
            else
            {
                throw new System.Web.HttpException(403, "403 Forbidden");
            }
            return RedirectToAction("Movie", new { id = realMovie.ID, title = realMovie.Permalink });
        }
于 2012-07-11T00:12:14.177 回答