Asp Net Core RC2. Связывание абстрактной модели класса
В RC1 я использую следующий код для привязки абстрактных классов или интерфейсов:
public class MessageModelBinder : IModelBinder {
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext) {
if(bindingContext.ModelType == typeof(ICommand)) {
var msgTypeResult = bindingContext.ValueProvider.GetValue("messageType");
if(msgTypeResult == ValueProviderResult.None) {
return ModelBindingResult.FailedAsync(bindingContext.ModelName);
}
var type = Assembly.GetAssembly(typeof(MessageModelBinder )).GetTypes().SingleOrDefault(t => t.FullName == msgTypeResult.FirstValue);
if(type == null) {
return ModelBindingResult.FailedAsync(bindingContext.ModelName);
}
var metadataProvider = (IModelMetadataProvider)bindingContext.OperationBindingContext.HttpContext.RequestServices.GetService(typeof(IModelMetadataProvider));
bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(type);
}
return ModelBindingResult.NoResultAsync;
}
}
Это связующее читает только тип модели (messageType
параметр) из строки запроса и переопределяет тип метаданных. А остальная часть работы выполняется стандартными связующими, такими какBodyModelBinder
.
В Startup.cs я просто добавляю первый компоновщик:
services.AddMvc().Services.Configure<MvcOptions>(options => {
options.ModelBinders.Insert(0, new MessageModelBinder());
});
контроллер:
[Route("api/[controller]")]
public class MessageController : Controller {
[HttpPost("{messageType}")]
public ActionResult Post(string messageType, [FromBody]ICommand message) {
}
}
Как я могу выполнить это в RC2?
Насколько я понимаю, теперь я должен использоватьIModelBinderProvider
, Хорошо, я попробовал Startup.cs:
services.AddMvc().Services.Configure<MvcOptions>(options => {
options.ModelBinderProviders.Insert(0, new MessageModelBinderProvider());
});
ModelBinderProvider:
public class MessageModelBinderProvider : IModelBinderProvider {
public IModelBinder GetBinder(ModelBinderProviderContext context) {
if(context == null) {
throw new ArgumentNullException(nameof(context));
}
return context.Metadata.ModelType == typeof(ICommand) ? new MessageModelBinder() : null;
}
}
ModelBinder:
public class MessageModelBinder : IModelBinder {
public Task BindModelAsync(ModelBindingContext bindingContext) {
if(bindingContext.ModelType == typeof(ICommand)) {
var msgTypeResult = bindingContext.ValueProvider.GetValue("messageType");
if(msgTypeResult == ValueProviderResult.None) {
bindingContext.Result = ModelBindingResult.Failed(bindingContext.ModelName);
return Task.FromResult(0);
}
var type = typeof(MessageModelBinder).GetTypeInfo().Assembly.GetTypes().SingleOrDefault(t => t.FullName == msgTypeResult.FirstValue);
if(type == null) {
bindingContext.Result = ModelBindingResult.Failed(bindingContext.ModelName);
return Task.FromResult(0);
}
var metadataProvider = (IModelMetadataProvider)bindingContext.OperationBindingContext.HttpContext.RequestServices.GetService(typeof(IModelMetadataProvider));
bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(type);
bindingContext.Result = ModelBindingResult.Success(bindingContext.ModelName, Activator.CreateInstance(type));
}
return Task.FromResult(0);
}
}
Но я не могу указатьNoResult
, Если я не укажуbindingContext.Result
Я получаю нулевую модель в контроллере. Если я укажуbindingContext.Result
, Я получаю пустую модель без установки полей модели.