Использование шаблона ViewModel с MVC 2 помощники HTML со строгим контролем типов

Я работаю с 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.

Спасибо.

18
задан Brettski 6 July 2010 в 21:15
поделиться

3 ответа

Проблема в том, что ваша форма редактирования использует сильно напечатанные помощники против типа DinnerFormViewModel, но вы звоните в UpdateModel по типу Dinner.

Когда вы используете сильно напечатанных помощников против типа, помощники создают поля формы, предполагая, что это тот тип, в который вы отправляете сообщение. Когда типы не совпадают, возникает проблема.

Однако, это очень легко исправить. Вы можете предоставить префикс к UpdateModel, который указывает, что вы не пытались отредактировать всю модель, а пытались отредактировать свойство модели, в данном случае Ужин.

UpdateModel(dinner, "Dinner");

Другой подход - вызов UpdateModel на фактической ViewModel.

var viewModel = new DinnerFormViewModel();
viewModel.Dinner = repository.GetDinner(id);
UpdateModel(viewModel);

Я думаю, что первый подход намного лучше.

19
ответ дан 30 November 2019 в 08:43
поделиться

Я уверен, что я не на 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 (T Model, String Prefix) Перегружать и пройти «ужин» или «ужин». как аргумент префикса.

1
ответ дан 30 November 2019 в 08:43
поделиться

Более простой способ - использовать префикс в качестве имени параметра, просто сделайте так:

public ActionResult Edit(Dinner Dinner, int DinnerID)
{
   ...
}
0
ответ дан 30 November 2019 в 08:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: