1

I'm working on my first WCF service, which will support several Ajax calls. I have an endpoint configured this way:

  <service behaviorConfiguration="ServiceBehavior" name="AQM">
    <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="Binding1" contract="IAQM" />
  </service>

and my behavior configuration:

   <endpointBehaviors>
      <behavior name="web">
         <webHttp />
         <enableWebScript /> 
      </behavior>
   </endpointBehaviors>

I need to create my own error handling so that I can format some specific information back to the client (see here http://zamd.net/2008/07/08/error-handling-with-webhttpbinding-for-ajaxjson/). My WebServiceHostFactory looks like this:

public class MyServiceFactory : WebServiceHostFactory
{
    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
    {
        var sh = new ServiceHost(typeof(AQM), baseAddresses);
        sh.Description.Endpoints[0].Behaviors.Add(new WebHttpBehaviorEx());
        return sh;
    }
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return base.CreateServiceHost(serviceType, baseAddresses);
    }
}

public class WebHttpBehaviorEx : WebHttpBehavior
{
    protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        // Clear default error handlers
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
        // Add our own error handler
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new ErrorHandlerEx());
    }    

However, after I created my own error handler, it seems it overrides the "enableWebScript" setting I had in my config above, which I think makes sense because now I'm creating my very own behavior dynamically which doesn't have any of the config settings above.

I read that this setting should be used with WCF/Ajax for security purposes (see here http://www.asp.net/ajaxlibrary/Using%20JSON%20Syntax%20with%20Ajax.ashx). So my question is, how can I set the the "enableWebScript" setting on my dynamically created behavior? Or is it not possible?

Update (6/1/2011): I'm also looking to dynamically change the behavior to use Windows credentials for authentication. In the config file it's done like this:

<bindings>
  <webHttpBinding>
    <binding name="Binding1">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Windows" />
      </security>
    </binding>
  </webHttpBinding>
</bindings>

This is another setting I need to make programmatically since it seems to ignore the config setting.

Ben
  • 1,169
  • 3
  • 17
  • 27
  • You shouldn't need both and behaviors on the same endpoint. The former is a general-purpose behavior for any REST-enabled WCF endpoint; the latter is specifically tailored for creating REST-enabled endpoints to be consumed by ASP.NET AJAX clients. – carlosfigueira May 31 '11 at 21:24
  • Yes, thanks Carlos. I am currently now using just the enableWebScript for the purpose you state. My goal is to find a way to dynamically set this behavior property somewhere when creating my new behavior. Do you know of a way to do this? – Ben May 31 '11 at 21:47
  • You can add the behavior programmatically as mentioned by Joel C. However, WebScriptEnablingBehavior is sealed, so you can't really extend it. Just to confirm, are you using AJAX in an ASP.NET application, or are you really using ASP.NET AJAX (similar names, different technologies :)? ASP.NET AJAX means using the to manage scripts in your HTML/JS page. – carlosfigueira May 31 '11 at 23:02
  • Nope not using AJAX through ASP.NET and no ASP.NET controls. I have a jQuery based UI that makes AJAX calls to a WCF service. Is enableWebScript a property in the WebScripEnablingBehavior class? Like I responded to Joel that it seems I already have a WebScriptEnablingBehavior object in my Properties collection when it creates the service host, but I can't find the programmatic equivalent to enableWebScript. – Ben Jun 01 '11 at 13:27

2 Answers2

1

For me it worked after adding the following constructor in WebHttpBehaviorEx

    public  WebHttpBehaviorEx()
    {
        DefaultBodyStyle = WebMessageBodyStyle.Wrapped;
        DefaultOutgoingRequestFormat = WebMessageFormat.Json;
        DefaultOutgoingResponseFormat = WebMessageFormat.Json;
    }
Madalina
  • 11
  • 1
0

There is a class WebScriptEnablingBehavior that you should be able to create in instance of programmatically and add it to the Behaviors collection of your endpoint. I've never tried it, and don't know how exactly that would work having multiple behaviors defined on a single endpoint, but I think that's basically what you're doing in your declarative configuration. Unfortunately WebScriptEnablingBehavior (which inherits from WebHttpBehavior) is sealed, so you can't just inherit from it.

Update: (from here)

The WebScriptEnablingBehavior is a "profile" of the WebHttpBehavior functionality designed specifically for interop with ASP.NET AJAX clients. It adds in some AJAX-isms like the ability to automatically generate ASP.NET AJAX client proxies.

I'm not sure you actually need to use <enableWebScript/>, like Carlos said, it sounds like it's only needed when you're using ASP.NET AJAX.

Joel C
  • 5,547
  • 1
  • 21
  • 31
  • Actually when I break at the CreateServiceHost() method I check the endpoint Behaviors and it does have a WebScripEnablingBehavior object as one of the behaviors. I might be able to set or enable this property for it, but I don't know and can't find how to access the enableWebScript property on it. – Ben Jun 01 '11 at 13:09
  • The only reason why I think I need it is because before I added my behaviors programmatically and used the config settings, I used to get my data off the ".d" param in the result object returned from the Ajax call. Now I get the data directly off of the result object. Reading more into it I found that enableWebScript adds the ".d" param for security purposes (cross-site scripting risk) [here](http://www.asp.net/ajaxlibrary/Using%20JSON%20Syntax%20with%20Ajax.ashx). So I do get my data, but I'm missing the added security of the .d param, making me wonder if I have to set it programmatically. – Ben Jun 01 '11 at 15:36
  • @Ben Honestly, unless I'm misunderstanding something, I find the argument that returning data in `d` is more secure to be pretty weak. Sure, it won't be parseable as a JSON construct using a default AJAX library, but how would it stop someone from using custom parsing (just like I'm sure you're having to do)? For cross-site scripting to work, the attacker would already have to know about your script service to make the request, isn't it reasonable to assume they'd be capable of rolling their own object parser? – Joel C Jun 01 '11 at 16:27
  • Joel, thanks for your reply. I'm not an expert on this by any means, but I think that the "d" just makes the results an invalid JavaScript command. This is another [site that explains it](http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=436). But that aside, I'm really trying to figure out how to dynamically set these values. Another issue I'm running into is dynamically setting the behavior to use Windows credentials. See my addition to the original post. – Ben Jun 01 '11 at 17:57
  • @Ben, did you find a way to pull this off? – dbobrowski Sep 26 '11 at 14:45
  • No. never did, but I decided to catch all errors and return a JSON error object. At the time it worked for what I needed. – Ben Oct 12 '11 at 20:28