【发布时间】:2010-01-18 06:26:10
【问题描述】:
这似乎是一个非常琐碎的问题,我已经坚持了大约一个小时,我不明白我做错了什么。
我有一个 ViewModel:
public class SongFormViewModel
{
public Song Song { get; set; }
public SelectList AlbumList { get; set; }
public SongFormViewModel(Song song, IQueryable<Album> albumList)
{
Song = song;
AlbumList = new SelectList(albumList, "AlbumId", "Title", song.AlbumId);
}
}
我有一个创建视图:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NightSpot.Models.SongFormViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Create
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create</h2>
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="AlbumId">AlbumId:</label>
<%= Html.DropDownList("AlbumId", Model.AlbumList) %>
<%= Html.ValidationMessage("AlbumId", "*") %>
</p>
<p>
<label for="Title">Title:</label>
<%= Html.TextBox("Title") %>
<%= Html.ValidationMessage("Title", "*") %>
</p>
<p>
<label for="TrackNumber">TrackNumber:</label>
<%= Html.TextBox("TrackNumber") %>
<%= Html.ValidationMessage("TrackNumber", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
我有一个 SongsController Create 方法:
//
// POST: /Songs/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Song song)
{
if (ModelState.IsValid)
{
try
{
repository.Add(song);
repository.Save();
return RedirectToAction("Details", new { id = song.SongId });
}
catch
{
ModelState.AddRuleViolations(song.GetRuleViolations());
}
}
return View(new SongFormViewModel(song, repository.FindAllAlbums()));
}
当我导航到 /Songs/Create URL 时,我看到了预期的 UI。我的下拉列表包含数据库中所有有效专辑的列表(来自专辑表),并且我已经验证每个 AlbumId 是值,每个 Title 是文本。太好了。
所以现在当我填写表格并点击“保存”时,我收到一条错误消息,告诉我需要选择专辑。当我在 Visual Web Developer 中单步调试调试器时,我看到标题和曲目编号已正确填充,但我的 Album 对象为 NULL,AlbumId 仍为 0。有什么想法吗?
更新
听从 Matt 的建议,我更新了我的 SongsController 以使用 SongFormViewModel 而不是 Song。这是新的控制器:
//
// POST: /Songs/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(SongFormViewModel song)
{
Song newSong = song.Song;
newSong.AlbumId = (int) song.AlbumList.SelectedValue;
if (ModelState.IsValid)
{
try
{
repository.Add(newSong);
repository.Save();
return RedirectToAction("Details", new { id = song.Song.SongId });
}
catch
{
ModelState.AddRuleViolations(song.Song.GetRuleViolations());
}
}
return View(new SongFormViewModel(newSong, repository.FindAllAlbums()));
}
我启动了我的 /Songs/Create URL 并收到一条消息,说 SongFormViewModel 需要一个无参数的构造函数。
所以我做了一个。
当我重新运行 /Songs/Create URL 时,我的 SongsController 中的这一行出现“对象引用未设置为对象的实例”异常:
Line 93: newSong.AlbumId = (int) song.AlbumList.SelectedValue;
想法?
更新
好的,所以我根据 Matt 的建议更新了我的观点,即在字段前加上“Song”:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<NightSpot.Models.SongFormViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Create
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create</h2>
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="Song.AlbumId">AlbumId:</label>
<%= Html.DropDownList("Song.AlbumId", Model.AlbumList) %>
<%= Html.ValidationMessage("Song.AlbumId", "*") %>
</p>
<p>
<label for="Song.Title">Title:</label>
<%= Html.TextBox("Song.Title") %>
<%= Html.ValidationMessage("Song.Title", "*") %>
</p>
<p>
<label for="Song.TrackNumber">TrackNumber:</label>
<%= Html.TextBox("Song.TrackNumber") %>
<%= Html.ValidationMessage("Song.TrackNumber", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
不幸的是,行为是相同的。 Null SelectedValue 和一个空的 Song 对象。
【问题讨论】:
-
所以我猜这 song.AlbumList 在你的操作方法中是空的? song.Song 是空的,还是进来没问题?
-
哦,现在这很有趣...SongFormViewModel.AlbumList.SelectedValue 为 null,并且 SongFormViewModel.Song 在调用 new Song() 构造函数后看起来处于一种状态。与以前不同,song.Song 上甚至没有填充文本框。
-
啊!这可能是因为您在视图中的 Html.TextBox() 调用仍然指向“TrackNumber”之类的属性,而不是隧道进入“Song.TrackNumber”(因为您正在编辑 ViewModel 而不是直接编辑歌曲)。
-
没有骰子。还是同样的问题。
-
好的,我们已经达到了我的知识极限。我会把我的答案留在那里,我们会看看其他人是否可以提供帮助。如果您有一段时间没有得到答案,赏金可能会吸引更多回复。
标签: c# asp.net-mvc