Объединение настраиваемой привязки ядра .NET и привязки по умолчанию

Я создаю привязку пользовательской модели для модели представления, реализуя IModelBinder.

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

public class ApplicationViewModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        // get .net core to bind values on model

        // Cary out any customization of the models properties

        bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
        return Task.CompletedTask; 
    }
}

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

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

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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
0
2 628
1

Ответы 1

Для пользовательского ComplexTypeModelBinder вы можете унаследовать от ComplexTypeModelBinder.

  1. Модель

    public class BinderModel
    {
       public int Id { get; set; }
       public string Name { get; set; }
       public string BinderValue { get; set; }
    }
    
  2. Действие контроллера

    [HttpPost]
    public void Post([FromForm]BinderModel value)
    {
    
    }
    
  3. CustomBinder

    public class CustomBinder : ComplexTypeModelBinder
    {
        private readonly IDictionary<ModelMetadata, IModelBinder> _propertyBinders;
        public CustomBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders)
        : base(propertyBinders)
        {
            _propertyBinders = propertyBinders;
        }
        protected override Task BindProperty(ModelBindingContext bindingContext)
        {
            if (bindingContext.FieldName == "BinderValue")
            {
                bindingContext.Result = ModelBindingResult.Success("BinderValueTest");
                return Task.CompletedTask;
            }
            else
            {
                return base.BindProperty(bindingContext);
            }
        }
        protected override void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result)
        {
            base.SetProperty(bindingContext, modelName, propertyMetadata, result);
        }
    }
    
  4. CustomBinderProvider

    public class CustomBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
            {
                var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
                for (var i = 0; i < context.Metadata.Properties.Count; i++)
                {
                    var property = context.Metadata.Properties[i];
                    propertyBinders.Add(property, context.CreateBinder(property));
                }
    
                //var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
                //return new ComplexTypeModelBinder(propertyBinders, loggerFactory);
                return new CustomBinder(propertyBinders);
            }
    
            return null;
        }
    
    }
    
  5. Поставщик инъекций

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(options => {
            options.ModelBinderProviders.Insert(0, new CustomBinderProvider());
        });
    }
    

ComplexTypeModelBinder не имеет конструктора с одним параметром. Вместо этого у меня работал IModelBinder.

tnJed 02.12.2019 22:16

Другие вопросы по теме