【问题标题】:Validating two attributes at once in ASP.NET Core MVC在 ASP.NET Core MVC 中一次验证两个属性
【发布时间】:2021-05-27 00:18:10
【问题描述】:

我有以下 ViewModel;

public class MyViewModel {
    [Required(ErrorMessage = "Location is required")]
    [Range(SOME_RANDOM_COORDINATE, SOME_RANDOM_COORDINATE, ErrorMessage = "Keep location within map bounds")]
    public double? Latitude { get; set; }

    [Required(ErrorMessage = "Location is required")]
    [Range(SOME_RANDOM_COORDINATE, SOME_RANDOM_COORDINATE, ErrorMessage = "Keep location within map bounds")]
    public double? Longitude { get; set; }
}

我使用 OpenStreetMap 作为这些纬度和经度值的输入,并且我想使用 ViewModel 中的属性添加客户端和服务器端验证。我正在创建两个 html 输入字段(均隐藏)。提交表单(而不是设置位置)时,我自然会得到两次“需要位置”。如何将这两个属性组合在一起进行验证?

查看;

<form asp-area="" asp-controller="Report" asp-action="Create" method="post" enctype="multipart/form-data">
    <h4>@ViewData["Title"]</h4>
    <hr />
    <div class="form-group">
        <input id="latitude" type="hidden" asp-for="@Model.Latitude" class="form-control" />
        <span asp-validation-for="@Model.Latitude" class="text-danger"></span>
    </div>
    <div class="form-group">
        <input id="longitude" type="hidden" asp-for="@Model.Longitude" class="form-control" />
        <span asp-validation-for="@Model.Longitude" class="text-danger"></span>
    </div>
</form>

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc viewmodel latitude-longitude


    【解决方案1】:

    您可以尝试使用自定义属性来验证坐标对。

    在您的模型中,我将删除 [Required] 属性并将其替换为自定义验证属性。这些值可以在模型中设置为默认值,以便初始视图最初不会引发错误。然后,您的控制器可以在呈现视图后将坐标覆盖为您想要的任何内容。

    public class MyCoordinateModel {    
        [Range(SOME_RANDOM_COORDINATE, SOME_RANDOM_COORDINATE, ErrorMessage = "Keep location within map bounds")]
        [CustomCoordinate("Longitude", ErrorMessage = "{0} field has not been set.")]
        public double? Latitude { get; set; }
    
        [Range(SOME_RANDOM_COORDINATE, SOME_RANDOM_COORDINATE, ErrorMessage = "Keep location within map bounds")]
        [CustomCoordinate("Latitude", ErrorMessage = "{0} field has not been set.")]
        public double? Longitude { get; set; }
    
        MyCoordinateModel()
        {
            Longitude = 0;
            Latitude = 0;
        }
    }
    

    自定义属性将是这样的,错误消息有条件地显示为无效的属性:

    [AttributeUsage(AttributeTargets.Property | 
      AttributeTargets.Field, AllowMultiple = false)]
    public class CustomCoordinateAttribute : ValidationAttribute
    {
        private readonly string _requiredProperty;
    
        public CustomCoordinateAttribute(public double? requiredValue)
        {
             _requiredProperty = requiredValue;
        }
    
        protected override ValidationResult IsValid(object value, 
           ValidationContext validationContext)
        {
            var currentValue = (double)value;
    
            var property = 
                validationContext.ObjectType.GetProperty(_requiredProperty);
    
            if (property == null)
                throw new ArgumentException("Specified property name not found");
    
            var otherValue = 
                (DateTime)property.GetValue(validationContext.ObjectInstance);
    
            if ((currentValue == null) || (otherValue == null))
            {
                return new ValidationResult("None of the coordinates are defined");
            }
    
            if ((currentValue == null) && (otherValue != null))
            {
                return new ValidationResult(String.Format(
                    ErrorMessageString, currentValue));
            }
    
            if ((currentValue != null) && (otherValue == null))
            {
                return new ValidationResult(String.Format(
                    ErrorMessageString, otherValue);
            }
    
            if ((currentValue < 0) || (otherValue < 0))
            {
                return new ValidationResult("Coordinates cannot be negative");
            }
    
            return ValidationResult.Success;
        }
    }
    

    【讨论】:

    • 我是否也应该删除范围属性并将其添加到自定义属性中?
    • 我认为 range 属性也会限制类的默认值,因此将其移动到自定义验证中是个好主意。
    【解决方案2】:

    你可以在表单提交之前使用ajax进行验证,这里有一个demo:

    行动:

    public IActionResult Verify(double? Latitude,double? Longitude)
            {
                if (Latitude==null||Longitude==null)
                {
                    return Json("Location is required");
                }
    
                return Json(true);
            }
    

    MyViewModel:

    public class MyViewModel {
        [Range(SOME_RANDOM_COORDINATE, SOME_RANDOM_COORDINATE, ErrorMessage = "Keep location within map bounds")]
        public double? Latitude { get; set; }
    
        [Range(SOME_RANDOM_COORDINATE, SOME_RANDOM_COORDINATE, ErrorMessage = "Keep location within map bounds")]
        public double? Longitude { get; set; }
    }
    

    查看:

      <form asp-area="" asp-controller="Report" asp-action="Create" method="post" enctype="multipart/form-data">
        <h4>@ViewData["Title"]</h4>
        <hr />
        <div class="form-group">
            <input id="latitude" hidden asp-for="Latitude" class="form-control" value="1"/>
            <span asp-validation-for="Latitude" class="text-danger"></span>
        </div>
        <div class="form-group">
            <input id="longitude" hidden asp-for="Longitude" class="form-control"/>
            <span asp-validation-for="Longitude" class="text-danger"></span>
        </div>
        <div>
            <span class="text-danger field-validation-error" id="error"></span>
        </div>
        <button>submit</button>
    </form>
    @section Scripts {
        @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
    <script>
        
        $("form").submit(function (e) {
            $.ajax({
                type: "GET",
                url: 'Verify?Latitude=' + $("#latitude").val() + '&Longitude=' + $("#longitude").val(),
                success: function (data) {
                    if (data != "valid") {
                        $("#error").html(data);
                    } else {
                        $('form').unbind().submit();
                    }
                }
    
            })
            return false;
            
            
        })
       
    </script>
    }
    

    结果:

    【讨论】:

      猜你喜欢
      • 2020-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-09
      • 1970-01-01
      • 2020-11-15
      相关资源
      最近更新 更多