Use parameter "params string[]" in WCF Rest endpoint
Asked Answered
R

3

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);
}
Refreshment answered 19/7, 2016 at 8:8 Comment(0)
L
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);
Labiche answered 19/7, 2016 at 8:30 Comment(0)
P
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.

Perpendicular answered 19/7, 2016 at 8:15 Comment(0)
I
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);
}
Inapposite answered 19/7, 2016 at 8:39 Comment(2)
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.Labiche
You make an excellent point - I've edited my answer accordingly. Thanks for pointing this out.Inapposite

© 2022 - 2024 — McMap. All rights reserved.