Using the WCF webHttp binding, is it possible to pass arbitrary query string arguments?

Scenario:

  • I want to call RESTish
  • I want to use WCF webHttpBinding to call a service
  • The service accepts GET requests, such as:

    GET /endpoint/{resourcename}/?arg1=a&arg2=b&...

  • Query string arguments may vary depending on the name of the resource. I do not want to create several methods in the interface with specific settings UriTemplate.

  • As an added bonus, query string arguments can be specified multiple times, i.e. GET /SomeResource/?a=1&a=2&a=3is a valid request.
  • What I would like is something like a contract below, can WCF do this webHttpBinding?

Example:

[WebGet(UriTemplate="/{resourcename}/???")]
[OperationContract]
Whatever DoTheThing(string resourcename, Dictionary<string, string> queryStringArgs)
+4
source share
2 answers

, queryStringArgs , , :

public string GetData(string value)
{
    var utm = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
    var queryStringArgs = new Dictionary<string, string>();
    foreach(var query in utm.QueryParameters.AllKeys)
    {
        queryStringArgs.Add(query, utm.QueryParameters[query]);
    }

    return string.Format("You entered: {0} {1}", value, queryStringArgs);
}

:

[OperationContract]
[WebGet(UriTemplate = "/GetData/{value}")]
string GetData(string value);

WebOperationContext, UrlTemplateMatch, IncomingRequest.

QueryParameters (NameValueCollection), -, .

+3

QueryStringConverter, , . , .

1. QueryStringConverter, :

public class CustomQueryStringConverter : System.ServiceModel.Dispatcher.QueryStringConverter
{
    public override bool CanConvert(Type type)
    {
        if (type == typeof(Dictionary<string, string>))
            return true;
        // ELSE:
        return base.CanConvert(type);
    }

    public override object ConvertStringToValue(string parameter, Type parameterType)
    {
        if (parameterType != typeof(Dictionary<string, string>))
            return base.ConvertStringToValue(parameter, parameterType);
        // ELSE (the type is Dictionary<string, string>)
        if (parameter == null)
            return new Dictionary<string, string>();

        return JsonConvert.DeserializeObject<Dictionary<string, string>>(parameter);
    }
}

2. -, , WebHttpBehavior GetQueryStringConverter, , :

public sealed class CustomWebHttpBehavior : WebHttpBehavior
{
    public CustomWebHttpBehavior()
    {
        // you can set default values for these properties here if you need to:
        DefaultOutgoingResponseFormat = WebMessageFormat.Json;
        AutomaticFormatSelectionEnabled = true;
        DefaultBodyStyle = WebMessageBodyStyle.Bare;
        HelpEnabled = true;
    }

    protected override System.ServiceModel.Dispatcher.QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
    {
        return new CustomQueryStringConverter();
    }
}

3. - BehaviorExtensionElement, wcf, :

public class CustomWebHttpBehaviorElement : BehaviorExtensionElement
{

    public override System.Type BehaviorType
    {
        get { return typeof(CustomWebHttpBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new CustomWebHttpBehavior();
    }
}

4. web.config wcf, :

<system.serviceModel>
    ...

    <extensions>
        <behaviorExtensions>
            <add name="customWebHttpBehaviorElement" type="Your.Namespace.CustomWebHttpBehaviorElement, Your.Assembly" />
        </behaviorExtensions>
    </extensions>
    ...

    <behaviors>
        <endpointBehaviors>
            <behavior name="RestServiceEndpointBehavior">
                <customWebHttpBehaviorElement />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    ...

</system.serviceModel>

( ) , RestServiceEndpointBehavior , .

:. , json : /SomeResource/?args={"a":1,"b"=2,"c"=3}, , 1 (args), (a, b, c).

2: :

    public string DoTheThing(Dictionary<string, string> args)
    {
        var resourceName = "";
        if(args.ContainsKey("resourceName"))
            resourceName = args["resourceName"];
        return string.Format("You entered: {0}", args);     
    }

:

    [WebInvoke(Method = "GET")]
    [OperationContract]
    string DoTheThing(Dictionary<string, string> args);

, "args" , .

, UriTemplate, , json, , , .

, .

+1

All Articles