Bug with GetQueryStringConverter not being called by WebServiceHost - by Sean Hederman

Status : 

  Deferred<br /><br />
		The product team has reviewed this issue and has deferred it for consideration at a later time.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.

Sign in
to vote
ID 616486 Comments
Status Closed Workarounds
Type Bug Repros 16
Opened 10/25/2010 9:17:58 AM
Access Restriction Public


The WebHttpBehavior.GetQueryStringConverter method is designed so that you can extend the behavior by supplying your own QueryStringConverter. However WebServiceHost completely ignores this behavior and news up QueryStringConverter on it's own, without involving the GetQueryStringConverter method.

It hus, completely bypasses this extensibility making it impossible to change the QueryStringConverter to be changed in any way incompatible with the base class.
Sign in to post a comment.
Posted by mclifton on 12/22/2011 at 3:59 PM
Figured out how to get this to work inside of an ASP.NET WCF web service. Check the workarounds for the solution.
Posted by mclifton on 12/21/2011 at 6:48 PM
Can anyone supply a workaround for a WCF webservice contained inside of an ASP.NET Web Application? I assume it would need to be done in the web.config, but I'm not sure how to accomplish that.
Posted by Microsoft on 6/20/2011 at 1:07 PM
This bug is under consideration to be fixed for the next version of the .NET Framework (the version after .NET 4.0). It will not be fixed for .NET 4.0 or early versions of the framework.

However, there is a general workaround that can be used. A working solution with the workaround is attached. At the top of the comments tab is a "Details" title that include an "Expand" link. In the expanded details is a list of file attachments. The workaround can be found in the QueryStringConverterBug.zip file attached by microsoft.

The workaround involves not using the WebServiceHost. Instead use the base ServiceHost class and explicitly add a WebHttp endpoint using the WebHttpBinding and an endpoint behavior that derives from WebHttpBehavior (you have to derive in order to supply a custom QueryStringConverter).
Posted by Microsoft on 6/20/2011 at 12:28 PM
Please see the attached solution for a general workaround to this issue.

The workaround involves not using the WebServiceHost. Instead use the base ServiceHost class and explicitly add a WebHttp endpoint using the WebHttpBinding and an endpoint behavior that derives from WebHttpBehavior (you have to derive inorder to supply a custom QueryStringConverter).

If you are hosting in IIS, you will need to author a custom ServiceHostFactory to do the same thing that is being done in the console application here.
Posted by Sean Hederman on 6/19/2011 at 12:08 AM
It appears that MS don't bother tracking defects that are marked as fixed. Hopefully this will be in .NET 5.0 when it's released probably sometime in the next couple years. Lesson Learned: never rely on MS to implement web technologies.
Posted by Jimmy Main on 5/26/2011 at 11:25 PM

What is happening with this bug.
The second workaround doesn't work, and after implementing a complete QueryStringConverter, and testing it for two days I realise that all the documentation I have been reading is rubbish, and my solution cannot work.

This has resulted in a serious waste of my time.

Please fix this.
Sorry, but this kind of bug is sloppy.

Posted by prenou on 5/24/2011 at 7:09 AM
I'm also blocked with this. Solution 1 given by Microsoft is okay but obviously not so pretty, Solution 2 did not work.

@Microsoft: It would really great to get the release date of this bug fix. Could you please at least give us this information so that I can know if it's worth to wait for this or not?

Thanks a lot.
Posted by mr-miles on 5/6/2011 at 4:59 AM
I tried the workaround, it didn't work.

Two things: first of all I think there's a bug - I only got past onOpening if I set WebHttpBinding.ContentTypeMapper = null beforehand.

Having done that, I then get a second exception:

