我尝试使用数据注解来为我的模型中的一个不能为空的List添加验证。我尝试了几种自定义属性的实现,包括here和here。
我的看法:
<div class="form-group">
@* Model has a list of ints, LocationIDs *@
@Html.LabelFor(model => model.LocationIDs, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<select class="select2 form-control" multiple id="LocationIDs" name="LocationIDs">
@* Adds every possible option to select box *@
@foreach (LocationModel loc in db.Locations)
{
<option value="@loc.ID">@loc.Name</option>
}
</select>
@Html.ValidationMessageFor(model => model.LocationIDs, "", new { @class = "text-danger" })
</div>
</div>
型号:
public class ClientModel
{
public int ID { get; set; }
[Required] // Does nothing
public List<int> LocationIDs { get; set; }
}
控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,LocationIDs")] ClientModel clientModel)
{
if (ModelState.IsValid)
{
db.Clients.Add(clientModel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(clientModel);
}
我尝试过的一个(功能相同的)属性:
[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
var list = value as IEnumerable;
return list != null && list.GetEnumerator().MoveNext();
}
}
目前,检查null或空列表会通过验证,即使没有选择任何内容。在这种情况下,绑定了一个长度为1的列表,其中包含第一个选项。
我已经确认控制器实际上发送了长度为1的List
。我不知道如何改变这种行为。我仍然认为这可能是在下面的块报价中所描述的。
我***认为***我的问题可能在this answer's edit中描述,但我不确定如何解决它。
摘录如下:
您还必须注意如何在视图中绑定列表。例如,如果您将List绑定到这样的视图:
<input name="ListName[0]" type="text" />
<input name="ListName[1]" type="text" />
<input name="ListName[2]" type="text" />
<input name="ListName[3]" type="text" />
<input name="ListName[4]" type="text" />
MVC模型绑定器总是在你的列表中放5个元素,都是String。空。如果这是View的工作方式,则属性需要变得更复杂一点,例如使用Reflection来提取泛型类型参数并将每个列表元素与default(T)或其他内容进行比较。
4条答案
按热度按时间yvgpqqbh1#
你可以尝试用一个类型构造验证器,并验证列表中是否有任何itens与你的类型的默认值不同。改变你在这里提到的例子:
mbzjlibv2#
你的
CannotBeEmptyAttribute
很好。我使用了完全相同的代码,它工作得很好。请确保您更改视图模型以使用它(而不是Required
,它在本例中不做您想要的事情。除非您实现自定义属性,否则它不会为您提供客户端验证。这意味着即使表单是无效的,它也会被发布,但
if (ModelState.IsValid)
会捕获它。你有没有使用调试器来查看IsValid
是否是false
?“手动”创建输入对于服务器端验证来说是完全可以的,但是客户端将无法工作,因为缺少必要的
data-
属性。下面是一个最小版本的表单,带有手动创建的多选输入,可与
CannotBeEmptyAttribute
一起使用:ax6ht2ek3#
另外,分配一个
MinLength
对我来说也很有效:4urapxun4#
我可以得到一个零选择来实际绑定为
null
的唯一方法是使用Html.ListBoxFor
(我最初无法弄清楚-它应该从一开始就这样做):我还没有让客户端验证工作,但我会把它作为另一个问题发布。