3

I have a WCF 4 RESTful web service which must work using on GET (its JSONP). I added a method to this service which requires a complex type parameter.

[OperationContract]
[WebGet(RequestFormat=WebMessageFormat.Json)]
void InsertEventActionList(string pageViewGUID, 
                             List<EventActionItem> eventActionItemList);

I was then getting the error:

Operation 'InsertEventActionList' in contract 'ITrackingService' 
has a query variable named 'eventActionItemList' of type 
'System.Collections.Generic.List`1[EventActionItem]', but type 
'System.Collections.Generic.List`1[EventActionItem]' is not convertible by 
'QueryStringConverter'.  Variables for UriTemplate query values 
must have types that can be converted by 'QueryStringConverter'.

Okay, so using this article - http://blogs.msdn.com/b/carlosfigueira/archive/2011/08/09/wcf-extensibility-querystringconverter.aspx I created a custom QueryStringConverter attached to a behavior extension:

[DataContract]
public class EventActionItem
{
    [DataMember]
    public string ActionName { get; set; }

    [DataMember]
    public string ActionValue { get; set; }

    [DataMember]
    public string ActionCategory { get; set; }
}

public class EventActionItemQueryStringConverter : QueryStringConverter
{
    public override bool CanConvert(Type type)
    {
        return type == typeof(List<EventActionItem>) || base.CanConvert(type);
    }

    public override object ConvertStringToValue(string parameter, Type parameterType)
    {
        if (parameterType == typeof(List<EventActionItem>))
        {
            List<EventActionItem> item = JsonConvert.DeserializeObject<List<EventActionItem>>(parameter);

            if (item != default(List<EventActionItem>))
            {
                return item;
            }
        }

        return base.ConvertStringToValue(parameter, parameterType);
    }
}

public class TrackingWebHttpBehavior : WebHttpBehavior
{
    protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
    {
        return new EventActionItemQueryStringConverter();
    }
}

public class TrackingBehaviorExtension : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(TrackingWebHttpBehavior); }
    }

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

web.config:

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="queryString"
             type="namespace.TrackingBehaviorExtension, namespace"/>
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior>
          <queryString />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>

However, I am still getting the same error. I have debugged the service initialization and the BehaviorExtensionElement is getting created, but the QueryStringConverter is never called.

Is it because I am using the standardEndpoint configuration instead of a customer user defined endpoint? If so how can I attach the custom behavior to the standardEndpoint?

EkoostikMartin
  • 6,831
  • 2
  • 33
  • 62

1 Answers1

0

EDIT

Depending on what you are developing, you might be able to use https://github.com/oyvindkinsey/easyXDM.
It allows POST in x-domain (using XHR).


Isn't too much for a query string? I think if it was only one object that needs to be passed, OK for a query string, but a list...? Maybe I am wrong.. but I think you should pass only "one" EventActionItem for each request.

If you can afford the changes, just make the list (or array) a body parameter and then use POST instead of GET, or like I suggested above, one request for each item in EventActionItem array.

  • This isn't really an answer, and I said in the first line of my question that it must be GET because this is x-domain JSONP. – EkoostikMartin Jul 11 '13 at 16:10
  • @EkoostikMartin: i said "If you can afford the changes...", and after two days, I still think you should not try to serialize a System.Collections.Generic.List`1[T] for a query string. It's not the EventActionItem in my opinion, it's the List. – Mohamed Amine SEBBANE Jul 14 '13 at 08:03