[InvalidOperationException: Operation 'xxx' in contract 'Izzz' has a query variable named 'yyyy' of type 'System.Nullable`1[System.Boolean]', but type 'System.Nullable`1[System.Boolean]' is not convertible by 'QueryStringConverter'. Variables for UriTemplate query values must have types that can be converted by 'QueryStringConverter'.]
System.ServiceModel.Dispatcher.UriTemplateClientFormatter.Populate(Dictionary`2& pathMapping, Dictionary`2& queryMapping, Int32& totalNumUTVars, UriTemplate& uriTemplate, OperationDescription operationDescription, QueryStringConverter qsc, String contractName) +1530
System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter..ctor(OperationDescription operationDescription, IDispatchMessageFormatter inner, QueryStringConverter qsc, String contractName, Uri baseAddress) +128
System.ServiceModel.Description.WebHttpBehavior.GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) +184
System.ServiceModel.Description.WebHttpBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) +1677
System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +4114
System.ServiceModel.ServiceHostBase.InitializeRuntime() +82
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +64
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789
System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +287
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +1132

[ServiceActivationException: The service '/' cannot be activated due to an exception during compilation. The exception message is: Operation 'xxx' in contract 'Izzz' has a query variable named 'yyy' of type 'System.Nullable`1[System.Boolean]', but type 'System.Nullable`1[System.Boolean]' is not convertible by 'QueryStringConverter'. Variables for UriTemplate query values must have types that can be converted by 'QueryStringConverter'..]
System.Runtime.AsyncResult.End(IAsyncResult result) +890624
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +180062
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +136

I can't believe this still isn't fixed after eight months, and being told where the bug is. It's particularly rubbish as it bypasses the extensibility completely.

Worse still, it's marked as resolved when it clearly isn't.

Posted by KristianKristensen on 4/20/2011 at 9:41 AM
I tried the same; didn't work.
I'm hosting my REST services using Global.asax. The WebHttpBinding doesn't show up in base.Description.Endpoints until after base.OnOpening has been called. Sort of destroys the workaround.

Also there seems to be a bug in the workaround. Shouldn't the DummyContentTypeMapper be removed again AFTER calling base.OnOpening()?
Posted by Scottw512 on 3/2/2011 at 10:46 AM
Some additional info...I can see it execute the line

webHttpBinding.ContentTypeMapper = new DummyContentTypeMapper();

but it never hits the breakpoint I have set on the line

return WebContentFormat.Default;

in DummyContentTypeMapper.GetMessageFormatForContentType
Posted by Scottw512 on 3/2/2011 at 10:43 AM
I tried implementing the second workaround by copying and pasting the code in the post from Microsoft and I'm still having the problem. I set breakpoints in the OnOpening override and can step through the code. It finishes and still throws the error. Any ideas how to troubleshoot this?
Posted by bald75 on 3/1/2011 at 1:32 PM
also, you need the populate the "workarounds" tab, gahhh!
Posted by bald75 on 3/1/2011 at 1:32 PM
why didn't you guys just add support for nullable types to begin with, gahhhh!!!
Posted by Andres Paz1 on 2/1/2011 at 11:37 AM
I'm confused. This is marked as Resolved/Fixed. How do I know which version was this fixed on?
Posted by Sean Hederman on 1/24/2011 at 11:44 PM
Since we all know EXACTLY where the bug is, and EXACTLY what the fix is, can I ask why you are "considering it for a fix in the next release"?
Posted by Microsoft on 1/24/2011 at 4:15 PM
Hi Everyone,

First off, let me ensure everyone that the product team is aware of this bug and is considering it for a fix in the next release. I realize that the fact this connection issue is marked “paused” or “resolved” might suggest that nothing is being done, but that is not the case. Of course, waiting for the next release in which this bug may be fixed is not all that useful if one is blocked by it today. Therefore, with this post I hope to accomplish the following:

(1) Provide a straight forward work-around to the issue with the QueryStringConverter that is easy to understand ands solves some scenarios blocked by this bug.

(2) Explain the bug in more detail so that developers will understand when they will and won't hit the bug and also provide some context in regards to the next item...

