Как я могу вызвать привязку пользовательской модели в MVC4?

Так что, похоже, несколько человек (какВот а такжеВот) были проблемы сMVC4 model binding for ApiControllersНо ни один из них, похоже, не решает проблему, которую я вижу.

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

<code>public class MyRequestModel
{
    public List<long> ListOfIntegers { get; set; }

    ...
}
</code>

И метод API GET, как это:

<code>public ResultsResponseModel Get(MyRequestModel request)
{
    // use request.ListOfIntegers meaningfully

    ...

    return response;
}
</code>

Я в основном хочу иметь возможность сказать/api/results/?listOfIntegers=1+2+3+4+5 и что решимость кList<long> имущество.

Я попробовал свои обычные приемы привязки модели, но, как и большинство веб-API вMVC4 it appears to have a totally separate path for model binding.

Самое дальнее, что я получил, - это использованиеSystem.Web.Http.ModelBinding.ModelBinder атрибут наMyRequestModelи создание связующего для модели, который "реализован"System.Web.Http.ModelBinding.IModelBinder, Это последовательно приводит к исключению ссылки на объект со следами стека, которые никогда не затрагивают мой код.

Кто-нибудь ударил это? Есть мысли о том, что попробовать дальше?

UPDATEВот трассировка стека, которую я записал в своем обычаеExceptionFilterAttribute:

<code>Object reference not set to an instance of an object.
    at System.Web.Http.ModelBinding.DefaultActionValueBinder.BindParameterValue(HttpActionContext actionContext, HttpParameterBinding parameterBinding)
    at System.Web.Http.ModelBinding.DefaultActionValueBinder.<>c__DisplayClass1.BindValuesAsync>b__0(RequestContentReadKind contentReadKind)
    at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass38.<ToAsyncVoidTask>b__37()
    at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)
</code>
 jorgehmv11 апр. 2012 г., 00:03
Вы можете отправить трассировку стека?
 Brandon Linton11 апр. 2012 г., 00:37
Просто добавил трассировку стека

Ответы на вопрос(1)

Решение Вопроса

Если вы говорите об ApiControllers, то вы пытаетесь смоделировать связывание в Web API, а теперь MVC. Вот примерное связующее модели

  public class MyRequestModelBinderProvider : ModelBinderProvider
    {
        MyRequestModelBinder binder = new MyRequestModelBinder();
        public IdeaModelBinderProvider()
        {          
        }

        public override IModelBinder GetBinder(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType == typeof(MyRequestModel))
            {
                return binder;
            }

            return null;
        }
    } 

Вот пример регистрации поставщика связывателя пользовательской модели

 IEnumerable<object> modelBinderProviderServices = GlobalConfiguration.Configuration.ServiceResolver.GetServices(typeof(ModelBinderProvider));
 List<Object> services = new List<object>(modelBinderProviderServices);
 services.Add(new MyRequestModelBinderProvider());
 GlobalConfiguration.Configuration.ServiceResolver.SetServices(typeof(ModelBinderProvider), services.ToArray());

Теперь в вашем пользовательском связывателе модели вы используете контексты для доступа к значениям строки запроса

  public class MyRequestModelBinder :  IModelBinder
    {
        public MyRequestModelBinder()
        {

        }

        public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
        {
            MyRequestModel yourModel; 
            //use contexts to access query string values
            //create / update your model properties

            bindingContext.Model = yourModel;  
            //return true || false if binding is successful
        }

Убедитесь, что вы используете классы и интерфейсы для WebAPI, а не MVC. Некоторые из имен совпадают, но разные пространства имен и DLL

 Brandon Linton11 апр. 2012 г., 15:27
Итак, я думаю, что у меня есть правильная структура на месте. Вы знаете, существует ли какой-либо способ вызывать привязку модели Web API по умолчанию, а затем просто вручную управлять параметрами значений списка в связывателе модели?
 11 апр. 2012 г., 22:45
вызовите base.GetBinder в вашем пользовательском ModelBinderProvide, чтобы получить связыватель модели по умолчанию, и поместите его в частное поле вашего настраиваемого связывателя модели, чтобы вы могли использовать его из связывателя модели.
 Brandon Linton12 апр. 2012 г., 15:46
@FrancescoAbbruzzese Я бы хотел сделать что-то подобное - к сожалению, поскольку мы наследуем от ModelBinderProvider, который является абстрактным классом с абстрактным базовым методом GetBinder, по умолчанию он не готов для меня. Я пытался отправить экземпляры из типов вSystem.Web.Http.Modelbinding.ModelBinders без особой удачи. Есть еще идеи?
 12 апр. 2012 г., 16:01
ммм, дело в том, что связыватель модели по умолчанию не является общедоступным, и, поскольку мы не можем получить копию связывателя модели по умолчанию ... трудно найти выход. Похоже, есть выбор дизайна "скрыть" полностью функциональные возможности связующего по умолчанию модели. Возможный подвох: используйте доступные сейчас источники, чтобы определить связыватель модели PUBLIC по умолчанию ... Само собой разумеется, мне это не нравится :) В следующие дни я начну изучать источники ... может быть, я найду другую точку расширения ... но я чувствую, что связыватель модели по умолчанию сделан полностью скрытым
 Brandon Linton12 апр. 2012 г., 16:12
+1 и принято - я все еще хотел бы иметь возможность сначала вызывать привязку модели по умолчанию в пользовательском связывателе, что, вероятно, должно стать отдельным вопросом. Это дало мне точку расширения, которую я искал, чтобы взять под контроль привязку модели для определенного типа. @FrancescoAbbruzzese У меня, вероятно, скоро будет другой вопрос по этому вопросу, если вы найдете какие-либо другие хуки :)

Ваш ответ на вопрос