Это, кажется, довольно тривиальная проблема, на которой я застрял около часа, и я не понимаю, что я делаю неправильно.
У меня есть 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);
}
}
У меня есть представление Create:
<%@ 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:
//
// 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, я вижуожидаемый интерфейс.Мой раскрывающийся список содержит список всех допустимых альбомов в моей базе данных (из таблицы «Альбомы»), и я проверил, что каждый идентификатор альбома является значением, а каждый заголовок - текстом.Отлично.
Так что теперь, когда я иду, чтобы заполнить свою форму и нажимаю «Сохранить», я получаю сообщение об ошибке, сообщающее, что мне нужно выбрать альбом.Проходя по отладчику в Visual Web Developer, я вижу, что название и номер дорожки заполнены правильно, но мой объект Album имеет значение NULL, а AlbumId по-прежнему равен 0. Есть идеи?
ОБНОВЛЕНИЕ
Следуя совету Мэтта, я обновил свой 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;
Идеи?
ОБНОВЛЕНИЕ
ОК, поэтому я обновил свой взгляд в соответствии с предложением Мэтта о добавлении префикса к полям "Песня":
<%@ 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>
Поведениеэто, к сожалению, то же самое.Нулевое значение SelectedValue и пустой объект Song.