我们有几个通过JsonProperty覆盖名称的模型,但是当我们通过ModelState获得验证错误时,这会引起问题。例如:
class MyModel
{
[JsonProperty("id")]
[Required]
public string MyModelId {get;set;}
}
class MyModelController
{
public IHttpActionResult Post([FromBody] MyModel model)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
/* etc... */
}
}上述邮政将返回错误的The MyModelId field is required.,这是不准确的。我们希望这个词是The id field is required.。我们尝试使用[DataMember(Name="id")],但得到了相同的结果。
问题1:除了在每个必需属性上提供我们自己的错误消息之外,是否有一种方法可以让ModelState错误显示JSON属性名称而不是C#属性名称?
-更新
我一直在玩这个,并找到了一个“自己动手”的方法,用于使用自定义属性名称重新创建错误消息。我真的希望有一个内置的方法来做这件事,但这似乎是工作.
https://gist.github.com/Blackbaud-JasonTremper/b64dc6ddb460afa1698daa6d075857e4
问题2:是否可以假定ModelState.Key与<parameterName>.<reflectedProperty>语法匹配,或者在某些情况下可能不符合?
问题3:是否有一种更简单的方法来确定JSON的参数名称,而不是通过对[DataMember]或[JsonProperty]属性的反射进行搜索?
发布于 2016-11-16 21:06:04
你试过使用DisplayName属性吗?
displayname attribute vs display attribute
此外,还可以将错误消息分配给[Required]属性。
[Required(ErrorMessage = "Name is required")]
发布于 2017-04-07 07:18:11
我也面临这个问题,我修改了一些代码从您的链接,以适应我的WebAPI。modelState还将存储旧键,它是模型的变量名,加上Json属性名。
ValidateModelStateFilter[ValidateModelStateFilter]过滤器源代码:
public class ValidateModelStateFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var descriptor = actionContext.ActionDescriptor;
var modelState = actionContext.ModelState;
if (descriptor != null)
{
var parameters = descriptor.GetParameters();
var subParameterIssues = modelState.Keys
.Where(s => s.Contains("."))
.Where(s => modelState[s].Errors.Any())
.GroupBy(s => s.Substring(0, s.IndexOf('.')))
.ToDictionary(g => g.Key, g => g.ToArray());
foreach (var parameter in parameters)
{
var argument = actionContext.ActionArguments[parameter.ParameterName];
if (subParameterIssues.ContainsKey(parameter.ParameterName))
{
var subProperties = subParameterIssues[parameter.ParameterName];
foreach (var subProperty in subProperties)
{
var propName = subProperty.Substring(subProperty.IndexOf('.') + 1);
var property = parameter.ParameterType.GetProperty(propName);
var validationAttributes = property.GetCustomAttributes(typeof(ValidationAttribute), true);
var value = property.GetValue(argument);
modelState[subProperty].Errors.Clear();
foreach (var validationAttribute in validationAttributes)
{
var attr = (ValidationAttribute)validationAttribute;
if (!attr.IsValid(value))
{
var parameterName = GetParameterName(property);
// modelState.AddModelError(subProperty, attr.FormatErrorMessage(parameterName));
modelState.AddModelError(parameterName, attr.FormatErrorMessage(parameterName));
}
}
}
}
}
}
}
private string GetParameterName(PropertyInfo property)
{
var dataMemberAttribute = property.GetCustomAttributes<DataMemberAttribute>().FirstOrDefault();
if (dataMemberAttribute?.Name != null)
{
return dataMemberAttribute.Name;
}
var jsonProperty = property.GetCustomAttributes<JsonPropertyAttribute>().FirstOrDefault();
if (jsonProperty?.PropertyName != null)
{
return jsonProperty.PropertyName;
}
return property.Name;
}
}发布于 2019-11-11 12:49:44
您可以访问参数类型,获取json名称,然后用json名称替换属性名。就像这样:
var invalidParameters = (from m in actionContext.ModelState
where m.Value.Errors.Count > 0
select new InvalidParameter
{
ParameterName = m.Key,
ConstraintViolations = (from msg in m.Value.Errors select msg.ErrorMessage).ToArray()
}).AsEnumerable().ToArray();
if (actionContext.ActionDescriptor.Parameters.Count == 1)
{
var nameMapper = new Dictionary<string, string>();
foreach (var property in actionContext.ActionDescriptor.Parameters[0].ParameterType.GetProperties())
{
object[] attributes = property.GetCustomAttributes(typeof(JsonPropertyNameAttribute), false);
if (attributes.Length != 1) continue;
nameMapper.Add(property.Name, ((JsonPropertyNameAttribute) attributes[0]).Name);
}
var modifiedInvalidParameters = new List<InvalidParameter>();
foreach (var invalidParameter in invalidParameters)
{
if(invalidParameter.ParameterName != null && nameMapper.TryGetValue(invalidParameter.ParameterName, out var mappedName))
{
var modifiedConstraintViolations = new List<string>();
foreach (var constraintViolation in invalidParameter.ConstraintViolations ?? Enumerable.Empty<string>())
{
modifiedConstraintViolations.Add(constraintViolation.Replace(invalidParameter.ParameterName, mappedName));
}
modifiedInvalidParameters.Add(new InvalidParameter
{
ParameterName = mappedName,
ConstraintViolations = modifiedConstraintViolations.ToArray()
});
}
else
{
modifiedInvalidParameters.Add(invalidParameter);
}
}
invalidParameters = modifiedInvalidParameters.ToArray();
}public struct InvalidParameter
{
[JsonPropertyName("parameter_name")]
public string? ParameterName { get; set; }
[JsonPropertyName("constraint_violations")]
public string[]? ConstraintViolations { get; set; }
}https://stackoverflow.com/questions/40640386
复制相似问题