(3) Provide a second work-around that is less straight forward but actually unblocks more scenarios,

So without further ado, Item (1) The Straight Forward Work-Around:

This thread was originally opened because the developer wanted to support Nullable<T> with the QueryStringConverter. The bug in question prevents this. Here is a workaround getting Nullable<T>-like support. This workaround isn't perfect (having the bug fixed would be preferable, no doubt) but it easy to implement and should unblock anybody that is trying to achieve this scenario.
First, use non-nullable types in the method signature of your service operation:

    [WebGet(UriTemplate = "/test?s={start}&e={end}")]
    public string Test(DateTime start, DateTime end)

Instead of:

        [WebGet(UriTemplate = "/test?s={start}&e={end}")]
    public string Test(DateTime? start, DateTime? end)

Second, create a helper method that will check the original request Uri to determine if the query name/value was actually present or not:

        Nullable<T> GetQueryValueOrNull<T>(string queryName, T queryValue)
        where T : struct
            if (string.IsNullOrWhiteSpace(
                return null;
            return queryValue;

Third, in each service operation implementation, call the helper method to get the new Nullable value:

    public string Test(DateTime start, DateTime end)
            DateTime? startOrNull = GetQueryValueOrNull<DateTime>("s", start);
            DateTime? endOrNull = GetQueryValueOrNull<DateTime>("e", end);
            return "Executed";

Now this workaround does introduce extra code in your service operation and binds the query parameter names from the UriTemplate to the imperative code within the service operation. However it will unblock you for the Nullable scenario and the help page for the service will still indicate the query string variables. We’ll look at a second workaround that unblocks more scenarios after we gain some context on the bug.

Moving on to item (2), Explaining the Bug in Detail:

As was pointed out earlier in this connect thread, the bug is in the IsRawContentMapperCompatibleDispatchOperation() method of the WebServiceHost. This is actually not the method that will create the QueryStringConverter that is used by the service during runtime. However, this method will attempt to validate the parameter types of the service operation by ensuring that they are supported by the QueryStringConverter. Unfortunately, a default QueryStringConverter is constructed for this validation; this is a bug, as the code should be creating the custom QueryStringConverter provided. Parameter types in the service operation that would be allowed with the custom QueryStringConverter appear to be invalid in this validation step and so an exception is thrown.

If you wrote a custom QueryStringConverter that did not attempt to convert new types not currently supported by the default QueryStringConverter, but instead simply altered how the default types were converted, you would not hit this exception. Of course, the main scenarios for custom QueryStringConverters is to support conversion of new types, so this fact isn’t all too useful.

But now that we know this exception is thrown from this validation step and is not occurring where the actual runtime QueryStringConverter will be created, this gives us hope for another workaround. If we could simply by-pass this validation step the exception would not be thrown and the correct custom QueryStringConverter would be created for use by the service during runtime. So how can we pass this validation step?

Item (3), A Second Work-Around to Unblock More Scenarios:

It turns out this validation step is only executed if a custom ContentTypeMapper is not set when the WebServiceHost is executing OnOpening. Therefore, if we can provide a dummy ContentTypeMapper prior to calling OnOpening of the WebServiceHost, this validation step will not occur and the service will start up without throwing the exception. After OnOpening has completed, we’ll need to remove our custom ContentTypeMapper so that we’ll see the correct default behavior.

The first step is to create a dummy ContentTypeMapper:

    class DummyContentTypeMapper : WebContentTypeMapper
        public override WebContentFormat
    GetMessageFormatForContentType(string contentType)
            return WebContentFormat.Default;

The second step is to override the OnOpening of WebServiceHost is a derived type so that we can set and remove this dummy ContentTypeMapper:

protected override void OnOpening()
    if (base.Description != null)
     foreach (var endpoint in base.Description.Endpoints)
        if (endpoint.Binding != null)
         // Add the derived WebHttpBehavior where the custom    
         // QueryStringConverter is set and then...

         WebHttpBinding webHttpBinding = endpoint.Binding as WebHttpBinding;
         if (webHttpBinding != null)
            webHttpBinding.ContentTypeMapper = new DummyContentTypeMapper();


    if (base.Description != null)
     foreach (var endpoint in base.Description.Endpoints)
        if (endpoint.Binding != null)
         WebHttpBinding webHttpBinding = endpoint.Binding as WebHttpBinding;
         if (webHttpBinding != null)
            webHttpBinding.ContentTypeMapper = new DummyContentTypeMapper();


Posted by yspring on 1/19/2011 at 4:24 AM
Microsoft get your thumbs out of your ass!

Why is this bug tagged as "paused"? This bug is breaking any documentation which mentions QueryStringConverter in any way.
Posted by JeffN825 on 1/17/2011 at 9:35 AM

When will this be fixed? This is a show stopper and a pretty blatant bug in your WebServiceHost code:

private static bool IsRawContentMapperCompatibleDispatchOperation(OperationDescription operation, ref int numStreamOperations)
    UriTemplateDispatchFormatter throwAway = new UriTemplateDispatchFormatter(operation, null,

new QueryStringConverter(),

operation.DeclaringContract.Name, new Uri("http://localhost"));
    int num = throwAway.pathMapping.Count + throwAway.queryMapping.Count;
    bool isRequestCompatible = false;

Posted by Andres Paz1 on 1/14/2011 at 10:52 AM
Is there a workaround for this?
How can we provide a Custom querystringconverter when using REST?
Posted by alekat on 12/16/2010 at 3:17 AM
Ah pity: the patch was for UriTemplateProcessor, so I think that this is still broken?
Posted by alekat on 12/15/2010 at 9:19 AM
woot! just recieved a really quick update and fix from Glen, going to try it now.

Posted by alekat on 12/15/2010 at 2:34 AM
I've been reviewing WCF (rest) and OpenRasta (have to choose between the two) with regards to some important projects I'm working on. So far I have pressure from Management to use a Microsoft technology, so how quickly this issue is resolved will determine which technology I will be recommending going forward. (Decision time is within the next 3 weeks. )

The fact that this issue has been marked as *resolved* is ringing alarm bells for me. I know that as a big company Microsoft has to decide where to allocate resources and uses voting so that critical issues will bubble to the surface and unfortunately that means that this issue will probably never get resolved as long as it's only got 7 vote points.

The purpose of a REST framework is to provide extension points where additional behaviour can be wired in as needed. The fact that this issue is "deffered" tells me this is not a high priority to Microsoft and is an indicator that if I'm looking for an extensible architecture, then this is probably not the right choice for me?

I'd love to be wrong here.

I'm just saying!

Posted by Daniel [MSFT] on 11/15/2010 at 4:10 PM
We think this is a bug.

Daniel Roth
Program Manager
Posted by DGDev on 11/14/2010 at 9:43 AM
This is a much needed fix. I'd like to give my REST services the ability to have querystring string parameters which support comma-delimited values.

Was this a bug or intended change?
Posted by Daniel [MSFT] on 11/5/2010 at 2:51 PM
Thank you for reporting this issue. We will consider fixing this issue in a future release.

Daniel Roth
Program Manager
Posted by Sean Hederman on 10/26/2010 at 4:45 AM
That would be because I used the "Steps to Reproduce" section to indicate exactly where in your code the bug was and how to fix it rather than exact steps. I have attached a sample project, as requested.
Posted by Microsoft on 10/26/2010 at 12:52 AM
Thank you for reporting this issue. In order to research the issue reported, we must first reproduce in our labs. Unfortunately, we are unable to reproduce the issue with the steps you provided.

Could you please provide us with a sample project zip?

It would be greatly appreciated if you could provide us this information as quickly as possible.

Thank you,
Posted by Microsoft on 10/25/2010 at 9:21 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)