Method Not Allowed Error (HTTP 405) When Calling WCF Method From AjaxControlToolKit AutoCompleteExtender

This is a follow-up to my question regarding an "EndPoint Not Found" exception that I posted here and is identical to the problem that this guy posted here. The only difference is that he was at least able to get the AutoCompleteExtender to communicate with the WCF service when they were both in the same project. I can't even get that far.

It is also worth noting that my ultimate goal is to deploy the solution to a SharePoint 2010 site which is why I'm restricted to an older version of the AjaxControlToolKit and .NET framework 3.5.

However, as of now I can't even get the code to work when I create a brand new website that is completely independent of SharePoint along with the WCF service hosted in the same site so I can avoid any Same Origin Policy issues that might prevent any of this from working.

I can successfully call the WCF service method from my browser and it returns the XML results I'm expecting, while Fiddler shows me that the browser is correctly performing a GET operation. The aggravation starts when the AutoCompleteExtender calls the same WCF method. I get a "405 Method Not Allowed" error and for some reason the AutoCompleteExtender tries to perform a POST operation which was clearly visible not only in Fiddler but also in the debugger because the breakpoint that gets hit in the generated JavaScript code shows that the verb parameter's value is set to POST and not GET.

I honestly don't care whether or not the AutoCompleteExtender performs a GET or a POST just as long as the freaking thing works. I checked the Request Filtering section in the IIS Manager to make sure POST wasn't in the "deny" list under the Verb section and also checked the web.config to make sure it wasn't blocked there either.

I was able to get a jQuery autocomplete solution working using the exact same WCF method but for the purposes of this project I cannot use jQuery. This must be a pure C# .NET solution.

I have already exhausted all the regular suggestions, including:

  1. I have set the httpGetEnabled attribute to "true" in the web.config.
  2. Web method names in the implementation class are decorated with WebMethod and ScriptMethod attributes.
  3. I have decorated the WCF service implementation class with the AspNetCompatibilityRequirements (RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed) and ScriptService attributes.

All of the required HttpHandlers in the web.config are present and appear to be correct.

I'm all out of ideas. The only thing I can think of is that since I'm performing all of this work on a server that has SharePoint 2010 installed that maybe the SharePoint installation made some wonky configuration changes to IIS that is secretly screwing everything up. I haven't had a chance to try this on a pure machine that doesn't have SharePoint 2010 installed but that is likely going to be my next step.

Just to reiterate, although I ultimately want to get this working in a UserControl deployed as a SharePoint solution, at this point I can't even get the autocomplete working in a standalone web application that is completely independent of SharePoint, running on the same physical server as SharePoint but as a separate website using a totally different Application Pool.

I also read an article here about using Ajax AutoComplete with WCF instead of ASMX and the guy swears he can get it to work. Now while I don't have much faith in people who provide solutions to problems that involve leaving out things like interfaces because they don't know how they work I don't think the dude would take the time to post something technical like this, claiming that it's possible when it really isn't. And since he was kind enough to try and share whatever knowledge he gained from his experience it would be pretty ungrateful (and kind of jerky) for me to knock him for not knowing something at this point.

UPDATE #1: OK! Finally some progress! As sort of a last resort I decided to try and get this working without using the WCF service by just sticking the method in my ASPX page's CodeBehind. Now I know that this won't be possible for my real solution because this won't work on UserControls which are my only option when it comes to SharePoint. But still, after all this time I was just so desperate that I needed to see something work. Anything. So I added the method to the CodeBehind in my ASPX page and voila! It still didn't work! Yeah, you heard that right.

The only difference was that the error said:

"Unknown web method GetItemsList. Parameter name: methodName"

Crazy, I know.

So I start digging around the web a little more and that's when I stumbled upon this fun little discussion on how to get AutoComplete to work without using a web service. Now keep in mind that I had already read like 1000 of these types of posts before but something about this one was different. In this post the code was using static methods. I figured what the hell. I made the methods in the CodeBehind file for my ASPX page static and...

B I N G O!

Yes! That did it. I had finally gotten AutoComplete to work. The only problem was that I couldn't make my WCF service methods static. So now what?

Back to the drawing board

