首页 > 解决方案 > 运行时类型的 ASP.NET Core ModelBinding

问题描述

如何编写将基于查询字符串创建模型实例的活页夹

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

        string modelName = bindingContext.ModelName;
        ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
        // My own method to get assembly type
        if (!TryGetRequestType(valueProviderResult.FirstValue, out Type requestType))
            return Task.CompletedTask;

        object modelInstance = Activator.CreateInstance(requestType);

        // ???? Call [FromBody] for modelInstance
        bindingContext.Result = ModelBindingResult.Success(modelInstance);
        return Task.CompletedTask;
    }
}

[HttpPost("rpc/{request:required}")]
public async Task<IActionResult> InvokeAsync([ModelBinder(typeof(RpcBinder))]object request, CancellationToken token)
{
    ...
}

并由默认提供者从请求正文中填充此实例

标签: asp.net-core

解决方案


我的解决方案:

public class RpcBinder : IModelBinder
{
    private readonly MvcOptions _options;
    private readonly IHttpRequestStreamReaderFactory _readerFactory;
    private readonly ILoggerFactory _loggerFactory;

    public RpcBinder(IOptions<MvcOptions> options,
        IHttpRequestStreamReaderFactory readerFactory,
        ILoggerFactory loggerFactory)
    {
        _options = options.Value;
        _readerFactory = readerFactory;
        _loggerFactory = loggerFactory;
    }

    publicTask BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));

        string modelName = bindingContext.ModelName;
        ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
        // Get model Type from Assembly by your own realization
        if (valueProviderResult == ValueProviderResult.None
            || !TryGetRequestType(valueProviderResult.FirstValue, out Type requestType))
            return Task.CompletedTask;

        bindingContext.ModelMetadata = bindingContext.ModelMetadata.GetMetadataForType(requestType);

        var bodyBinder = new BodyModelBinder(_options.InputFormatters, _readerFactory, _loggerFactory, _options);
        return bodyBinder.BindModelAsync(bindingContext);
    }
}

推荐阅读