C# 在ASP.NET核心MVC中同时验证两个属性
我有以下的视图模型C# 在ASP.NET核心MVC中同时验证两个属性,c#,asp.net-core,asp.net-core-mvc,viewmodel,latitude-longitude,C#,Asp.net Core,Asp.net Core Mvc,Viewmodel,Latitude Longitude,我有以下的视图模型 public class MyViewModel { [Required(ErrorMessage = "Location is required")] [Range(SOME_RANDOM_COORDINATE, SOME_RANDOM_COORDINATE, ErrorMessage = "Keep location within map bounds")] public double? Latitude {
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输入字段(都是隐藏的)。当提交表单时(而不是设置位置),我自然会得到两次“位置是必需的”。如何将这两个要验证的属性组合在一起
观点
@ViewData[“标题”]
您可以尝试使用自定义属性验证坐标对
在您的模型中,我将删除[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;
}
}
[AttributeUsage(AttributeTargets.Property |
AttributeTargets.Field,AllowMultiple=false)]
公共类CustomCoordinateAttribute:ValidationAttribute
{
私有只读字符串_requiredProperty;
公共CustomCoordinateAttribute(公共双精度?必需值)
{
_requiredProperty=requiredValue;
}
受保护的覆盖验证结果有效(对象值,
ValidationContext(验证上下文)
{
var currentValue=(双)值;
var属性=
validationContext.ObjectType.GetProperty(_requiredProperty);
if(属性==null)
抛出新ArgumentException(“未找到指定的属性名称”);
var otherValue=
(DateTime)属性.GetValue(validationContext.ObjectInstance);
if((currentValue==null)| |(otherValue==null))
{
返回新的ValidationResult(“未定义任何坐标”);
}
如果((currentValue==null)&&(otherValue!=null))
{
返回新的ValidationResult(String.Format(
ErrorMessageString,currentValue));
}
如果((currentValue!=null)&&(otherValue==null))
{
返回新的ValidationResult(String.Format(
ErrorMessageString,其他值);
}
如果((当前值<0)| |(其他值<0))
{
返回新的ValidationResult(“坐标不能为负”);
}
返回ValidationResult.Success;
}
}
您可以在提交表单之前使用ajax进行验证,下面是一个演示:
行动:
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; }
}
视图:
@ViewData[“标题”]
提交
@节脚本{
@{wait Html.RenderPartialAsync(“_validationScript”);}
$(“表格”)。提交(功能(e){
$.ajax({
键入:“获取”,
url:“验证?纬度=”+$(“#纬度”).val()+”&经度=”+$(“#经度”).val(),
成功:功能(数据){
如果(数据!=“有效”){
$(“#错误”).html(数据);
}否则{
$('form').unbind().submit();
}
}
})
返回false;
})
}
结果:
我是否也应该删除range属性并将其添加到custom属性中?我认为range属性也会限制类的默认值,因此最好将其移动到自定义验证中。
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>
}