Validating model properties WCF Web APi

Topics: Web Api
Nov 23, 2011 at 8:14 AM
Edited Nov 23, 2011 at 8:49 AM

As we do in ASP.NET MVC applications, what is the way of validating model properties according to incoming data on WCF Web API?

I found a similar question on stackoverflow but not sure if it is the right way of doing it. 

http://stackoverflow.com/questions/7974205/validating-model-properties-wcf-web-api

Also, the framework is now at preview stage and pretty dynamic which means it opens to any changes. I would like to know what are the plans for validation?

Can you provide an example for that? thanks!

EDIT

According to answer on SO, I created below operation handler:

 

public class ValidationOperationHandler : HttpOperationHandler {

        private readonly HttpOperationDescription _httpOperationDescription;
        private readonly Uri _baseAddress;

        public ValidationOperationHandler(HttpOperationDescription httpOperationDescription, Uri baseAddress) {

            _httpOperationDescription = httpOperationDescription;
            _baseAddress = baseAddress;
        }

        protected override IEnumerable<HttpParameter> OnGetInputParameters() {

            return new[] { HttpParameter.RequestMessage };
        }

        protected override IEnumerable<HttpParameter> OnGetOutputParameters() {

            var types = _httpOperationDescription.InputParameters.Select(x => x.ParameterType);
            return types.Select(type => new HttpParameter(type.Name, type));
        }

        protected override object[] OnHandle(object[] input) {

            var request = (HttpRequestMessage)input[0];
            var uriTemplate = _httpOperationDescription.GetUriTemplate();

            var uriTemplateMatch = uriTemplate.Match(_baseAddress, request.RequestUri);

            var validationResults = new List<ValidationResult>();

            //Bind the values from uriTemplateMatch.BoundVariables to a model

            //Do the validation with Validator.TryValidateObject and add the results to validationResults

            //Throw a exception with BadRequest http status code and add the validationResults to the message

            //Return an object array with instances of the types returned from the OnGetOutputParmeters with the bounded values

            throw new NotImplementedException();
        }

    }

and the registration is like below:

var httpConfiguration = new HttpConfiguration
            {
                RequestHandlers = (collection, endpoint, operation) => collection.Add(new ValidationOperationHandler(operation, endpoint.Address.Uri))
            };
What would be the complete code for that?

 

Coordinator
Nov 23, 2011 at 4:32 PM

We don’t currently have any direct support for MVC style model binding and validation, but it is definitely something that we are looking at. If this is something that is important to you, then could you please add this feature request in Issue Tracker so that the community can vote on it?

Thanks.

Nov 23, 2011 at 5:31 PM
Edited Nov 23, 2011 at 5:31 PM

@danroth27

thanks! Just done that:

http://wcf.codeplex.com/workitem/119

The way I follow is not a healthy way of doing it right? Also, can you guys reveal if ASP.NET MVC and WCF Web API will be merged or not (it is pretty obvious that they will). 

Can you guys also announce the road-map so that we can shape our apps according to that.

Coordinator
Nov 23, 2011 at 9:16 PM

We've discussed validation many times in the past. Operation handlers definitely are the recommended way to do it. When we designed handlers, validation was one of the core scenarios we had in mind.

If the validation fails, then what you want to do is throw an HttpResponseException / HttpResponseException<T> and include validation information in the response.

Coordinator
Nov 23, 2011 at 9:21 PM

Forgot to mention, HttpResponseException carries underneath it an HttpResponseMessage so you can tweak headers or modify the content.

Coordinator
Nov 23, 2011 at 9:25 PM

To throw the exception you'd do something like

var response = new HttpResponseMessage<List<ValidationResult>>(list);
throw new HttpResponseException(response);

Nov 24, 2011 at 7:22 AM

thanks Glenn.

the place where I struggle is the comments as you see on my code sample:

 

       protected override object[] OnHandle(object[] input) {

            var request = (HttpRequestMessage)input[0];
            var uriTemplate = _httpOperationDescription.GetUriTemplate();

            var uriTemplateMatch = uriTemplate.Match(_baseAddress, request.RequestUri);

            var validationResults = new List<ValidationResult>();

            //Bind the values from uriTemplateMatch.BoundVariables to a model

            //Do the validation with Validator.TryValidateObject and add the results to validationResults

            //Throw a exception with BadRequest http status code and add the validationResults to the message

            //Return an object array with instances of the types returned from the OnGetOutputParmeters with the bounded values

            throw new NotImplementedException();
        }

 

do you have any sample how to take those actions there? 

On my models, I have validation annotations like Required, StringLength, etc. on my models so Validator.TryValidateObject should work for me but I have these issues:

  • How to reach out to model inside OnHandle method you see above?
  • If there is no validation error, what should I return?

I would really appreciate if you put a sample for me because I have tried several combinations and they all break somewhere.

Thanks!

Nov 24, 2011 at 11:26 AM

1) Redefine the OnGetInputParameters method to return the HttpParameter describing the model. Use the HttpOperationDescription to obtain this HttpParameter.

2) The model value will be passed on input[0].

3) If validation succeeds, return an empty object[] (redefine OnGetOutputParameters to return an empty IEnumerable<HttpParameter>

HTH

Pedro

 

OnGetInputParameters