.net core 中嵌套模型的自定义验证Custom Validation for nested model in .net core

Custom Validation for nested model in .net core

提问人:Safi Mustafa 提问时间:9/13/2021 最后编辑:Safi Mustafa 更新时间:7/8/2022 访问量:1218

问:

我正在尝试使用自定义验证来验证嵌套模型。但问题是函数从未在嵌套模型上调用。但是,它适用于简单的类属性AttributeAdapterBase.AddValidation

自定义必需的验证属性:

    public interface IId
    {
        long Id { get; set; }
    }

    public class Select2RequiredAttribute : RequiredAttribute
    {
        public Select2RequiredAttribute(string errorMessage = "") : base()
        {
            ErrorMessage = errorMessage;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            Type t = value.GetType();

            if (typeof(IId).IsAssignableFrom(t))
            {
                if ((value as IId).Id == 0)
                {
                    return new ValidationResult(ErrorMessage);
                }
            }
            else
            {
                return new ValidationResult(ErrorMessage);
            }

            return ValidationResult.Success;
        }
}

属性适配器底座:

public class Select2RequiredAttributeAdapter : AttributeAdapterBase<Select2RequiredAttribute>
{
    public Select2RequiredAttributeAdapter(Select2RequiredAttribute attribute, IStringLocalizer stringLocalizer) : base(attribute, stringLocalizer)
    {
    }

    public override void AddValidation(ClientModelValidationContext context)
    {
        MergeAttribute(context.Attributes, "data-val", "true");
        MergeAttribute(context.Attributes, "data-val-select2-required", GetErrorMessage(context));
    }

    public override string GetErrorMessage(ModelValidationContextBase validationContext)
    {
        return Attribute.ErrorMessage ?? GetErrorMessage(validationContext.ModelMetadata, validationContext.ModelMetadata.GetDisplayName());
    }
}

适配器提供程序:

public class Select2RequiredAdapterProvider : IValidationAttributeAdapterProvider
{
    private readonly IValidationAttributeAdapterProvider _baseProvider = new ValidationAttributeAdapterProvider();

    public IAttributeAdapter GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
    {
        if (attribute is Select2RequiredAttribute)
        {
            return new Select2RequiredAttributeAdapter(attribute as Select2RequiredAttribute, stringLocalizer);
        }
        else
        {
            return _baseProvider.GetAttributeAdapter(attribute, stringLocalizer);
        }
    }
}

Startup.cs:

services.AddSingleton<IValidationAttributeAdapterProvider, Select2RequiredAdapterProvider>();

模型类:

public interface IBaseBriefViewModel : IId
{
    string Name { get; set; }
}

public class BaseBriefViewModel : IBaseBriefViewModel
{
    public virtual long Id { get; set; }
    public string Name { get; set; }
}

public class UserViewModel 
{
    public long Id { get; set; }
    public string Name { get; set; }
    [Select2Required("Branch is required.")]
    public BaseBriefViewModel Branch { get; set; }
}

分支选择 2 部分视图:

@model DataLibrary.ViewModels.BriefViewModels.BaseBriefViewModel
@{
    var elementId = ViewData["ElementId"] != null && !string.IsNullOrEmpty(ViewData["ElementId"].ToString()) ? ViewData["ElementId"].ToString() : "branch-id";
}

<div class="form-group">
    <label>Branch: <span class="text-danger"></span></label>
    <div class="row">
        <div class="@select2Class">
            @Html.DropDownListFor(model => model.Id, new List<SelectListItem>() {
           new SelectListItem()
           {
               Value = (Model!=null&&Model.Id>0)?Model.Id.ToString():"",
               Text = (Model!=null&&Model.Id>0)?Model.Name:"",
               Selected = (Model!=null&&Model.Id>0)?true:false,
           }}, new { @id = elementId, @class = "form-control disable-field"})
            @Html.ValidationMessageFor(model => model.Id, "", new { @class = "text-danger" })
        </div>
    </div>
</div>

<script>
    $(function () {
        var id = "#" + "@elementId";
        var url = '/Branch/GetBranchsForSelect2';
        var dataArray = function (params) {
            params.page = params.page || 1;
            return {
                prefix: params.term,
                pageSize: pageSize,
                pageNumber: params.page,
            };
        };
        Select2AutoCompleteAjax(id, url, dataArray, pageSize, "---Branch---");
    });
</script>

所有这些代码都适用于服务器端。但为了更好的用户体验,我想在提交表单之前显示错误。我怎样才能做到这一点?我想将其用于项目中的许多 Select2。因此,对静态错误消息进行硬编码不是一个好主意。我真正想做的是从父对象传递错误消息。在这种特定情况下,Like Branch 是必需的。也许在其他一些课程中,我可能会通过产品是必需的BaseBriefViewModel

任何方向都将不胜感激

asp.net-mvc . net-core 数据注释 unobtrusive-validation unobtrusive-javascript

评论


答:

1赞 aleksander_si 7/8/2022 #1

目前不支持此功能 - 但支持正在计划中。请参阅 dotnet github issue:

https://github.com/dotnet/runtime/issues/36093