在ModelState.Errors中使用[JsonProperty(“name”))
我们有几个通过JsonProperty覆盖名称的模型,但是当我们通过ModelState获取验证错误时,这会导致问题。例如:在ModelState.Errors中使用[JsonProperty(“name”))
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]
属性搜索?
您是否尝试过使用DisplayName
属性?
displayname attribute vs display attribute
此外,您还可以指定一个错误消息[Required]
属性。
[Required(ErrorMessage = "Name is required")]
我也面临这个问题,我修改了一些代码,从你的链接,以适合我的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;
}
}
有没有AspNetCore的这个版本?谢谢 –
我也尝试[显示名称],并没有奏效。然而根据你的链接,[Display]属性完成了这项工作(也许这就是你的意思?)。谢谢! – jt000