帖子上的模型属性为null

时间:2014-05-06 06:40:03

标签: c# asp.net-mvc

我有一个简单的应用程序,我松散地基于asp.net上的教程中使用的MVC音乐商店,允许用户输入他们正在观看的电视节目的详细信息,以便他们可以跟踪哪些他们在每个节目中都会参与其中。

我的应用程序中的主要实体是Show:

Public class Show
{
      // a few automatic properties
      public int id { get; set; }
      public Genre Genre { get; set; }
}

和流派类

Public partial class Genre
{
    public int GenreId { get; set; }
    public string Name { get; set; }
    public List<Show> Shows { get; set; }
}

我的控制器中的POST编辑方法是由VS为我生成的:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(Show show)
    {
        if (ModelState.IsValid)
        {
            db.Entry(show).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(show);
    }

当我在调试器中检查db时,我可以看到Show对象(当时很多都在数据库中。我用两个播种它,但通常通过表单添加第三个)都具有类型I&#39 ;已输入但在“编辑”操作返回视图后,类型为空,而所有其他值都已更新。这是为什么?

我想也许类型字段是空的,因为我没有实例化它们但我会在哪里这样做?我不想在每次设置节目类型时创建新类型。我只是希望一个节目有一个类型参考,以便我最终允许用户选择一个类型,并看到他们跟随该类型的所有节目。

编辑:这是我的编辑视图。 “详细信息”视图也非常相似。

@model watchedCatalogue2.Models.Show

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>@Html.DisplayFor(m => m.Name)</legend>

        @Html.HiddenFor(m => m.id)

        <div class="editor-label">
            @Html.LabelFor(m => m.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.Name)
            @Html.ValidationMessageFor(m => m.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(m => m.Genre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.Genre.Name)
            @Html.ValidationMessageFor(m => m.Genre.Name)
        </div>

        <div class="editor-label">
            @Html.Label("Number of episodes")
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.NoEpisodes)
            @Html.ValidationMessageFor(m => m.NoEpisodes)
        </div>

        <div class="editor-label">
            @Html.Label("Number of episodes watched")
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.NoEpisodesWatched)
            @Html.ValidationMessageFor(m => m.NoEpisodesWatched)
        </div>

        <div class="editor-label">
            @Html.Label("Watching State")
        </div>
        <div class="editor-field">
            @Html.DropDownListFor(m => m.State,      watchedCatalogue2.Models.Show.WatchStateItems)
        </div>

        <div class="editor-label">
            @Html.LabelFor(m => m.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.Description)
            @Html.ValidationMessageFor(m => m.Description)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

另外,为了更好的衡量,我的控制器中的db引用了我的CatalogueEntities类:

namespace watchedCatalogue2.Models
{
    public class CatalogueEntities : DbContext
    {
        public DbSet<Genre> Genres { get; set; }
        public DbSet<Show> Shows { get; set; }
    }
}

3 个答案:

答案 0 :(得分:2)

问题可能在MVC中,所有数据都没有保留/发布到POST方法上,而只保留在View上作为可编辑元素呈现并包含在模型中。

最简单的解决方法是将其渲染为隐藏字段,如下所示:

MVC 2.0及更早版本:

<%: Html.HiddenFor(m => m.GenreId) %>

剃刀:

@Html.HiddenFor(m => m.GenreId)

如果你使用AJAX或类似的东西,你也可以发送/传递值作为参数。

另请注意,如果您使用ModelState.IsValid功能,则隐藏字段很可能会呈现为null,并且很可能是一个问题。要删除此内容并不总是建议,只需添加ModelState.Remove("TheKey");,在您的情况下可能是ModelState.Remove("GenreID");

答案 1 :(得分:1)

如果我正确地解决问题,您需要以某种方式在表单上呈现数据以保持数据,同时记住网络是无状态的,如果值不存在则表单已发布,不会被重新绑定到您的视图模型。

在您的观点中包含以下格式:

@ Html.HiddenFor(model =&gt; model.GenreId)

或者,根据您在Get上的网址,您可以更改POST方法签名以包含ID。

答案 2 :(得分:0)

经过一些研究,我注意到示例中的许多模型类都引用了标记为虚拟的其他模型。我想我没有什么可失去的,所以我修改了我的Show类,所以public Genre Genre { get; set; }现在读取public virtual Genre Genre { get; set; }。突然间一切正常。我很感激,如果有人知道它的工作原理可以向我解释,因为我到目前为止看到的所有内容都是对延迟加载的引用,但与我的问题无关。

感谢大家的帮助。