mvc 操作方法中泛型类型参数的 dot net core 自定义模型绑定

blo*_*s4t 2 asp.net-mvc generic-type-argument actionmethod custom-model-binder asp.net-core

我正在构建一个简单的搜索、排序、页面功能。我附上了下面的代码。以下是用例:

  1. 我的目标是通过每个请求传递“当前过滤器”以保留它们,特别是在排序和分页时。

  2. 我不想用许多(如果不是太多)参数污染我的操作方法,而是考虑使用保存当前过滤器的通用类型参数。

  3. 我需要一个能够实现此目的的自定义模型绑定器。

有人可以发布一个示例实现吗?

PS:我也在探索替代方案,而不是来回传递复杂的对象。但我需要将此路线作为最后的手段,并且我找不到自定义模型绑定泛型类型参数的好示例。任何指向此类示例的指针也会有所帮助。谢谢!。

public async Task<IActionResult> Index(SearchSortPage<ProductSearchParamsVm> currentFilters, string sortField, int? page)
{
    var currentSort = currentFilters.Sort;
    // pass the current sort and sortField to determine the new sort & direction
    currentFilters.Sort = SortUtility.DetermineSortAndDirection(sortField, currentSort);
    currentFilters.Page = page ?? 1;

    ViewData["CurrentFilters"] = currentFilters;

    var bm = await ProductsProcessor.GetPaginatedAsync(currentFilters);

    var vm = AutoMapper.Map<PaginatedResult<ProductBm>, PaginatedResult<ProductVm>>(bm);

    return View(vm);
}

public class SearchSortPage<T> where T : class
{
    public T Search { get; set; }
    public Sort Sort { get; set; }
    public Nullable<int> Page { get; set; }
}

public class Sort
{
    public string Field { get; set; }
    public string Direction { get; set; }
}

public class ProductSearchParamsVm
{
    public string ProductTitle { get; set; }
    public string ProductCategory { get; set; }
    public Nullable<DateTime> DateSent { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Lak*_*ono 5

首先创建模型绑定器,它应该实现接口 IModelBinder

SearchSortPageModelBinder.cs

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

        SearchSortPage<T> ssp = new SearchSortPage<T>();

        //TODO: Setup the SearchSortPage<T> model 

        bindingContext.Result = ModelBindingResult.Success(ssp);

        return TaskCache.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后创建应该实现 IModelBinderProvider 接口的 Model Binder Provider

SearchSortPageModelBinderProvider.cs

public class SearchSortPageModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.ModelType.GetTypeInfo().IsGenericType && 
            context.Metadata.ModelType.GetGenericTypeDefinition() == typeof(SearchSortPage<>))
        {
            Type[] types = context.Metadata.ModelType.GetGenericArguments();
            Type o = typeof(SearchSortPageModelBinder<>).MakeGenericType(types);

            return (IModelBinder)Activator.CreateInstance(o);
        }

        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后一件事是注册 Model Binder Provider,它应该在 Startup.cs 中完成

public void ConfigureServices(IServiceCollection services)
{
        .
        .

        services.AddMvc(options=>
        {
            options.ModelBinderProviders.Insert(0, new SearchSortPageModelBinderProvider());
        });
        .
        .
}
Run Code Online (Sandbox Code Playgroud)