我需要规范化字符串数据(将一些字符相互替换,例如:'ی' 与 'ي' 或修剪它)。为此,我创建了以下模型绑定器,如下所示:
public class StringModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == ValueProviderResult.None)
return Task.CompletedTask;
var value = Normalize(valueProviderResult.FirstValue);
bindingContext.Result = ModelBindingResult.Success(value);
return Task.CompletedTask;
}
}
此活页夹适用于两者Query
和Route
绑定,但如果我使用FromBody
属性则失败。它失败了,因为BindModelAsync
永远不会被调用。我在这里找到了针对此问题提出的另一个问题,遗憾的是没有答案。
我试图扩展它,ComplexObjectModelBinder
但它是一个sealed
类(并且也不提供任何构造函数)。因此,我尝试扩展ComplexTypeModelBinder
注释为已过时的内容。
我已经ComplexTypeModelBinderProvider
从源代码中复制了逻辑,令我惊讶的是BindModelAsync
,我StringModelBinder
现在收到了电话。但仍然失败,因为bindingContext.ValueProvider
它只包含路由的提供者,结果仍然为空。
我现阶段的活页夹提供者:
public class MyModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
{
var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
for (var i = 0; i < context.Metadata.Properties.Count; i++)
{
var property = context.Metadata.Properties[i];
propertyBinders.Add(property, context.CreateBinder(property));
}
var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
return new ComplexTypeModelBinder(
propertyBinders,
loggerFactory,
allowValidatingTopLevelNodes: true);
}
if (context.Metadata.ModelType == typeof(string))
{
return new StringModelBinder();
}
return null;
}
}
我还尝试从正文创建一个提供程序并将我的更改StringModelBinder
为:
public class StringModelBinder : IModelBinder
{
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == ValueProviderResult.None)
{
var context = new ValueProviderFactoryContext(bindingContext.ActionContext);
await new FormValueProviderFactory().CreateValueProviderAsync(context);
valueProviderResult = context.ValueProviders
.Select(x => x.GetValue(bindingContext.ModelName))
.FirstOrDefault(x => x != ValueProviderResult.None);
if (valueProviderResult == ValueProviderResult.None) return;
}
var value = valueProviderResult.FirstValue.Replace("A", "B");
bindingContext.Result = ModelBindingResult.Success(value);
}
}
现在的问题是,在 .Net 5 中进行这种标准化的最佳方法是什么?
谁可能担心:这个问题可能看起来是重复的,但我找不到任何与 .Net 5 相关的内容,如果有问题可以回答这个ComplexTypeModelBinder
问题,它不适合 .Net 5,因为它已经过时了。