Deploying a WCF Data Service to a server that has WebDAV installed

Here’s a simple one, that was fairly annoying:

I deployed a WCF Data Service to a site today, and while I was testing all of the operations I found that both the PUT and DELETE verbs weren’t working. At first, a 405 Method Not Allowed was being returned. I placed the service within an Umbraco site so I just figured that was where the conflict was.

After some digging around on the internet, I came across across ASP.NET MVC got 405 error on HTTP DELETE request?, from Stack Overflow, which it stated that the issue was related to WebDAV. The solution was to remove the WebDAVModule. That got rid of the 405, but unfortunately didn’t resolve the issue.

The requests started returning a 200 status code, which was good, but the page that was coming back was a 500 error. Because I wasn’t testing the service on the actual machine, I wasn’t seeing the actual error. So I logged on to the server and the tests showed the following error:

HTTP Error 500.21 – Internal Server Error
Handler “WebDAV” has a bad module “WebDAVModule” in its module list

(Gotta’ love more detailed errors.) From there I found How can I get OData DELETE to work?, also from Stack Overflow, which gave a good explanation of what was happening and how to solve it. Apparently, WebDAV blocks the DELETE and PUT requests (thanks a lot WebDAV…) and so the solution is to remove WebDAV or disable it on your site. You can completely disable WebDAV as follows:

<system.webServer>
    <modules>
        <remove name="WebDAVModule" />
    </modules>
    <handlers>
        <remove name="WebDAV" />
    </handlers>
</system.webServer>

Thank you to Stack Overflow and all those that contribute to it!

Advertisements

Cross Domain Requests with WCF Data Services and datajs

I have been developing a project that uses WCF Data Services 5.0 and datajs 1.1.0. Everything was working fine until I decided to move the client and service into separate projects. Once they were in separate projects, when I would launch them, they would, as expected, run on different localhost ports and therefore be running on different domains.

It was at this point the client stopped working. I noticed via fiddler that instead of making a GET request to the OData service, the browser based client was instead using the OPTIONS verb and the service was responding with a “501 – Not Implemented”.

I figured that this had something to do with the browser cross-domain policy, but wasn’t quite sure what to do. It was amazing to me that there didn’t appear to be a built-in/simple way to resolve this seemingly common issue. After a bit of googling, I found an MSDN blog post entitled, Getting JSON Out of WCF Data Services, by Glenn Gailey, that mentions a couple ways to get a service to format its response in JSONP (JSON with Padding).

I figured that the option involving the WCF Data Services Toolkit would be the easiest and attempted that first. The toolkit is available via nuget, so it was easy to install. But I ran into problems surrounding assembly conflicts. After struggling a while with that, I gave up and attempted the other option, JSONP and URL-controlled format support for ADO.NET Data Services.

After working with this next solution, I discovered that it didn’t work for WCF Data Services 5.0. I wish I would have taken the time the read the comments on the project’s page, because I had to learn the hard way why it didn’t work. The solution allows you to add the JSONPSupportBehavior attribute to your service class, which then attaches an inspector to the service to check for the $format and $callback query string parameters and then modifies the HTTP headers accordingly. For versions less than 5.0, the accepts header can be “application/json, text/plain;q=0.5” but I eventually learned that version 5.0 requires the header to be “application/json;odata=verbose”. I updated the JSONPSupportBehaviour.cs file accordingly.

WCF Data Service:

[JSONPSupportBehavior]
public class SampleService : DataService<SampleEntities>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        // ...
    }
}

JSONPSupportBehaviour.cs:

// replace the Accept header so that the Data Services runtime
// assumes the client asked for a JSON representation
httpmsg.Headers["Accept"] = "application/json;odata=verbose";
httpmsg.Headers["Accept-Charset"] = "utf-8";

Once I got all that figured out, I realized that datajs wasn’t including the $callback and $format parameters in the query string. Eventually I came across a post from the datajs project forum which gave some clarification on this whole issue and stated that the enableJsonpCallback needed to be set to true on the OData.read request. After making this final change, my client and service were able to communicated together just fine.

OData.read({
    requestUri: url,
    enableJsonpCallback: true
},
function (data, response) {
    // success
},
function (error) {
    // failure
});

Using CSS Classes for Image Alignment in TinyMCE

I had a problem with aligning images in the TinyMCE editor in Umbraco 4.7.1.1. There are two ways a user can align images: a) Using the paragraph alignment button, and b) Using styles defined for the editor. We wouldn’t need option b) at all except that, when you have margins automatically applied to the images, things can get messy. Even then, annoyingly enough, option b) doesn’t always work, depending on what tag the image is nested in. So I searched for a better solution. I wanted the user to be able to still use the alignment tool, but I wanted the tool to apply class instead of using the style attribute to the float the image.

Eventually, I found a blog post, Patching TinyMCE For Better Left/Right Aligned Images, by Gareth Senior, that included a simple solution to my problem. Gareth included code for a simple patch that made all my TinyMCE dreams come true. I’ll include the same code here, only I’ll also document how I implemented the changes in Umbraco.

The simple change is made to the tiny_mce_src.js. Normally, you make the changes to tiny_mce_src.js, then minify the file and use the minified version. The Umbraco installation includes a minified version of the file, but apparently it’s not used. I made the following changes to umbraco_client/tinymce3/tiny_mce_src.js, and it fixed things for me really nicely:

3469    case 'float':
3470+      tinymce.DOM.removeClass(n, 'align-left');
3471+      tinymce.DOM.removeClass(n, 'align-right');
3472+      if (v != "") tinymce.DOM.addClass(n, "align-" + v);
3473       isIE ? s.styleFloat = v : s.cssFloat = v;
3474       break;

This will add the class “align-left” or “align-right” to the image when the alignment options are used from the tool bar. You can then use those to create styles that will compensate for the margins.

NOTE: Be sure to clear the browser cache, or the browser will hold on to the old version and it will seem like it did nothing. Oh and remember that you’ll have to make this change again when you upgrade Umbraco as the upgrade will replace the edits.

Edit: 5/16/2012 – This also works in Umbraco 4.7.2.