So there I was. After finally tasting success for just a few brief seconds my hopes were quickly dashed once I realized that this wasn't really going to help me at all. Well, at least I got AutoComplete to work in some capacity right?

Yeah, this wasn't going to cut it. There had to be something else I was missing.

TO THE INTERNET!

After readings few more posts on the web I stumbled across one that seemed interesting. As I scroll through the various pieces of code something catches my attention. It seems that the author's methods are configured to return JSON and the WebInvoke's Method property is set to POST instead of GET.

Hmmm... very nice I think to myself.

WAIT! WHAT?????????

Use POST and return JSON??? Are you freaking kidding me???

Well, I guess it's worth a shot. In hindsight it kind of makes sense that if all the requests that were coming from the AutoCompleteExtender were POSTs then perhaps it would have been a little more (OK, much more) intelligent of me to try and make my WCF service method match the AutoCompleteExtender than the other way around. It still wouldn't have worked because I was trying to return XML from my service instead of JSON but at least I would have been a little more on target than I had been up until now.

I figured if the AutoCompleteExtender was using POST no matter what I tried to do, then I mine as well use the WebInvoke attribute on my service interface and set the Method property to POST too. I also decided to removed the uriTemplate property since it wasn't really doing anything anyway.

Survey says...

Exception!

Okay. Fiddler shows me that I got a ServiceActivationException. So now I'm off to the Windows Application logs in the Event Viewer to see what all the hubbub was about. Well, as it turns out my method had specified that multiple request body parameters be serialized without any wrapper elements which is apparently a big no-no. My mistake was that I had set the BodyStyle to WebMessageBodyStyle.Bare instead of WebMessageBodyStyle.Wrapped.

OK. No biggie. The important thing was that I finally managed to get this far.

So let's try this one more time shall we?

And nothing. I launch my web browser, type stuff into the textbox, wait a few seconds and get bupkis (click on the link or ask your Jewish friend if you don't know what that means).

I decide to check Fiddler just for the hell of it and am surprised by what I see (and it's not bupkis -that I can assure you). It's JSON data. Good old fashioned JSON data.

I couldn't believe it! I finally got data back from a WCF service. I mean the AutoComplete still didn't work when I tried using the service instead of the method from the CodeBehind even though Fiddler showed both approaches returning the exact same JSON data but hey it's a start.

In addition, even if I do eventually get this all to work in it's current state it's still just a WCF service that is local to the project. Meaning, I haven't yet had any success trying this out when the WCF service is in a totally separate project let alone getting it to play nice with SharePoint (or to be more accurate, getting SharePoint to play nicely with it). Right now I am just taking baby steps.

I'll be updating this post as soon as I have more to report. Please don't hesitate to ask me any questions and surely don't hesitate to post any suggestions.

UPDATE #2: So now I have the AutoCompleteExtender actually using my WCF service and returning valid JSON data but the AutoComplete is not actually happening. I cheated a little by upgrading my IIS site to the .NET 4.0 framework so I could make use of some of the new features. I figured that if I can get at least some of this working as a standalone IIS servie then at least I'd be little better off than where I am now.

I updated my web.config with the following for my endpointBehavior:

<behavior name="webBehavior"> <webHttp helpEnabled="true" automaticFormatSelectionEnabled="false" /> </behavior>

Notice the automaticFormatSelectionEnabled="false" attribute. Why false? Because, when set to "true" for some reason (bug?) the HTTP response header that gets sent back to the client inserts text/html instead of application/xml or application/json and as a result the data isn't displayed correctly in the browser.

I also tried creating three different methods, one that returns Xml, the other JSON and a third that takes an additional parameter that is used to determine the format to return (Xml/JSON) and programatically changes the outgoing message response accordingly. More information about manipulating the response headers can be found here.

if (string.Equals("json", format, StringComparison.OrdinalIgnoreCase))
{
if (WebOperationContext.Current != null)
    WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;
}

Is this an ideal solution? No. But it does the trick. Now if I could only get the actual AutoComplete to work. :(

So how did I ultimately resolve these issues?

In short, I figured out that the AutoCompleteExtender is in fact performing a POST operation and not a GET. In fact, when dealing with JSON data you should always assume POST. My WCF methods were using WebGet instead of WebInvoke.