This isn’t the first time I’ve hit this particular wall: I’m creating a WCF REST service for AJAX callbacks and using the WebScriptServiceHostFactory host factory in the service:

<%@ ServiceHost Language="C#" 
        Service="WcfAjax.BasicWcfService"                 
        CodeBehind="BasicWcfService.cs"        
        Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %>

 

to avoid all configuration. Because of the Factory that creates the ASP.NET Ajax compatible format via the custom factory implementation I can then remove all of the configuration settings that typically get dumped into the web.config file. However, I do want ASP.NET compatibility so I still leave in:

<system.serviceModel>        
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>

in the web.config file. This option allows you access to the HttpContext.Current object to effectively give you access to most of the standard ASP.NET request and response features. This is not recommended as a primary practice but it can be useful in some scenarios and in backwards compatibility scenerios with ASP.NET AJAX Web Services.

Now, here’s where things get funky. Assuming you have the setting in web.config, If you now declare a service like this:

    [ServiceContract(Namespace = "DevConnections")]
#if DEBUG 
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
#endif
    public class BasicWcfService

(or by using an interface that defines the service contract)

you’ll find that the service will not work when an AJAX call is made against it. You’ll get a 500 error and a System.ServiceModel.ServiceActivationException System error. Worse even with the IncludeExceptionDetailInFaults enabled you get absolutely no indication from WCF what the problem is.

So what’s the problem?  The issue is that once you specify aspNetCompatibilityEnabled=”true” in the configuration you *have to* specify the AspNetCompatibilityRequirements attribute and one of the modes that enables or at least allows for it. You need either Required or Allow:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

without it the service will simply fail without further warning.

It will also fail if you set the attribute value to NotAllowed. The following also causes the service to fail as above:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.NotAllowed)]

This is not totally unreasonable but it’s a difficult issue to debug especially since the configuration setting is global – if you have more than one service and one requires traditional ASP.NET access and one doesn’t then both must have the attribute specified. This is one reason why you’d want to avoid using this functionality unless absolutely necessary. WCF REST provides some basic access to some of the HTTP features after all, although what’s there is severely limited.

I also wish that ServiceActivation errors would provide more error information. Getting an Activation error without further info on what actually is wrong is pretty worthless especially when it is a technicality like a mismatched configuration/attribute setting like this.