使用查询字符串参数消除UriTemplate匹配的歧义

时间:2012-01-04 00:30:07

标签: c# wcf uritemplate

我正在使用WCF 4.0创建REST-ful Web服务。我想要做的是根据UriTemplate中的查询字符串参数调用不同的服务方法。

例如,我有一个API,允许用户使用其驾驶执照或社会安全号码作为密钥来检索有关某人的信息。在我的ServiceContract /接口中,我将定义两种方法:

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

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

但是,当我用两种方法调用我的服务时,我得到以下异常:

  

UriTemplateTable不支持多个模板   等效路径为模板'people?ssn = {ssn}'但有不同之处   查询字符串,其中查询字符串不能全部消除歧义   字面值。有关更多信息,请参阅UriTemplateTable的文档   细节。

使用UriTemplates是不是有办法做到这一点?这似乎是一种常见的情况。

非常感谢!

3 个答案:

答案 0 :(得分:11)

或者,如果要保留查询字符串格式,则可以在UriTemplate的开头添加静态查询字符串参数。例如:

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

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

答案 1 :(得分:10)

我也遇到了这个问题,最终想出了一个不同的解决方案。我不想为对象的每个属性使用不同的方法。

我所做的如下:

在服务合约中定义URL模板,而不指定任何查询字符串参数:

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

然后在实现中访问任何有效的查询字符串参数:

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

然后,您可以使用

等网址进行搜索
/PersonService.svc/People 
/PersonService.svc/People?ssn=5552
/PersonService.svc/People?ssn=5552&driversLicense=123456

它还使您能够混合和匹配查询字符串参数,以便使用您想要的内容并省略您不感兴趣的任何其他参数。它的优点是不会将您限制为只有一个查询参数。

答案 2 :(得分:8)

根据This post,这是不可能的,你必须做类似的事情:

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

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