[英]How do I create a custom validation message on a model passed into a controller c# web api
如何在傳遞給ac#Web API的控制器操作方法的模型上創建自定義驗證消息?
這是模型:
[DataContract]
public class TestDto //: IValidatableObject
{
[DataMember]
[LongValidation("Its not a long!")]
public long? ID { get; set; }
[DataMember]
public string Description { get; set; }
public string DescriptionHidden { get; set; }
}
這是我的控制器類:
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public string Post([FromBody]TestDto testDto)
{
//todo: should a post return any data?
if (ModelState.IsValid)
return "success!";
else
{
var ret = string.Empty;
foreach (var modelState in ModelState)
{
ModelErrorCollection errorCollection = modelState.Value.Errors;
var errors = string.Empty;
foreach (var error in errorCollection)
{
errors = errors + "exception message: " + error.Exception.Message + ", errorMessage: " + error.ErrorMessage;
}
ret = ret + "Error: " + modelState.Key + ", " + modelState.Value.Value + ", errors: " + errors;
}
return ret;
}
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
如果我將此對象發布到Post操作中:
{
"ID" : "1aaa","Description": "sample string 2",
}
在我的LongValidation的有效方法中,我獲得了long的默認值not:“ 1aaa”,因此無法在驗證器中執行正確的驗證。
這是Long Validator的代碼:
public class LongValidationAttribute : ValidationAttribute
{
public LongValidationAttribute(string errorMessage) : base(errorMessage)
{
}
public override string FormatErrorMessage(string name)
{
return base.FormatErrorMessage(name);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
long ret;
bool success = long.TryParse(value.ToString(), out ret);
//return base.IsValid(value, validationContext);
if (success == false)
return new ValidationResult(this.ErrorMessage);
else
{
return ValidationResult.Success;
}
}
}
1aaa
不是long
值,而是string
值。 因此,當您將數據提交到端點時,默認的模型綁定器將無法將此字符串值映射到您的long?
屬性。
如果您絕對希望將此字符串值映射到clas屬性並得到驗證,則需要將屬性更改為long?
string
類型。 但是,當然,現在,您需要在代碼的其他部分將其轉換為long!
如果您在正常使用情況下期望數值,我建議您僅使用適當的數值類型。 在您的代碼中,您可以檢查它是否為null
並根據需要使用它。
看到這個帖子: https : //blog.markvincze.com/how-to-validate-action-parameters-with-dataannotation-attributes/
基本上,您需要使用自定義過濾器屬性掛接到MVC管道中:
public class ValidateActionParametersAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var descriptor = context.ActionDescriptor as ControllerActionDescriptor;
if (descriptor != null)
{
var parameters = descriptor.MethodInfo.GetParameters();
foreach (var parameter in parameters)
{
var argument = context.ActionArguments[parameter.Name];
EvaluateValidationAttributes(parameter, argument, context.ModelState);
}
}
base.OnActionExecuting(context);
}
private void EvaluateValidationAttributes(ParameterInfo parameter, object argument, ModelStateDictionary modelState)
{
var validationAttributes = parameter.CustomAttributes;
foreach (var attributeData in validationAttributes)
{
var attributeInstance = CustomAttributeExtensions.GetCustomAttribute(parameter, attributeData.AttributeType);
var validationAttribute = attributeInstance as ValidationAttribute;
if (validationAttribute != null)
{
var isValid = validationAttribute.IsValid(argument);
if (!isValid)
{
modelState.AddModelError(parameter.Name, validationAttribute.FormatErrorMessage(parameter.Name));
}
}
}
}
}
基於Kevin的出色回答,我創建了以下類以在MVC4 / MVC5下達到預期的效果:
public sealed class ValidateActionParametersAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var descriptor = context.ActionDescriptor;
if (descriptor != null)
{
var modelState = context.Controller.ViewData.ModelState;
foreach (var parameterDescriptor in descriptor.GetParameters())
{
EvaluateValidationAttributes(
suppliedValue: context.ActionParameters[parameterDescriptor.ParameterName],
modelState: modelState,
parameterDescriptor: parameterDescriptor
);
}
}
base.OnActionExecuting(context);
}
static private void EvaluateValidationAttributes(ParameterDescriptor parameterDescriptor, object suppliedValue, ModelStateDictionary modelState)
{
var parameterName = parameterDescriptor.ParameterName;
parameterDescriptor
.GetCustomAttributes(inherit: true)
.OfType<ValidationAttribute>()
.Where(x => !x.IsValid(suppliedValue))
.ForEach(x => modelState.AddModelError(parameterName, x.FormatErrorMessage(parameterName)));
}
}
注意:上面使用的.ForEach方法是一個簡單的擴展方法,您可以自己編寫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.