Damian Mehers' Blog Xamarin from Geneva, Switzerland.

31Oct/0822

WCF REST Services: Setting the response format based on request’s expected type

I just attended the Microsoft PDC in LA.  One of the many excellent sessions was a pre-conference on WCF, part of which was presented by Ron Jacobs. Ron did a fantastic job of explaining WCF REST Services and the WCF REST Starter Kit.

One of the examples he showed from the WCF REST Starter kit was an example where the response type (JSON or XML) is dynamically set based on the HTTP request's requested content type in the "Accepts" HTTP Header.

That example works by switching between two different operation implementations (methods).

I liked the idea of using the requested content type to automatically return JSON or XML depending on the requested content type, but I wasn't so keen on having to implement two methods.

I thought I'd try to get a similar thing working but using a single operation implementation which is called no matter whether or JSON or XML are requested.

The DynamicResponseType attribute

This is how it works.  You decorate your method with an additional DynamicResponseType attribute which I have defined:

   1: [ServiceContract]
   2: [ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
   3: [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   4: public class Service1
   5: {
   6:     [OperationContract]
   7:     [WebGet(UriTemplate = "GetData?param1={i}&param2={s}")]
   8:     [DynamicResponseType]
   9:     public SampleResponseBody GetData(int i, string s)
  10:     {
  11:         return new SampleResponseBody() { 
  12:             Name = "Test",
  13:             Value = s, 
  14:             Time = DateTime.Now.ToShortTimeString() 
  15:         };
  16:     }
  17: }
  18:  
  19: public class SampleResponseBody
  20: {
  21:     public string Name { get; set; }
  22:     public string Value { get; set; }
  23:     public int IntValue { get; set; }
  24:     public string Time { get; set; }
  25: }

An example client

Then when the client requests a specific type (XML or JSON), it is served automatically.

Below I have a pure HTML/Javascript client with two buttons, each of which call the same  GetWebRequest function when they are clicked but passing a different requested content type as a parameter.  The GetWebRequest function issues an HTTP request to the WCF operation I showed above.

The first button says it wants JSON, and the second XML.  This is done by setting the "Accept" request header:

   1: <body>
   2:     <form id="form1" runat="server">
   3:     <div>
   4:     
   5:     <input type="button" value="Click to request JSON" 
   6:         onclick="GetWebRequest('application/json');" />
   7:     
   8:     <input type="button" value="Click to request XML" 
   9:         onclick="GetWebRequest('application/xml');" />
  10:     
  11:     </div>
  12:     <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
  13:     </form>
  14:  
  15: <script type="text/javascript">
   1:  
   2:   function GetWebRequest(acceptType) {  
   3:     var wRequest = new Sys.Net.WebRequest();
   4:     wRequest.get_headers()["Accept"] = acceptType;
   5:     var url = "/Service1.svc/GetData?param1=12&param2=";
   6:     wRequest.set_url(url + new Date());
   7:     wRequest.set_httpVerb("GET");
   8:     wRequest.add_completed(OnWebRequestCompleted);
   9:     wRequest.invoke();
  10:   }
  11:  
  12:   function OnWebRequestCompleted(executor, eventArgs) {
  13:     alert(executor.get_responseData());
  14:   }

</script>

  16: </body>

This is the form that gets displayed initially:

image

When you click on the first button we request JSON from the WCF Service operation:

image

When you click on the second button we request XML from the same WCF Service operation:

image

How it works.

I've created my own  WCF ServiceHostFactory which I wire up in the SVC file:

   1: <%@ ServiceHost Language="C#" 
   2:     Debug="true" 
   3:     Service="WcfService2.Service1" 
   4:     CodeBehind="Service1.svc.cs" 
   5:     Factory="DamianBlog.ServiceHostFactory2Ex" %>

In my ServiceHostFactory2Ex class I ensure that my own WebServiceHost class gets created.

Then in my own WebServiceHost I ensure that my own WebHttpBehavior replaces the standard one.

Next in my own WebHttpBehavior I override the GetReplyDispatchFormatter method and return my own IDispatchMessageFormatter.

In my own IDispatchMessageFormatter I implement the SerializeReply method and then use a JSON formatter or XML formatter depending on the "Accepts" HTTP request header which I pick up from the OperationContext.Current.RequestContext.RequestMessage.

The full source is available for download here http://damianblog.com/WCFDynamicResponseDemo.zip.

Rob Jacobs blogs at http://blogs.msdn.com/rjacobs/

Filed under: WCF 22 Comments
26Oct/080

To right click running Vista on new (late 2008) MacBook Pros

All the documentation says to press two-fingers and click, but actually you must press down three fingers and then click to right-click when running Vista, Boot Camped on the new MacBook Pros (late 2008).

Filed under: Uncategorized No Comments
22Oct/080

ASP.NET MVC with the AJAX Control Toolkit: automatically getting control dependencies

[Edited 23rd Oct to compress returned JavaScript]

I recently wrote a blog post showing how you can use controls from the AJAX Control Toolkit in ASP.NET MVC applications, specifically the ListSearchExtender.  Stephen Walther also wrote one on using the Calendar control here.

One thing that bugged me was that it was painful to find out what scripts a particular control depended on, so that they could be included in the JavaScript used to initialize a control.

I decided to create a simple MVC Controller/View that would return back all the JavaScript required for any particular ASP.NET AJAX Control Toolkit control.

This is the old code for using the ListSearchExtender in an ASP.NET MVC View:

<select id="Countries">
    <option>Switzerland</option>
    <option>United Kindom</option>
    <option>United States</option>
</select>

<script src="/Scripts/MicrosoftAjax.debug.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.Common.Common.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.ExtenderBase.BaseScripts.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.DynamicPopulate.DynamicPopulateBehavior.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.Compat.Timer.Timer.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.Animation.Animations.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.Animation.AnimationBehavior.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.PopupExtender.PopupBehavior.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.PopupControl.PopupControlBehavior.js" type="text/javascript"></script>
<script src="/Scripts/AjaxControlToolkit.ListSearch.ListSearchBehavior.js" type="text/javascript"></script>

<script type="text/javascript">
Sys.Application.initialize();
Sys.Application.add_init(function() {
    $create(AjaxControlToolkit.ListSearchBehavior,
        { "id": "ListBox1_ListSearchExtender" },
        null, null, $get("Countries"));
});
</script>

This is the new code to pull in the dependencies:

<select id="Countries">
    <option>Switzerland</option>
    <option>United Kindom</option>
    <option>United States</option>
</select>

<script src="/ControlDependencies/Get?extenderTypeName=AjaxControlToolkit.ListSearchExtender" type="text/javascript"></script>

<script type="text/javascript">
Sys.Application.initialize();
Sys.Application.add_init(function() {
    $create(AjaxControlToolkit.ListSearchBehavior,
        { "id": "ListBox1_ListSearchExtender" },
        null, null, $get("Countries"));
});
</script>

You'll see that all the individual script includes have been replaced by a single call to the Get action on the ControlDependencies controller.

This is the source to the controller:

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;
using AjaxControlToolkit;

namespace TestDependencies.Controllers {
public class ControlDependenciesController : Controller {
    readonly Assembly toolkitAssembly =
        typeof(AjaxControlToolkit.Utility).Assembly;

    [OutputCache(VaryByParam = "extenderTypeName",
                 Duration = 86400,  // One day
                 Location = System.Web.UI.OutputCacheLocation.Client)]
    public ActionResult Get(string extenderTypeName) {

        if (string.IsNullOrEmpty(extenderTypeName)) {
            return new EmptyResult();
        }

        // Get the type representing the extender we are handling
        Type extenderType = toolkitAssembly.GetType(extenderTypeName,
                                                    false);
        if(extenderType == null) {
            return new EmptyResult();
        }

        // What other extenders does this one depend on?
        Stack<Type> dependencies = new Stack<Type>();
        AddDependencies(extenderType, dependencies);

        // What scripts do those extenders require?
        List<string> scriptsToInclude = new List<string>();
        GetDependencyScripts(dependencies, scriptsToInclude);

        return PartialView(scriptsToInclude);
    }

    // Find the types that the specified extender type depends on
    static void AddDependencies(Type extenderType,
                                Stack<Type> dependencies) {
        dependencies.Push(extenderType);
        Attribute[] attributes =
            Attribute.GetCustomAttributes(extenderType,
                      typeof(RequiredScriptAttribute));

        foreach (RequiredScriptAttribute attribute in attributes) {
            AddDependencies(attribute.ExtenderType, dependencies);
        }
    }

    // Find the scripts used by the specified extender types
    static void GetDependencyScripts(IEnumerable<Type> dependencies,
                                     ICollection<string> scripts) {
        foreach (Type dependency in dependencies) {
            Attribute[] attributes =
                Attribute.GetCustomAttributes(dependency,
                           typeof(ClientScriptResourceAttribute));

            foreach (ClientScriptResourceAttribute attribute in attributes) {
                if (!scripts.Contains(attribute.ResourcePath)) {
                    scripts.Add(attribute.ResourcePath);
                }
            }
        }
    }
}
}

The View is a User Control that simply outputs all of the required scripts.  This is the code-behind:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Web.Mvc;

namespace TestDependencies.Views.ControlDependencies {
  public partial class Get : ViewUserControl<List<string>> {

    protected void Page_Load(object sender, EventArgs e) {
      Response.ContentType = "application/x-javascript";

      // Get compressed stream if possible
      Stream outputStream = GetOutputStream();

      using(StreamWriter outputWriter = new StreamWriter(outputStream)) {

        // Standard AJAX library
        string script = File.ReadAllText(
                              MapPath("/Scripts/MicrosoftAjax.js"));
        outputWriter.WriteLine(script);

        // Required scripts
        foreach(string scriptPath in ViewData.Model) {
          script = File.ReadAllText(MapPath("/Scripts/" + scriptPath));
          outputWriter.WriteLine(script);
        }

      }
      Response.End();
    }

    // Compress scripts if possible -- stolen from ToolkitScriptManager
    // in AJAX Control Toolkit
    private Stream GetOutputStream() {
      Stream outputStream = Response.OutputStream;
      if(!Request.Browser.IsBrowser("IE") ||
                         (6 < Request.Browser.MajorVersion)) {
        foreach(
          string acceptEncoding in (Request.Headers["Accept-Encoding"] ??
                                       "").ToUpperInvariant().Split(',')) {
          if("GZIP" == acceptEncoding) {
            Response.AddHeader("Content-encoding", "gzip");
            outputStream = new GZipStream(outputStream,
                                          CompressionMode.Compress);
            break;
          }
          if("DEFLATE" == acceptEncoding) {
            Response.AddHeader("Content-encoding", "deflate");
            outputStream = new DeflateStream(outputStream,
                                             CompressionMode.Compress);
            break;
          }
        }
      }
      return outputStream;
    }
  }
}

The ASCX is empty:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Get.ascx.cs" Inherits="TestDependencies.Views.ControlDependencies.Get"  %>

There are two advantages to using this technique.  Firstly performance should be increased since all the required scripts are returned in a single response.  Secondly you don't have to manually work out the dependencies for a particular ASP.NET AJAX Control Toolkit control.

Filed under: AJAX, MVC No Comments