2015-02-26 11 views
5

wiem, że można użyć atrybutów Validation na modelu, aby potwierdzić to tak:Web API walidacji parametr pojedynczy łańcuch za pomocą walidacji

public class CommunicationQuery 
{ 
    [RegularExpression("[0-9]{0,10}", ErrorMessage = "Please enter a valid policy number")] 
    public string PolicyId { get; set; } 
    [RegularExpression("[0-9]{0,10}", ErrorMessage = "Please enter a valid member number")] 
    public string MemberId { get; set; } 
} 

public IEnumerable<Communication> Get([FromUri]CommunicationQuery documentQuery) 
{ 

} 

Ale czy to możliwe, aby potwierdzić jeden ciąg znaków za pomocą atrybutów walidacji takie jak to?

public async Task<HttpResponseMessage> Get([RegularExpression("[0-9]{0,10}")]string id) 
{ 

} 

To nie działa. Jedynym sposobem, w jaki mogłem to zrobić, było utworzenie obiektu opakowania i użycie [FromUri], użycie niestandardowego ActionFilterAttribute na samej akcji lub ręczne sprawdzenie poprawności parametru w akcji kontrolera za pomocą wyrażenia regularnego.

+2

API sieci wiązań tras również użyteczne do walidacji jak [Sposób ("XYZ/{id int: MaxLength (10)}")] – 111

Odpowiedz

3

Jeśli używasz Atrybut Routing zarządzać swoimi ścieżkami wejścia w kontrolerach, zawsze można zrobić coś takiego:

[Route("{Id:regex([0-9]{0,10})}")] 
public async Task<HttpResponseMessage> Get(string id) 
{ 

} 

Istnieją różne contraints trasy, co zostało udokumentowane na Attribute Routing overview documentation.

Podnosi to pytanie, dlaczego akceptujesz ciąg numeryczny o długości 10 jako identyfikator. musisz zachować ostrożność podczas analizowania go w int, aby nie przekroczyć wartości 2,147,483,647, ponieważ jest to maksymalny rozmiar domyślnej liczby całkowitej.

3

Pozostałe dwa rozwiązania działają tylko w przypadku atrybutów trasy. Jednak jeśli chce potwierdzić parametr kwerendy można zrobić coś takiego:

public class MinWithStatusAttribute : ParameterBindingAttribute 
{ 
    private readonly int _minValue; 
    public MinWithStatusAttribute(int minValue) 
    { 
     _minValue = minValue; 
    } 

    public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter) => new MinWithStatusParameterBinding(parameter, _minValue); 
} 

public class MinWithStatusParameterBinding : HttpParameterBinding, IValueProviderParameterBinding 
{ 
    private readonly int _minValue; 
    public HttpParameterBinding DefaultUriBinding; 

    public MinWithStatusParameterBinding(HttpParameterDescriptor desc, int minValue) 
     : base(desc) 
    { 
     _minValue = minValue; 
     var defaultUrl = new FromUriAttribute(); 
     this.DefaultUriBinding = defaultUrl.GetBinding(desc); 
     this.ValueProviderFactories = defaultUrl.GetValueProviderFactories(desc.Configuration); 
    } 


    public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) 
    { 
     return DefaultUriBinding.ExecuteBindingAsync(metadataProvider, actionContext, cancellationToken).ContinueWith((tsk) => 
     { 
      var currentBoundValue = this.GetValue(actionContext); 
      if (!(currentBoundValue is int)) return; //if it is not an Int, return. 
      var currentBoundInt = (int)currentBoundValue; 
      if (currentBoundInt >= _minValue) return; //If the value provided is greater than or equal to the min value, return. Else throw an error 
      var preconditionFailedResponse = actionContext.Request.CreateResponse(HttpStatusCode.PreconditionFailed, $"The parameter {DefaultUriBinding.Descriptor.ParameterName} must be greater than or equal to {_minValue}" }); 
      throw new HttpResponseException(preconditionFailedResponse); 
     }, cancellationToken); 
    } 

    public IEnumerable<ValueProviderFactory> ValueProviderFactories { get; } //IValueProviderParameterBinding 
} 

Jest to dla liczb całkowitych, ale można łatwo zmodyfikować go do pracy z ciąg regex. Teraz może być stosowany do parametru zapytania jako takie:

public IHttpActionResult SendEmailToCandidate(int id, [MinWithStatus(3)]int company_id, [MinWithStatus(3)]int recruiter_id, string subject, string body) 
    { 
     //Do stuff in your controller method. If they enter less than 3 it will display an error with Http status code 412 precondition failed. 
    }