Как я могу передать ViewModel обратно на ту же страницу
Я пытаюсь заставить HTTPPost работать в разделе комментариев на странице видео, но у меня возникли некоторые трудности при обратной передаче. Сохранение записывается в базу данных, но при перезагрузке страницы я не могу найти переменную @Model.SelectedMediaItem.Name, которая была найдена в первый раз. Мой HTML-код выглядит следующим образом:
@{
ViewBag.Title = "Screencast";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@model Project.ViewModels.MediaViewModel
<body onload="initialize()">
<div class="container region3wrap_screencast">
<div class="row content_top_contact">
<div class="nine columns">
<ul class="breadcrumbs">
<li><a href="@Url.Action("Index","Home")">Home</a></li>
<li><a href="@Url.Action("Index","Media")">Media</a></li>
<li><a href="@Url.Action("Screencast","Media")">Screencast</a></li>
<li class="current"><a href="#">@Model.SelectedMediaItem.Name</a></li>
</ul>
</div>
</div>
</div>
<div class="twelve columns leave-comment">
<h3>Leave a Comment</h3>
@using(Html.BeginForm("Screencast","Media", FormMethod.Post, Model))
{
<div class="row">
<div class="six columns">
<div class="row">
<div class="six columns">
@Html.LabelFor(c => c.FeedbackComment.UserID)
@Html.TextBoxFor(c => c.FeedbackComment.UserID)
</div>
<div class="six columns">
@Html.LabelFor(c => c.FeedbackComment.ContentID)
@Html.TextBoxFor(c => c.FeedbackComment.ContentID)
</div>
<div class="row">
<div class="twelve columns">
@Html.LabelFor(c => c.FeedbackComment.FeedbackString)
@Html.TextAreaFor(c => c.FeedbackComment.FeedbackString)
</div>
</div>
</div>
</div>
</div>
<input type="submit" value="Submit button" class="medium button bottom20"/>
}
</div>
</body>
Мои действия контроллера следующие:
//GET
public ActionResult Screencast(int ID)
{
mvm = new ViewModels.MediaViewModel(ID);
return View(mvm);
}
//POST
[HttpPost]
public ActionResult Screencast(MediaViewModel mvm)
{
Feedback newFeedback= new Feedback();
newFeedback.UserID = mvm.FeedbackComment.UserID;
newFeedback.ContentID = mvm.FeedbackComment.ContentID;
newFeedback.CourseID = null;
newFeedback.Timestamp = DateTime.Now;
newFeedback.FeedbackString = mvm.FeedbackComment.FeedbackString;
//Initialize the Feedback Repository and save changes
feedbackRepository = new Repository<Feedback>(dbcontext);
feedbackRepository.Add(newFeedback);
feedbackRepository.SaveChanges();
return View(mvm);
}
Когда я вызываю страницу, чтобы начать с URL /Media/Screencast/1, она загружается с моделью представления, заполненной деталями SelectedMediaItem, и все выглядит так, как ожидается.
Когда я пытаюсь отправить сообщение обратно, мои данные о модели представления теряются, хотя комментарий фактически сохраняется, как и ожидалось, мне нужно посетить другую страницу и вернуться, прежде чем я смогу увидеть.
Как я могу передать свою модель представления в @Html.BeginFor в качестве дополнительного параметра?
Моя ViewModel выглядит следующим образом:
public class MediaViewModel
{
private Repository<Content> contentRepository;
private Repository<Feedback> feedbackRepository;
private MetaLearningContext dbcontext;
public int screencastID { get; set; }
public IEnumerable<Content> Screencasts { get; set; }
public IEnumerable<Content> Podcasts { get; set; }
public IEnumerable<Content> Documents { get; set; }
public IEnumerable<Feedback> FeedbackComments { get; set; }
public Content SelectedMediaItem { get; set; }
public MetaLearningUser User { get; set; }
public MetaLearningUser FeedbackAuthor { get; set; }
public Feedback FeedbackComment { get; set; }
public MediaViewModel()
{
this.dbcontext = new MyContext(System.Configuration.ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
this.contentRepository = new Repository<Content>(dbcontext);
this.feedbackRepository = new Repository<Feedback>(dbcontext);
this.dbcontext.Configuration.LazyLoadingEnabled = true;
//Retrieve a list of Screencasts
Screencasts = contentRepository
.Get(c => c.ContentTypeID == 1);
//Retrieve a list of Podcasts
Podcasts = contentRepository
.Get(c => c.ContentTypeID == 2);
//Retrieve a list of Documents
Documents = contentRepository
.Get(c => c.ContentTypeID == 3);
}
public MediaViewModel(int id)
{
this.dbcontext = new MyContext(System.Configuration.ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
this.contentRepository = new Repository<Content>(dbcontext);
this.feedbackRepository = new Repository<Feedback>(dbcontext);
this.dbcontext.Configuration.LazyLoadingEnabled = true;
//Retrieve a list of Screencasts
Screencasts = contentRepository
.Get(c => c.ContentTypeID == 1);
//Retrieve a list of Podcasts
Podcasts = contentRepository
.Get(c => c.ContentTypeID == 2);
//Retrieve a list of Documents
Documents = contentRepository
.Get(c => c.ContentTypeID == 3);
//Retrieve selected screencast
SelectedMediaItem = contentRepository
.Get(c => c.ContentID == id)
.FirstOrDefault();
}
}
2 ответа
Просто чтобы добавить что-то к ответу Маттиаса:
1) он прав - если вам нужна информация, куда перенаправить, поместите ее в скрытое поле или добавьте в качестве параметра в Form-Method.
2) Шаблон, который распространен в MVC, - это PRG (Post/Redirect/Get), поэтому, по сути, ваш POST должен отвечать RedirectToAction("Screencast") вместо представления. ( http://en.wikipedia.org/wiki/Post/Redirect/Get)
Чтобы использовать это, вы должны немного изменить свои функции:
public ActionResult Screencast(int ID)
{
mvm = new ViewModels.MediaViewModel(ID); //The id is in the viewmodel i think
return View(mvm);
}
[HttpPost]
//Even if unused include the formcollection for cases where the GET has the same signature
public ActionResult Screencast(int ID, MediaViewModel mvm, FormCollection collection)
{
//Do something
return RedirectToAction("Screencast", new { id = ID });
}
И внутри вашего взгляда:
@using(Html.BeginForm("Screencast", new { id = Model.SelectedMediaItem }))
{ ... }
- Возможно, для предлагаемой перегрузки требуется больше параметров, но вы увидите, что...
Вероятно, это связано с тем, что SelectedMediaItem не был опубликован вместе с остальными значениями в форме. Поэтому, когда форма сериализуется в модель, свойство SelectedMediaItem имеет значение null. Что вы можете сделать, это просто добавить это в форму отправки сообщения:
@Html.HiddenFor(c => c.SelectedMediaItem)