public class BondsFilterModel : BaseListRequest
{
public string Keyword { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
}
public class BaseListRequest
{
public int PageSize { get; set; }
public int Page { get; set; }
public string SortColumn { get; set; }
public SortDirection SortDirection { get; set; }
}
public enum SortDirection
{
Ascending = 1,
Descending = 2
}
В полном .NET Framework вы могли бы сделать
public class BaseListRequestModelBinder : DefaultModelBinder
{
public const string KendoSort = "sort";
public const string KendoPage = "page";
public const string KendoPageSize = "pageSize";
public const char SplitChar = '-';
public const string AscendingDirectionString = "asc";
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
if (bindingContext.Model is BaseListRequest model)
{
var page = Convert.ToInt32(request.Form[KendoPage]);
model.Page = Math.Max(page - 1, 0);
model.PageSize = Convert.ToInt32(request.Form[KendoPageSize]);
var sort = request.Form[KendoSort];
if (!string.IsNullOrWhiteSpace(sort))
{
model.SortColumn = sort.Remove(sort.LastIndexOf(SplitChar));
model.SortDirection = sort.Split(SplitChar)
.LastOrDefault()
?.Equals(AscendingDirectionString, StringComparison.InvariantCultureIgnoreCase) ?? false ? SortDirection.Ascending : SortDirection.Descending;
}
}
base.OnModelUpdated(controllerContext, bindingContext);
}
}
public class BaseListRequestModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(Type modelType)
{
if (typeof(BaseListRequest).IsAssignableFrom(modelType))
{
return new BaseListRequestModelBinder();
}
return null;
}
}
и в global.asax
protected void Application_Start()
{
// other code
ModelBinderProviders.BinderProviders.Add(new BaseListRequestModelBinderProvider());
}
и это будет заполнять только свойства базового класса, производный класс будет заполняться из связующего устройства модели по умолчанию.
В .NET Core, когда я делаю:
public class BaseListRequestModelBinder : IModelBinder
{
public const string KendoSort = "sort";
public const string KendoPage = "page";
public const string KendoPageSize = "pageSize";
public const char SplitChar = '-';
public const string AscendingDirectionString = "asc";
public Task BindModelAsync(ModelBindingContext bindingContext)
{
var model = Activator.CreateInstance(bindingContext.ModelType) as BondsFilterModel;
var pageString = bindingContext.ValueProvider.GetValue(KendoPage).FirstValue;
var page = Convert.ToInt32(pageString);
model.Page = Math.Max(page - 1, 0);
var pageSizeString = bindingContext.ValueProvider.GetValue(KendoPageSize).FirstValue;
model.PageSize = Convert.ToInt32(pageSizeString);
var sort = bindingContext.ValueProvider.GetValue(KendoSort).FirstValue;
if (!string.IsNullOrWhiteSpace(sort))
{
model.SortColumn = sort.Remove(sort.LastIndexOf(SplitChar));
model.SortDirection = sort.Split(SplitChar)
.LastOrDefault()
?.Equals(AscendingDirectionString, StringComparison.InvariantCultureIgnoreCase) ?? false ? SortDirection.Ascending : SortDirection.Descending;
}
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
public class BaseListRequestModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (typeof(BaseListRequest).IsAssignableFrom(context.Metadata.ModelType))
{
return new BinderTypeModelBinder(typeof(BaseListRequestModelBinder));
}
return null;
}
}
и в Startup.cs
services.AddMvc(config => config.ModelBinderProviders.Insert(0, new BaseListRequestModelBinderProvider()))
Мой связыватель вызывается, и базовый класс привязан правильно. Но свойства производного класса не устанавливаются.
Я предполагаю, что основное различие между полной .NET Framework и Core состоит в том, что мне приходится создавать экземпляр Model самостоятельно в связующем в Core, тогда как в полной .NET Framework я изменяю существующую модель.
Есть ли способ связать только базовый класс и оставить производный класс для связывателей по умолчанию, как в полной .NET Framework?