我有一个强类型的视图,它有一个DropDownListFor属性。Guid的验证
下拉列表中的每个项目都由一个GUID表示。
我所追求的是一种验证用户是否从下拉列表中选择项目的方法。目前我还没有看到使用数据注释来做这件事。
有没有办法实现这个使用数据注释,因此客户端和服务器端验证将工作。
我猜我需要做一个自定义的方法来做到这一点,但想知道是否有任何东西已经存在。
我有一个强类型的视图,它有一个DropDownListFor属性。Guid的验证
下拉列表中的每个项目都由一个GUID表示。
我所追求的是一种验证用户是否从下拉列表中选择项目的方法。目前我还没有看到使用数据注释来做这件事。
有没有办法实现这个使用数据注释,因此客户端和服务器端验证将工作。
我猜我需要做一个自定义的方法来做到这一点,但想知道是否有任何东西已经存在。
编辑答案
,在重读你的问题,这听起来像你只是想如果选择的值就知道了。如果是这样的话那么就应用RequiredAttribute
到Guid
财产,并使其可为空的模型
public class GuidModel
{
[Required]
public Guid? Guid { get; set; }
public IEnumerable<Guid> Guids { get; set; }
}
然后在强类型的视图(@model GuidModel
)
@Html.ValidationMessageFor(m => m.Guid)
@Html.DropDownListFor(
m => m.Guid,
Model.Guids.Select(g => new SelectListItem {Text = g.ToString(), Value = g.ToString()}),
"-- Select Guid --")
添加客户端验证的JavaScript脚本客户端验证参考。
控制器看起来像
public class GuidsController : Controller
{
public GuidRepository GuidRepo { get; private set; }
public GuidsController(GuidRepository guidRepo)
{
GuidRepo = guidRepo;
}
[HttpGet]
public ActionResult Edit(int id)
{
var guid = GuidRepo.GetForId(id);
var guids - GuidRepo.All();
return View(new GuidModel { Guid = guid, Guids = guids });
}
[HttpPost]
public ActionResult Edit(GuidModel model)
{
if (!ModelState.IsValid)
{
model.Guids = GuidRepo.All();
return View(model);
}
/* update db */
return RedirectToAction("Edit");
}
}
这将确保Guid
属性是必需的模型绑定GuidModel
。
原来的答案
我不相信有一个现成的数据注释验证属性,它能够这样做的。我写了a blog post about one way to achieve this;这篇文章使用的是一个IoC容器,但如果你想让某些东西能够工作,你可以采用硬编码的依赖关系。
喜欢的东西
public class ValidGuidAttribute : ValidationAttribute
{
private const string DefaultErrorMessage = "'{0}' does not contain a valid guid";
public ValidGuidAttribute() : base(DefaultErrorMessage)
{
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var input = Convert.ToString(value, CultureInfo.CurrentCulture);
// let the Required attribute take care of this validation
if (string.IsNullOrWhiteSpace(input))
{
return null;
}
// get all of your guids (assume a repo is being used)
var guids = new GuidRepository().AllGuids();
Guid guid;
if (!Guid.TryParse(input, out guid))
{
// not a validstring representation of a guid
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
// is the passed guid one we know about?
return guids.Any(g => g == guid) ?
new ValidationResult(FormatErrorMessage(validationContext.DisplayName)) : null;
}
}
,然后发送到控制器动作
public class GuidModel
{
[ValidGuid]
public Guid guid { get; set; }
}
模型这给你的服务器端验证。你也可以编写客户端验证来做到这一点,也许使用RemoteAttribute
,但在这种情况下我没有看到很多的价值,因为唯一会看到这个客户端验证的人是那些在DOM;这对您的普通用户没有任何好处。
其实,你不能使用Required
属性用的GUID(没有我在下面提及的方法),因为他们从struct
继承,因此它们的默认值实际上是Guid.Empty的实例,这将满足的要求Required
属性。现在说,有可能得到你想要的东西,你只需要让你的财产可以为空,拿这个例子...
public class Person
{
[Required] //Only works because the Guid is nullable
public Guid? PersonId { get; set;}
public string FirstName { get; set;}
public string LastName { get; set;}
}
通过标记为空的GUID(使用?,或可为空的,如果你喜欢的很长的路),你让它对浏览器发送的内容结合,保持为空。在你的情况下,只要确保下拉列表的默认选项的值使用空字符串作为它的值。
编辑:唯一要注意这种方法是你最终不得不使用像Person.GetValueOfDefault()
无处不在,并可能测试为Guid.Empty
。我厌倦了这样做,最终创建了自己的验证属性来帮助简化验证Guids(以及其他任何具有默认值的类型,我想将它们视为无效,如int,DateTime等)。但是,我还没有客户端验证,所以验证只发生在服务器上。但是,如果您可以使用可为空的类型,则可以将它与[Required]
(旨在不重复[Required]
的功能)结合使用。那么至少你会得到[Required]
的客户端验证。这意味着您仍然需要使用GetValueOrDefault()
,但至少您不必再为Guid.Empty
进行测试。 Gist链接有一些带有例子的XMLDocs,为简洁起见,我在这里将它们留在这里。我目前在ASP.NET Core中使用它。
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public class RequireNonDefaultAttribute : ValidationAttribute
{
public RequireNonDefaultAttribute()
: base("The {0} field requires a non-default value.")
{
}
public override bool IsValid(object value)
{
return value != null && !Equals(value, Activator.CreateInstance(value.GetType()));
}
}
我试着在模型中使用类似下面的属性的代码,如果我提供空值,模型会失败?根据摘要中的例子,在这种情况下,我认为null是好的,但不是0。请确认 [必须是非默认] public int?测试{get;组; } – Krishna
这是因为你的类型是int ?.任何Nullable <>对象的默认值都是null,所以null无效,但是0。不过,你是正确的,因为我的例子不然。我会解决这个问题。为了得到你要描述的工作(允许null,但不是0),最好使用像这样的'[Range(1,int.MaxValue)] int?我{get; set;} –
@Albercht谢谢您的确认。 – Krishna
我知道这是一个老问题了,但如果任何人有兴趣我设法解决这个问题通过创建[IsNotEmpty]注释(制作的GUID为空的不在我的情况下一个选项)。
这使用反射来确定在属性上是否存在Empty的实现,并且如果这样比较它。
public class IsNotEmptyAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
if (value == null) return false;
var valueType = value.GetType();
var emptyField = valueType.GetField("Empty");
if (emptyField == null) return true;
var emptyValue = emptyField.GetValue(null);
return !value.Equals(emptyValue);
}
}
实际上,除非您将Guid属性标记为可空,请参阅我的答案。 –
@NickAlbrecht谢谢,更正 –