Using query string parameters to disambiguate a UriTemplate match

I am using WCF 4.0 to create a REST-ful web service. What I would like to do is have different service methods called based on query string parameters in the UriTemplate.

For example, I have an API that allows users to retrieve information about a person using either by their driver's license or their social security number as a key. In my ServiceContract / interface I would define two methods:

[OperationContract]
[WebGet(UriTemplate = "people?driversLicense={driversLicense}")]
string GetPersonByLicense(string driversLicense);

[OperationContract]
[WebGet(UriTemplate = "people?ssn={ssn}")]
string GetPersonBySSN(string ssn);

However, when I call my service with both methods I get the following exception:

UriTemplateTable does not support multiple templates that have equivalent path as template 'people?ssn={ssn}' but have different query strings, where the query strings cannot all be disambiguated via literal values. See the documentation for UriTemplateTable for more detail.

Is there not some way to do this with UriTemplates? It seems like a common scenario.

Thanks very much!

Answers


According to This post, it is not possible, you would have to do something like:

[OperationContract]
[WebGet(UriTemplate = "people/driversLicense/{driversLicense}")]
string GetPersonByLicense(string driversLicense);

[OperationContract]
[WebGet(UriTemplate = "people/ssn/{ssn}")]
string GetPersonBySSN(string ssn);

Alternatively, if you want to keep the query string format, adding a static query string parameter to the beginning of the UriTemplate would work. For example:

[OperationContract]
[WebGet(UriTemplate = "people?searchBy=driversLicense&driversLicense={driversLicense}")]
string GetPersonByLicense(string driversLicense);

[OperationContract]
[WebGet(UriTemplate = "people?searchBy=ssn&ssn={ssn}")]
string GetPersonBySSN(string ssn);

I also ran into this problem and eventually came up with a different solution. I didn't want to have a different method for each property of an object.

What I did was as follows:

Define the URL Template in the service contract not specifying any query string parameters:

[WebGet(UriTemplate = "/People?")]
[OperationContract]
List<Person> GetPersonByParams();

Then in the implementation access any valid query string parameters:

public List<Person> GetPersonByParms()
    {
        PersonParams options= null;

        if (WebOperationContext.Current != null)
        {
            options= new PersonParams();

            options.ssn= WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters["ssn"];
            options.driversLicense = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters["driversLicense"];
            options.YearOfBirth = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters["YearOfBirth"];
        }

        return _repository.GetPersonByProperties(options);
    }

You can then search by using URL's such as

/PersonService.svc/People 
/PersonService.svc/People?ssn=5552
/PersonService.svc/People?ssn=5552&driversLicense=123456

It also enables you to mix and match query string parameters so just use what you want and omit any other params you're not interested in. It has the advantage of not restricting you to just one query parameter.


Need Your Help

Why do .net languages vary in performance?

c# .net performance programming-languages

I have heard that C++ .NET is fastest , C# is next, followed by VB .NET and Languages like Iron-Python and Boo come last in terms of performance. If all .NET languages compile to intermediate byte-...

jQuery get .text() but not the text in span

javascript jquery menu textnode

Hi guys this is my jQuery part that makes my menu for my pages.