编辑:所以事实证明我ModelBinder
的实际上不是问题。问题出在我的ValueConverter
. 把这个留在这里,因为我认为它说明了如何做一个自定义模型绑定器。
这个问题有很多代码。我正在努力做到尽可能彻底和精确。
我有一Measurement
堂课。我的许多模型都有一个或多个类型的属性Measurement
。此类使用ValueConverter
. 我想做的是在提交表单时将表单数据(即字符串)转换为这种类型。所以,我创建了一个自定义ModelBinder
.
public class MeasurementModelBinder : IModelBinder
{
public MeasurementModelBinder() { }
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if(bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); }
ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if(valueProviderResult == ValueProviderResult.None) { throw new Exception(); }
string valueString = valueProviderResult.FirstValue;
if (string.IsNullOrEmpty(valueString)) { throw new Exception(); }
Measurement result = new Measurement(valueString);
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
我希望这MeasurementModelBinder
适用于每个模型中这种类型的所有属性。所以我正在努力做到这一点。这是具有Measurement
类型属性的模型的示例。
public class Material
{
[Key]
public int Key { get; set; }
public string Name { get; set; }
public Measurement Density { get; set; }
public Measurement Conductivity { get; set; }
[Display(Name="Specific Heat")]
public Measurement SpecificHeat { get; set; }
public string Description { get; set; }
public DateTime Created { get; set; }
public DateTime Updated { get; set; }
public Material() { }
public Material(string name, Measurement density, Measurement conductivity, Measurement specificHeat, string description = "")
{
Name = name;
Density = density;
Description = description;
Conductivity = conductivity;
SpecificHeat = specificHeat;
}
public override string ToString() { return Name; }
}
至于控制器,我现在只是在使用测试控制器,这是 Visual Studio 自动生成的带有视图的 MVC 实体框架控制器之一的修改版本。这是控制器中的操作之一。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Material material)
{
material.Created = DateTime.Now;
material.Updated = DateTime.Now;
if (ModelState.IsValid)
{
_context.Add(material);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(material);
}
在Created
与Updated
磁场不受形式提供的,所以我填补他们自己。但是,其他所有内容都由表单填充,作为字符串。您可以Measurement
在上面的自定义模型绑定器类中看到对象是如何构造的。
我创建了一个ModelBinderProvider
类,如下所示。
public class MeasurementModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if(context == null) { throw new ArgumentException(nameof(context)); }
if(!context.Metadata.IsComplexType && context.Metadata.ModelType == typeof(Measurement))
{
return new MeasurementModelBinder();
}
return null;
}
}
我已经在Startup.ConfigureServices()
方法中注册了提供者,就像这样。
services.AddMvc(options =>
{
options.ModelBinderProviders.Insert(0, new MeasurementModelBinderProvider());
});
这是正在提交的表格。
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Description" class="control-label"></label>
<input asp-for="Description" class="form-control" />
<span asp-validation-for="Description" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Density" class="control-label"></label>
<input asp-for="Density" class="form-control" />
<span asp-validation-for="Density" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Conductivity" class="control-label"></label>
<input asp-for="Conductivity" class="form-control" />
<span asp-validation-for="Conductivity" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="SpecificHeat" class="control-label"></label>
<input asp-for="SpecificHeat" class="form-control" />
<span asp-validation-for="SpecificHeat" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
我希望通过提交此表单向材料表添加一条新记录,并填写所有字段。它不会这样做。相反,它添加了一个所有Measurement
属性都为空的新记录。
我尝试将[ModelBinder(BinderType = typeof(MeasurementModelBinder))]
属性添加到Measurement
类中,但没有帮助。事实上,它导致了“无法解决服务”错误,当我通过添加services.AddScoped<IModelBinder, MeasurementModelBinder>();
到摆脱该错误时ConfigureServices()
,我的操作仍然得到相同的结果。
我也尝试将[BindProperty(BinderType typeof(MeasurementModelBinder))]
属性添加到模型本身的属性中,但没有帮助。此外,这是我宁愿不做的事情。有没有办法让它在所有Measurement
类型属性上工作?如果没有,有没有办法让它工作?
谢谢。
我尝试了您的代码,当我将[ModelBinder(BinderType = typeof(MeasurementModelBinder))]
属性添加到Measurable
类时,它对我有用。我认为您应该将[ModelBinder(BinderType = typeof(MeasurementModelBinder))]
属性添加到Measurement
类中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句