Я работаю с ASP.NET MVC2 RC и не могу выяснить, как заставить помощника HTML, TextBoxfor работать с шаблоном ViewModel. При использовании на странице редактирования данные не сохраняются, когда UpdateModel () называют в контроллере. Я взял следующие примеры кода из приложения NerdDinner.
Edit.aspx
<%@ Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NerdDinner.Models.DinnerFormViewModel>" %>
...
<p>
// This works when saving in controller (MVC 1)
<label for="Title">Dinner Title:</label>
<%= Html.TextBox("Title", Model.Dinner.Title) %>
<%= Html.ValidationMessage("Title", "*") %>
</p>
<p>
// This does not work when saving in the controller (MVC 2)
<label for="Title">Dinner Title:</label>
<%= Html.TextBoxFor(model => model.Dinner.Title) %>
<%= Html.ValidationMessageFor(model=> model.Dinner.Title) %>
</p>
DinnerController
// POST: /Dinners/Edit/5
[HttpPost, Authorize]
public ActionResult Edit(int id, FormCollection collection) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsHostedBy(User.Identity.Name))
return View("InvalidOwner");
try {
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
ModelState.AddModelErrors(dinner.GetRuleViolations());
return View(new DinnerFormViewModel(dinner));
}
}
Когда исходный стиль помощника используется (Http. TextBox), UpdateModel (ужин) работы вызова как ожидалось и новые значения сохраняются.
Когда новый стиль помощника (MVC2) используется (Http. TextBoxFor), UpdateModel (ужин) вызов не обновляет значения. Да, текущие значения загружаются в страницу редактирования на загрузке.
Есть ли что-то еще, что я должен добавить к коду контроллера, чтобы он работал? Новый помощник хорошо работает, если я просто использую модель и не шаблон ViewModel.
Спасибо.
Проблема в том, что ваша форма редактирования использует сильно напечатанные помощники против типа DinnerFormViewModel, но вы звоните в UpdateModel по типу Dinner.
Когда вы используете сильно напечатанных помощников против типа, помощники создают поля формы, предполагая, что это тот тип, в который вы отправляете сообщение. Когда типы не совпадают, возникает проблема.
Однако, это очень легко исправить. Вы можете предоставить префикс к UpdateModel, который указывает, что вы не пытались отредактировать всю модель, а пытались отредактировать свойство модели, в данном случае Ужин.
UpdateModel(dinner, "Dinner");
Другой подход - вызов UpdateModel на фактической ViewModel.
var viewModel = new DinnerFormViewModel();
viewModel.Dinner = repository.GetDinner(id);
UpdateModel(viewModel);
Я думаю, что первый подход намного лучше.
Я уверен, что я не на 100%, но кажется, что сильно напечатанный помощник создает удостоверения личности / имена «ужин. Itle» вместо того, чтобы просто «название» и, следовательно, - Updatemodel
не может это связать.
К сожалению - я не использовал DEALLEMODEL
Метод сам, поэтому я не знаю решение.
Можете ли вы добавить HTML, который отображается для обоих подходов?
Играть вокруг с отражателем ATM.
Это то, что я нашел:
protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel: class
{
if (model == null)
{
throw new ArgumentNullException("model");
}
if (valueProvider == null)
{
throw new ArgumentNullException("valueProvider");
}
Predicate<string> predicate = delegate (string propertyName) {
return BindAttribute.IsPropertyAllowed(propertyName, base.includeProperties, base.excludeProperties);
};
IModelBinder binder = this.Binders.GetBinder(typeof(TModel));
ModelBindingContext context2 = new ModelBindingContext();
context2.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(delegate {
return base.model;
}, typeof(TModel));
context2.ModelName = prefix;
context2.ModelState = this.ModelState;
context2.PropertyFilter = predicate;
context2.ValueProvider = valueProvider;
ModelBindingContext bindingContext = context2;
binder.BindModel(base.ControllerContext, bindingContext);
return this.ModelState.IsValid;
}
параметры
- Моделируйте экземпляр модели для обновления.
- префикс префикс для использования при рассмотрении значений в поставщике элементов.
Итак, вы можете попробовать использовать UpdateModel
Перегружать и пройти «ужин» или «ужин». как аргумент префикса.
Более простой способ - использовать префикс в качестве имени параметра, просто сделайте так:
public ActionResult Edit(Dinner Dinner, int DinnerID)
{
...
}