Zok*_*oka 2 c# model-binding model-validation asp.net-core
我对本文中的多态绑定示例进行了一些更改。
[Required]属性。CPUIndexScreenSizeLaptopSmartPhone到目前为止还可以。
现在添加新类:
public class DeviceWrapper
{
public Device Device { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
并修改AddDevice.cshtml.cs文件:
...
[BindProperty]
public DeviceWrapper Device { get; set; } // model type changed here
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
switch (Device.Device) // added Device. prefix to respect new model structure
{
case Laptop laptop:
Message = $"You added a Laptop with a CPU Index of {laptop.CPUIndex}.";
break;
case SmartPhone smartPhone:
Message = $"You added a SmartPhone with a Screen Size of {smartPhone.ScreenSize}.";
break;
}
return RedirectToPage("/Index");
}
Run Code Online (Sandbox Code Playgroud)
还修改页面AddDevice.cshtml以尊重新的模型结构。即在所有属性中Device.{prop}为每个添加前缀。例子:Device.name
<select id="Device_Kind" name="Device.Device.Kind" asp-items="Model.DeviceKinds" class="form-control"></select>
Run Code Online (Sandbox Code Playgroud)
现在运行应用程序。将断点放入AddDeviceModel.OnPost方法中。与第一个示例中的操作相同 - 创建设备而不填充 CPU 索引或屏幕大小。ModelState.IsValid检查now的值true。模型已绑定,但未经验证。我应该做什么来对这个包装模型应用验证。
在我的示例分支上尝试一下: https: //github.com/zoka-cz/AspNetCore.Docs/tree/master/aspnetcore/mvc/advanced/custom-model-binding/3.0sample/PolymorphicModelBinding
我发现,还有更多的问题:
首先,这里的官方示例以及示例源代码中都包含错误:
// Setting the ValidationState ensures properties on derived types are correctly
bindingContext.ValidationState[newBindingContext.Result] = new ValidationStateEntry
{ Metadata = modelMetadata };
Run Code Online (Sandbox Code Playgroud)
应该是
// Setting the ValidationState ensures properties on derived types are correctly
bindingContext.ValidationState[newBindingContext.Result.Model] = new ValidationStateEntry
{ Metadata = modelMetadata };
Run Code Online (Sandbox Code Playgroud)
(注意索引器 - 它应该是模型本身。模型实例是关键,通过它搜索 ValidationState 字典)。
但是,它并没有解决原始问题,也没有验证包装的模型。还有另一个问题,我认为这是 ASP.NET Core 中的错误(已报告- 请参阅详细信息)。抽象Device类未经验证,因为它被跳过(出于什么原因?),因为DeviceWrapper它的子属性没有验证器,因为它不考虑真实类型(Laptop或SmartPhone)的元数据,而只考虑元数据对于抽象类型Device,它实际上没有验证器。
这一发现让我找到了我认为更好的解决方案。我必须强制验证器验证设备。我必须说类型的属性Device有验证器。IValidatableObject这可以通过在抽象类上实现来实现Device:
public abstract class Device : IValidatableObject
{
public string Kind { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
yield return ValidationResult.Success; // just to force validator to validate according to the correct metadata
}
}
Run Code Online (Sandbox Code Playgroud)
可能会发生您无法更改抽象类的情况,那么您可能会发现第二种方式更可行:
public class ForceValidationAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
return true;
}
}
public class DeviceWrapper
{
[ForceValidation] // this will force the validator to work according to the correct metadata
public Device Device { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这两种方法都不好,我相信它应该在 ASP.NET Core 中修复,但作为解决方法,在我看来它是更干净的解决方案,因为生成的 ModelState 是正确的。
| 归档时间: |
|
| 查看次数: |
800 次 |
| 最近记录: |