9

I know that you can use Validation attributes on a model to validate it like so:

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

}

But is it possible to validate a single string using validation attributes such as this?

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

}

This didn't seem to work. The only ways I've been able to do this was to either create a wrapper object and use [FromUri], use a custom ActionFilterAttribute on the action itself or to manually validate the parameter in the controller action using a regular expression.

1
  • 2
    Web API Route Constraints also useful for validation like [Route("XYZ/{id:int:maxlength(10)}")] Commented Feb 26, 2015 at 7:28

2 Answers 2

6

If you're using Attribute Routing to manage your paths coming into your controllers, you can always do something like this:

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

}

There are various route contraints, as documented on the Attribute Routing overview documentation.

It does raise the question as to why you're accepting a numeric string of length 10 as your id. you'll have to be careful when parsing it into an int that it doesn't exceed 2,147,483,647, as that's the maximum size for a default integer.

Sign up to request clarification or add additional context in comments.

Comments

5

The other two solutions will only work for route attributes. However if you are wanting to validate a query parameter you could do something like this:

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
}

This is for an integer, but you could easily modify it to work with string regex. Now it can be applied to your query parameter as such:

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.
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.