在View中使用接口类型作为模型并使用真实类型属性和验证的最佳实践
本文关键字:验证 属性 最佳 类型 接口类型 View 模型 真实 | 更新日期: 2023-09-27 18:03:17
我有这样的接口:
public interface IFoo
{
decimal Amount { get; set; }
}
我有一些视图模型实现它:
public class Foo1 : IFoo
{
[Display(Name = "Foo1 Amount")]
[Range(6, 11)]
public decimal Amount { get; set; }
}
public class Foo2 : IFoo
{
[Display(Name = "Foo2 Amount")]
[Range(1, 5)]
public decimal Amount { get; set; }
}
我不想为Foo1
和Foo2
分别创建一个新视图。
所以,我已经创建了一个视图,它有IFoo
类型的模型。
@model IFoo
<div>
@Html.LabelFor(x => x.Amount)
@Html.TextBoxFor(x => x.Amount)
@Html.ValidationMessageFor(x => x.Amount)
</div>
但是,它不会创建客户端不显眼的属性,如客户端Range
属性。
如果我为每一种类型创建一个新的视图,那么一切都会好起来。
更新:我已经尝试改变接口抽象类提供的答案,但它没有帮助。
遗憾的是,使用接口无法做到这一点。当您使用html helper生成html时,它首先为属性生成ModelMetadata
(在强类型html helper的情况下,通过调用
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
这会基于属性生成元数据,并考虑到它的属性。在TextBoxFor()
的情况下,然后调用HtmlHelper
的GetUnobtrusiveValidationAttributes()
方法来生成data-val-*
属性。
除非您要创建自己的ModelMetadataProvider并覆盖CreateMetadata()方法,否则您需要为每个具体类创建单独的视图。
我建议您使用抽象或仅使用基类,用一些默认范围定义Amount属性并在子类中重写。
public abstract class Test
{
protected int _number;
[System.ComponentModel.DataAnnotations.Range(0, 10)]
public abstract int NumProp
{
get;
set;
}
}
public class Test2 : Test
{
[System.ComponentModel.DataAnnotations.Range(100, 1000)]
public override int NumProp
{
get{
return _number;
}
set
{
_number = value;
}
}
}