ASP.NET MVC UpdateModel с интерфейсом

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

, Например...

<div id="page">
    <div id="primary-content"></div>
    <div id="secondary-content"></div>
    <div id="search-form-and-primary-nav-wrapper">
        <form id="search-form"></form>
        <ul id="primary-nav">
            <li id="primary-nav-about-us"></li>
        </ul>
    </div>
    <a id="logo"><img /></a>
</div><!-- /#page -->

, Как Вы видите, селекторы иногда довольно длинны. Но настолько легче, по моему скромному мнению, чем работа с чем-то как YUI grids.css, где Вы заканчиваете с идентификаторами как #doc, #bd, #yui-main, и т.д.

6
задан Brian Vallelunga 9 September 2009 в 16:30
поделиться

2 ответа

Здесь обсуждалось отсутствие проверки фактического типа интерфейса: http://forums.asp.net/t/1348233.aspx

Тем не менее, я нашел хакерский способ обойти проблему. Так как у меня уже была настраиваемая привязка модели для этого типа, я смог добавить в нее код, чтобы выполнить привязку за меня. Вот как теперь выглядит моя связыватель модели:

public class AccountViewModelModelBinder : DefaultModelBinder
{
    private readonly IProfileViewModel profileViewModel;
    private bool profileBound = false;

    public AccountViewModelModelBinder(IProfileViewModel profileViewModel)
    {
        this.profileViewModel = profileViewModel;
    }

    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // Bind the profile
        if (profileBound)
            return;

        profileBound = true;

        bindingContext.ModelType = profileViewModel.GetType();
        bindingContext.Model = profileViewModel;
        bindingContext.ModelName = "Profile";

        BindModel(controllerContext, bindingContext);
    }

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, System.Type modelType)
    {
        var model = new AccountViewModel();
        model.Profile = profileViewModel;

        return model;
    }
}

В основном, когда связыватель модели "завершил" привязку основного AccountViewModel, я затем изменяю контекст привязки (как предлагает Эйстон) и снова вызываю BindModel. Затем это связывает мой профиль. Обратите внимание, что я вызвал GetType для profileViewModel (который предоставляется контейнером IOC в конструкторе). Также обратите внимание, что я включил флаг, чтобы указать, была ли уже привязана модель профиля. Иначе получился бы бесконечный цикл вызова OnModelUpdated.

Я не говорю, что это красиво, но это работает достаточно хорошо для моих нужд. Я все еще хотел бы услышать другие предложения.

0
ответ дан 17 December 2019 в 20:33
поделиться

Мне нужно было бы проверить код ASP.NET MVC (DefaultModelBinder), но я предполагаю, что он отражает тип IProfile, а не экземпляр StandardProfile.

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

Вы можете попробовать что-то вроде обновления BindingContext и изменения ModelType на StandardProfile, а затем вызвать

bindingContext.ModelType = typeof(StandardProfile);
IProfile profile = base.BindModel(controllerContext, bindingContext);

В любом случае, имея пустой Интерфейс странный ~


Изменить: просто хочу добавить, что приведенный выше код - это просто псевдокод, вам нужно будет проверить DefaultModelBinder, чтобы увидеть, что именно вы хотите написать.


Изменить # 2:

Можете ли вы сделать:

public class ProfileModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
    {
        bindingContext.ModelType = typeof(StandardProfile);
        return base.BindModel(controllerContext, bindingContext);
    }
}

Нет необходимости создавать привязку модели для AccountView, она работает нормально.


Редактировать # 3

Протестировано, указанная привязка работает, просто нужно добавить:

ModelBinders.Binders[typeof(IProfile)] = new ProfileModelBinder();

Ваше действие выглядит следующим образом:

public ActionResult AddAccount(AccountViewModel viewModel) {
    // viewModel is fully populated, including profile, don't call UpdateModel
}

Вы можете использовать IOC при установке связывателя модели (например, внедрить конструктор типа).

2
ответ дан 17 December 2019 в 20:33
поделиться
Другие вопросы по тегам:

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