Подтвердить что ты не робот

Использование атрибута ModelBinder против ModelBinders.Add()

Может ли кто-нибудь сказать мне, что pros/concs использует атрибут [ModelBinder()] и регистрирует привязки модели через ModelBinders.Add() в global.asax?

Одно из преимуществ, которое я могу придумать, заключается в том, что он более явный, тогда как регистрация в глобальном ModelBinders не так очевидна для кого-то, проверяющего метод действия.

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

Разве это единственная разница?

Другими словами, если бы это было правильно:

  • Если вы используете модель только в одном методе действий (возможно, два, получите + сообщение), используйте [ModelBinder()].
  • Если вы используете модель более чем в одном методе действий, зарегистрируйте ее в глобальном ModelBinders.
4b9b3361

Ответ 1

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

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

  • Задайте атрибут в классе модели, например:

    [ModelBinder(typeof(MyModelBinder))]
    public class MyModel
    {
        ...
    }    
    
  • Глобально зарегистрировать связующее

    ModelBinders.Binders.Add(typeof(MyModel), new MyModelBinder())
    

Еще одна причина, по которой я предпочитаю один из них, заключается в том, что если вам когда-либо придется вручную инициировать процесс привязки модели, вы также можете использовать свое настраиваемое связующее устройство:

public ActionResult SomeActionMethod()
{
     MyModel model = ...

     //manually invoke the model binding process considering only query string data
     //The custom model binder will be used only if it was globally registered
     //in the binders dictionary or set in an attribute of the model class
     TryUpdateModel(model, new QueryStringValueProvider())

     ...
}

У вас также есть возможность реализовать свою собственную логику для выбора привязки модели, реализовав интерфейс IModelBinderProvider и зарегистрировавшись в global.asax, как в

ModelBinderProviders.BinderProviders.Add(new CustomModelBinderProvider()) 

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

В конце есть довольно много вариантов для выбора связующего. В asp MVC 3 это будет разрешено следующим образом (при условии, что вы используете контроллер ControllerActionInvoker по умолчанию)

  • Атрибут параметра. См. Метод GetParameterValue класс ControllerActionInvoker

  • Биндер вернулся из модуля IModelBinderProvider. См. Метод GetBinder в ModelBinderDictionary class

  • Биндер глобально зарегистрирован в словаре ModelBinders.Binders.

  • Связующее, определенное в атрибуте [ModelBinder()] для типа модели.

  • DefaultModelBinder.

Ответ 2

Мне кажется, что преимущество использования атрибута вместо добавления к коллекции связующих моделей в Global.asax заключается в том, что вы можете указать метод (или класс), который использовать конкретное связующее, а не связывать связующее с определенным тип. Затем вы можете создать модель на основе контекста, а не типа.