我有一个自定义模型活页夹,它将发布的值转换为另一个模型。
问题是bindingContext.ValueProvider.GetValue(modelName)
即使从客户端发布值也不会返回任何内容。
操作方法
[HttpPost]
public ActionResult Update([DataSourceRequest] DataSourceRequest request,
[Bind(Prefix = "models")] AnotherModel items)
{
return Ok();
}
目标模型类
[ModelBinder(BinderType = typeof(MyModelBinder))]
public class AnotherModel
{
IEnumerable<Dictionary<string, object>> Items { get; set; }
}
客户模型粘合剂
public class MyModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
// ISSUE: valueProviderResult is always None
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
//here i will convert valueProviderResult to AnotherModel
return Task.CompletedTask;
}
}
快速观察显示ValueProvider确实具有值
UPDATE1
当我可以通过IFormCollection进行迭代时,在Update操作方法中,Request.Form具有所有的键和值对。不确定为什么模型联编程序无法检索它。
foreach (var f in HttpContext.Request.Form)
{
var key = f.Key;
var v = f.Value;
}
答案 0 :(得分:0)
如果检查MVC CollectionModelBinder的源代码,您会注意到“ name [index]”形式的值将返回ValueProviderResult。无,需要单独处理。
似乎您正在尝试解决错误的问题。我建议绑定到像Dictionary
这样的标准集合类。
要么;
public ActionResult Update([DataSourceRequest] DataSourceRequest request,
[Bind(Prefix = "models")] Dictionary<string, RecordTypeName> items)
或者;
public class AnotherModel : Dictionary<string, RecordTypeName> {}
如果您不知道每个字典值在编译时将具有哪种类型,那么可以在其中使用自定义活页夹。
答案 1 :(得分:0)
我的例子
在我的客户端中,我在请求中发送一个标头,该标头是Base64String(Json序列化对象)
对象-> Json-> Base64。
标题不能为多行。使用base64,我们得到1行。
所有这些都适用于Body和其他来源。
标题类
public class RequestHeader : IHeader
{
[Required]
public PlatformType Platform { get; set; } //Windows / Android / Linux / MacOS / iOS
[Required]
public ApplicationType ApplicationType { get; set; }
[Required(AllowEmptyStrings = false)]
public string UserAgent { get; set; } = null!;
[Required(AllowEmptyStrings = false)]
public string ClientName { get; set; } = null!;
[Required(AllowEmptyStrings = false)]
public string ApplicationName { get; set; } = null!;
[Required(AllowEmptyStrings = true)]
public string Token { get; set; } = null!;
public string ToSerializedString()
{
return JsonConvert.SerializeObject(this);
}
}
IHeader界面
public interface IHeader
{
}
模型活页夹
public class HeaderParameterModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
StringValues headerValue = bindingContext.HttpContext.Request.Headers.Where(h =>
{
string guid = Guid.NewGuid().ToString();
return h.Key.Equals(bindingContext.ModelName ?? guid) |
h.Key.Equals(bindingContext.ModelType.Name ?? guid) |
h.Key.Equals(bindingContext.ModelMetadata.ParameterName);
}).Select(h => h.Value).FirstOrDefault();
if (headerValue.Any())
{
try
{
//Convert started
bindingContext.Model = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(Convert.FromBase64String(headerValue)), bindingContext.ModelType);
bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
}
catch
{
}
}
return Task.CompletedTask;
}
}
Model Binder提供商
我们可以使用任何BindingSource。
public class ParametersModelBinderProvider : IModelBinderProvider
{
private readonly IConfiguration configuration;
public ParametersModelBinderProvider(IConfiguration configuration)
{
this.configuration = configuration;
}
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context.Metadata.ModelType.GetInterfaces().Where(value => value.Name.Equals(nameof(ISecurityParameter))).Any() && BindingSource.Header.Equals(context.Metadata.BindingSource))
{
return new SecurityParameterModelBinder(configuration);
}
if (context.Metadata.ModelType.GetInterfaces().Where(value=>value.Name.Equals(nameof(IHeader))).Any() && BindingSource.Header.Equals(context.Metadata.BindingSource))
{
return new HeaderParameterModelBinder();
}
return null!;
}
}
在Startup.cs中
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.ModelBinderProviders.Insert(0,new ParametersModelBinderProvider(configuration));
});
}
控制器操作
ExchangeResult是我的结果类。
[HttpGet(nameof(Exchange))]
public ActionResult<ExchangeResult> Exchange([FromHeader(Name = nameof(RequestHeader))] RequestHeader header)
{
//RequestHeader previously was processed in modelbinder.
//RequestHeader is null or object instance.
//Some instructions
}