2

I would like to define an OperationContract, which I can pass any number of string parameters. The values should be interpreted as an array of string. Is there any possibility to use this type of parameter in an OperationContract and define this in the UriTemplate?

[ServiceContract]
public interface IRestService {
    [OperationContract]
    [WebGet(UriTemplate = "operations/{values}")]
    void Operations(params string[] values);
}
rbr94
  • 2,227
  • 3
  • 23
  • 39

3 Answers3

2

You should not do this on a GET operation. GET operations support parameters on the path or the query string only, neither of which are suitable for complex types such as collections.

A collection should be passed as a body parameter using a POST operation.

[OperationContract]
[WebInvoke(Method = "POST", 
           RequestFormat = WebMessageFormat.Json, // or xml
           UriTemplate = "operations/xAllTheStrings")]
void Operations(string[] values);
tom redfern
  • 30,562
  • 14
  • 91
  • 126
1

No, but you can make an (extension) method to your proxy and/or service contract for convenience, that would expose a params string array parameter, and pass it to the real proxy/service contract as a string array.

LoekD
  • 11,402
  • 17
  • 27
1

Your Service Contract interface is just that - a formal contract between what the server will accept and what the client needs to adhere to. This contract is serialised in to XML in the form of the wsdl - so any data types which appear in your contract must be expressible in their serialised form in XML.

In your case, the number of the arguments to your service call is not well-defined: it could have 0, 1, 2... etc. One of the tenants of service orientation is that the contracts need to be explicit - which this is not.

The most "idiomatic" approach (within a service orientated context) is the following:

[ServiceContract]
public interface IRestService {
    [OperationContract]
    [WebGet(UriTemplate = "operations/{values}")]
    void Operations(string[] values);
}

As suggested in this answer, if you want to add some syntactic sugar on the client side you could create an extension method which does use the params keyword to make the client-side experience easier to digest.

EDIT:

As pointed out by Tom, the above contract will not work. You would need to either change the operation to a POST (as demonstrated on Tom's answer), or make the argument string of a delimited that you unravel on the server side to produce the array:

[ServiceContract]
public interface IRestService {
    [OperationContract]
    [WebGet(UriTemplate = "operations/{delimitedValues}")]
    void Operations(string delimitedValues);
}
Community
  • 1
  • 1
Lawrence
  • 3,287
  • 19
  • 32
  • Would this operation even work? How would the query string get mapped into the template? The rest of your answer is great BTW, but I'm just not sure about the code sample provided. – tom redfern Jul 27 '16 at 07:42
  • You make an excellent point - I've edited my answer accordingly. Thanks for pointing this out. – Lawrence Jul 27 '16 at 08:53