ASP.NET Core +客户端验证:如果ViewBag和Model具有相同的属性名称,则不会生成data-val- *属性

时间:2019-03-12 10:35:39

标签: asp.net asp.net-core unobtrusive-validation viewbag client-side-validation

我在ASP.NET Core 2.2中认识到,如果ViewBag和Model具有相同的属性名称,则不会生成data-val- *属性(在我的情况下,它是关于属性“ Title”的)。由于缺少data-val- *属性,客户端验证无法正常工作。

这是我的模特:

public class ActivityModel
{
    public int Id { get; set; }

    [Required]
    public string Title { get; set; }
}

这是我的观点:

@model ActivityModel

@{ ViewBag.Title = "This is my title"; }  

@using (Html.BeginForm("Create", "Activities"))
{
    @Html.EditorFor(model => model.Title)

    <input type="submit" value="Create" class="btn btn-default" />
}

@section Scripts {
    @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}

_layout.cshtml中的ViewBag.Title属性用于显示当前标题名称。

如果我将ViewBag或Model属性名称更改为其他名称,则会生成data-val- *属性,并且客户端验证有效。

从技术角度来看,是什么导致了这种行为?

1 个答案:

答案 0 :(得分:0)

虽然我不知道发生这种情况的确切原因,但我可以建议您一些解决方法。显而易见的一种方法是在渲染输入后分配ViewBag

@using (Html.BeginForm("Create", "Activities"))
{
    @Html.EditorFor(model => model.Title)
    <input type="submit" value="Create" class="btn btn-default" />
} 

@{ ViewBag.Title = "This is my title"; }  

或者您可以使用input tag helper,因为它不会遇到此问题

 <input asp-for="Title" />
 <input type="submit" value="Create" class="btn btn-default" />

可能会很有趣

您可以通过在剃刀视图中将ViewContext.ClientValidationEnabled设置为false来禁用添加客户端验证属性(这很明显)

@{
    ViewContext.ClientValidationEnabled = false;
}

如果出于某种原因您需要为同一属性渲染多于1个input,并通过以下代码进行验证

@Html.EditorFor(model => model.Title)
@Html.EditorFor(model => model.Title)

将不对第二个input进行验证

<input class="text-box single-line" data-val="true" data-val-required="The Title field is required." id="Title" name="Title" type="text" value="Activity">
<input class="text-box single-line" id="Title" name="Title" type="text" value="Activity">

之所以会发生这种情况,是因为渲染器跟踪渲染的属性,并防止为同一属性多次添加验证。 ViewContext.FormContext跟踪属性,因此可以控制此行为。在添加验证属性之前,渲染器检查属性是否是通过调用ViewContext.FormContext.RenderedField(propertyName)渲染的,是否渲染了属性,则调用ViewContext.FormContext.RenderedField(propertyName, true)将特性标记为已渲染。但是您可以像这样用false调用此方法

@Html.EditorFor(model => model.Title)
@{
    ViewContext.FormContext.RenderedField("Title", false);
}
@Html.EditorFor(model => model.Title)

给出以下结果

<input class="text-box single-line" data-val="true" data-val-required="The Title field is required." id="Title" name="Title" type="text" value="Activity">
<input class="text-box single-line" data-val="true" data-val-required="The Title field is required." id="Title" name="Title" type="text" value="Activity">