2017-01-27 1 views
1

Wie erstelle ich eine benutzerdefinierte Validierungsnachricht für ein Modell, das an eine Controller-Aktionsmethode einer C# -Web-API übergeben wird? HierWie erstelle ich eine benutzerdefinierte Validierungsnachricht für ein an einen Controller übergebenes Modell C# web api

ist das Modell:

[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; } 
} 

Hier ist meine Controller-Klasse:

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) 
    { 
    } 
} 

Wenn ich dieses Objekt in den Beitrag Aktion schreiben:

{ 
"ID" : "1aaa","Description": "sample string 2", 
} 

In meinem LongValidation gültigen Methode, ich bekomme den Standardwert für eine lange nicht: "1aaa", so kann ich die korrekte Validierung in der Valida nicht durchführen Tor. Hier

ist der Code für die Lang 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; 
     } 
    } 
} 

Antwort

1

1aaa ist kein long Wert, sondern ein string Wert. Wenn Sie also die Daten an den Endpunkt übergeben, kann der Standardmodell-Binder diesen Zeichenfolgenwert nicht Ihrer long?-Eigenschaft zuordnen.

Wenn Sie unbedingt möchten, dass dieser Zeichenfolgenwert Ihrer clas-Eigenschaft zugeordnet und validiert wird, müssen Sie Ihre Eigenschaft von in string ändern. Aber natürlich müssen Sie es in andere Teile Ihres Codes konvertieren!

Ich schlage vor, einfach den entsprechenden numerischen Typ zu verwenden, wenn Sie im Normalfall einen numerischen Wert erwarten. In Ihrem Code können Sie überprüfen, ob es null oder nicht ist und verwenden Sie es bei Bedarf.

1

Sehen Sie diesen Beitrag: https://blog.markvincze.com/how-to-validate-action-parameters-with-dataannotation-attributes/

Grundsätzlich müssen Sie mit einem benutzerdefinierten Filterattribut in die MVC-Pipeline Haken:

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)); 
       } 
      } 
     } 
    } 
} 
+0

Danke für die Darstellung der richtigen Art und Weise, die Dinge im gegebenen Kontext zu tun. Das angegebene Code-Snippet funktioniert für den asp.net-Core. Ich habe den Code in meiner Antwort unten umgestaltet, um Leuten zu helfen, die gleiche Funktionalität in mvc4 + zu erreichen. Danke noch einmal. – xDisruptor

0

Basierend auf Kevins hervorragende Antwort, die ich die folgende Klasse erstellt haben, das gewünschte zu erreichen Wirkung unter 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))); 
    } 
} 

Hinweis: Die oben verwendete .ForEach Methode ist eine einfache Erweiterung Methode, die Sie wri können auf eigene Faust.

Verwandte Themen