Asp net core rc2. Abstract class model binding

后端 未结 1 1446
后悔当初
后悔当初 2020-12-19 08:40

In the RC1 I use the following code for abstract classes or interfaces binding:

public class MessageModelBinder : IModelBinder {

    public Task

        
相关标签:
1条回答
  • 2020-12-19 09:17

    I had a similar requirement with custom model binding and abstract classes and the suggestions posted by dougbu on github AspNet/Mvc/issues/4703 worked for me. I upgraded from RC1 to ASP.NET Core 1.0 and needed to modify my custom model binder with his recommendations. I've copy & pasted his code below in case the link to the github issue breaks. Read the comments in the github issue for security considerations around code that creates objects of a requested type on the server.

    MessageModelBinderProvider

    public class MessageModelBinderProvider : IModelBinderProvider 
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            if (context.Metadata.ModelType != typeof(ICommand))
            {
                return null;
            }
    
            var binders = new Dictionary<string, IModelBinder>();
            foreach (var type in typeof(MessageModelBinderProvider).GetTypeInfo().Assembly.GetTypes())
            {
                var typeInfo = type.GetTypeInfo();
                if (typeInfo.IsAbstract || typeInfo.IsNested)
                {
                    continue;
                }
    
                if (!(typeInfo.IsClass && typeInfo.IsPublic))
                {
                    continue;
                }
    
                if (!typeof(ICommand).IsAssignableFrom(type))
                {
                    continue;
                }
    
                var metadata = context.MetadataProvider.GetMetadataForType(type);
                var binder = context.CreateBinder(metadata);
                binders.Add(type.FullName, binder);
            }
    
            return new MessageModelBinder(context.MetadataProvider, binders);
        }
    }
    

    MessageModelBinder

    public class MessageModelBinder : IModelBinder
    {
        private readonly IModelMetadataProvider _metadataProvider;
        private readonly Dictionary<string, IModelBinder> _binders;
    
        public MessageModelBinder(IModelMetadataProvider metadataProvider, Dictionary<string, IModelBinder> binders)
        {
            _metadataProvider = metadataProvider;
            _binders = binders;
        }
    
        public async Task BindModelAsync(ModelBindingContext bindingContext)
        {
            var messageTypeModelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, "messageType");
            var messageTypeResult = bindingContext.ValueProvider.GetValue(messageTypeModelName);
            if (messageTypeResult == ValueProviderResult.None)
            {
                bindingContext.Result = ModelBindingResult.Failed();
                return;
            }
    
            IModelBinder binder;
            if (!_binders.TryGetValue(messageTypeResult.FirstValue, out binder))
            {
                bindingContext.Result = ModelBindingResult.Failed();
                return;
            }
    
            // Now know the type exists in the assembly.
            var type = Type.GetType(messageTypeResult.FirstValue);
            var metadata = _metadataProvider.GetMetadataForType(type);
    
            ModelBindingResult result;
            using (bindingContext.EnterNestedScope(metadata, bindingContext.FieldName, bindingContext.ModelName, model: null))
            {
                await binder.BindModelAsync(bindingContext);
                result = bindingContext.Result;
            }
    
            bindingContext.Result = result;
        }
    }
    
    0 讨论(0)
提交回复
热议问题