如何在ASP.NET Core MVC中显示特定的ModelState错误?

时间:2019-06-05 13:42:26

标签: c# asp.net-core model-view-controller asp.net-core-mvc asp.net-core-2.2

在我的一个控制器动作中,我要做的第一件事是将模型传递给新动作,该动作实际上只是解析输入以确定用户是否输入了有效日期。然后返回模型并检查ModelState.IsValid。

public Import ValidateUploadModel(Import Model)
    {
        // DO not allow future dates
        if (Model.CurrMoInfo.CurrMo > DateTime.Now)
        {
            ModelState.AddModelError("FutureDate", "You cannot assign a future date.");
        }
        //Do not allow dates from the same month (we run the processing a month behind)
        if (Model.CurrMoInfo.CurrMo.Month == DateTime.Now.Month)
        {
            ModelState.AddModelError("SameMonth", "You must process a previous month.");
        }

        //Ensure day is last day of a previous month
        if (Model.CurrMoInfo.CurrMo.Day != DateTime.DaysInMonth(Model.CurrMoInfo.CurrMo.Year, Model.CurrMoInfo.CurrMo.Month))
        {
            ModelState.AddModelError("LastDay", "You must enter the last day of the month.");
        }

        //Do not allow dates older than 12 months back
        if (Model.CurrMoInfo.CurrMo < DateTime.Now.AddMonths(-12))
        {
            ModelState.AddModelError("TooOld", "Date must not be older than a year.");
        }

        return Model;
    }

在我知道我有模型状态错误的时候,我可以通过以下内容在剃刀视图中正确显示它们

<span class="text-danger">@Html.ValidationSummary(false)</span>

因此,由于我所有的模型状态错误都与页面上的相同输入有关,因此我可以放心地这样做。 但是,如果我有需要相互独立显示的各种错误输入怎么办?我将如何去做呢?另外,除了使用@ Html.ValidationSummary之外,还有其他更好(或更合适)的方法吗?

我已经搜索了Microsoft文档和数十个StackOverflow问题,以尝试将较旧的答案转换为.Net Core做事的方式。

为清楚起见进行编辑:

这是剃刀视图中的整个卡片:

<div class="card-body">

                @if (Model.StagingCount == 0)
                {
                    <input asp-for="@Model.CurrMoInfo.CurrMo" type="date" required class="col-lg-12" />
                }
                else
                {
                    <input asp-for="@Model.CurrMoInfo.CurrMo" type="date" disabled="disabled" required class="col-lg-12" />
                }

                <span class="text-danger">@Html.ValidationSummary(false)</span>

            </div>

该输入用于模型属性,但未添加注释。我编写了自己的规则,如果不遵守规则,则将错误手动添加到模型状态。我拥有的代码有效,但是当我开始需要验证更多字段时,它无法扩展。我只想知道这样做的更好方法。

1 个答案:

答案 0 :(得分:1)

在上面的示例中,您并没有真正遵循标准惯例。

对于像这样的简单验证(您只验证一个字段中的值),用于将错误消息放置在ModelState中的键应该与模型中受影响字段的名称相同。对于您而言,实际上您的所有错误都应使用CurrMoInfo.CurrMo键记录。仅错误消息本身需要有所不同。据我所知,对每个特定的不同错误使用自定义键不会为您的应用程序增加任何价值。您没有按预期方式使用它。

如果将它们全部记录在CurrMoInfo.CurrMo上,则可以使用asp-validation-for标签帮助程序来创建一个字段,该字段显示专门针对该字段的错误,例如

<span asp-validation-for="CurrMoInfo.CurrMo" class="text-danger"></span>

然后,您可以(可选)使用ValidationSummary(如标题所示)汇总整个模型的所有错误-并显示您可能创建的与单个特定字段无关的任何其他模型错误。

完整示例:

public Import ValidateUploadModel(Import Model)
{
    // DO not allow future dates
    if (Model.CurrMoInfo.CurrMo > DateTime.Now)
    {
        ModelState.AddModelError("CurrMoInfo.CurrMo", "You cannot assign a future date.");
    }
    //Do not allow dates from the same month (we run the processing a month behind)
    if (Model.CurrMoInfo.CurrMo.Month == DateTime.Now.Month)
    {
        ModelState.AddModelError("CurrMoInfo.CurrMo", "You must process a previous month.");
    }

    //Ensure day is last day of a previous month
    if (Model.CurrMoInfo.CurrMo.Day != DateTime.DaysInMonth(Model.CurrMoInfo.CurrMo.Year, Model.CurrMoInfo.CurrMo.Month))
    {
        ModelState.AddModelError("CurrMoInfo.CurrMo", "You must enter the last day of the month.");
    }

    //Do not allow dates older than 12 months back
    if (Model.CurrMoInfo.CurrMo < DateTime.Now.AddMonths(-12))
    {
        ModelState.AddModelError("CurrMoInfo.CurrMo", "Date must not be older than a year.");
    }

    return Model;
}


<div class="card-body">
    @if (Model.StagingCount == 0)
    {
        <input asp-for="CurrMoInfo.CurrMo" type="date" required class="col-lg-12" />
    }
    else
    {
        <input asp-for="CurrMoInfo.CurrMo" type="date" disabled="disabled" required class="col-lg-12" />
    }
    <span asp-validation-for="CurrMoInfo.CurrMo" class="text-danger"></span>
</div>

进一步阅读:https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/validation?view=aspnetcore-2.2

P.S。我不认为这个一般原则已经从.NET Framework更改为.NET Core。