Sunday, May 8, 2011

WCF + REST

Good grief...after a long night and most of the morning I finally figured out (via trial-and-error, of course) how to correctly define my WCF contract to work with the dojox.rpc.Rest, dojox.rpc.Service and dojox.data.JsonRestStore.

Here is my interface for a "Echo" resource:


    [DataContract]
    public class EchoValue
    {
        [DataMember]
        public string Id;
        [DataMember]
        public string Value;
        [DataMember]
        public UInt64 Version;
    }

    [ServiceContract]
    public interface IDataServices
    {
        [OperationContract]
        [WebInvoke(Method = "DELETE", UriTemplate = "echo/{id}")]
        void DeleteEcho(string id);

        [OperationContract]
        [WebInvoke(Method = "PUT", UriTemplate = "echo/{id}", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        EchoValue PutEcho(string id, EchoValue data);

        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "echo", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        EchoValue AddEcho(EchoValue data);

        [OperationContract]
        [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate="echo/{id}")]
        EchoValue GetEcho(string id);

        [OperationContract]
        [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "echo")]
        List GetEchos();
    }

First, I hand-coded a service object to understand the details...

    var echoService = function (id) {
        return dojo.xhrGet({
            url: url + "/" + id,
            handleAs: "json",
            load: onLoad,
            error: onError
        });
    };
    dojo.mixin(echoService, {
        put: function (id, value) {
            return dojo.xhrPut({
                url: url + "/" + id,
                handleAs: "json",
                contentType: "application/json",
                putData: dojo.toJson({ Value: value }),
                load: onLoad,
                error: onError
            });
        },
        post: function (id, value) {
            return dojo.xhrPost({
                url: url,
                handleAs: "json",
                contentType: "application/json",
                postData: dojo.toJson({ Id: id, Value: value }),
                load: onLoad,
                error: onError
            });
        },
        "delete": function (id) {
            return dojo.xhrDelete({
                url: url + "/" + id,
                handleAs: "json",
                load: onLoad,
                error: onError
            });
        }
    });
And tested it...

    echoService["delete"]("X").then(function () {
        echoService.post("X", ++key).then(function () {
            echoService["delete"]("X").then(function () {
                echoService.post("X", ++key).then(function () {
                    echoService.put("X", ++key).then(function () {
                        echoService("X").then(function () {
                            dojo.publish("/ready");
                        }); ;
                    });
                });
            });
        });
    });

I also experimented with dojox.rpc.Rest...

  var restService = dojox.rpc.Rest(url + "/", true);
And tested it on its own and with dojox.data.JsonRestStore...

    var restStore = new dojox.data.JsonRestStore({ service: restService });
    restService.put("Y", dojo.toJson({ Value: ++key })).then(function () {
        restStore.fetchItemByIdentity({
            identity: "Y",
            onItem: function (data) {
                restStore.setValue(data, "Value", key++);
                restStore.save();
            },
            onError: onError
        });
    });

I also tested dojox.data.JsonRestStore on its own...

 var store = new dojox.data.JsonRestStore({ target: url, idAttribute: "id" });
 store.newItem({ id: "Z", Value: ++key });
 store.save();
 dojo.publish("/ready");
 
 dojo.subscribe("/ready", function () {
     store.fetchItemByIdentity({
         identity: "Z",
         onItem: function (data) {
             dojo.publish("/update", [data]);
         },
         onError: onError
     });
 });
 
 dojo.subscribe("/update", function (item) {
     store.setValue(item, "Value", ++key);
     store.save();
     dojo.publish("/delete", [item]);
 });
 
 dojo.subscribe("/delete", function (item) {
     store.deleteItem(item);
     store.save();
 });

Things to notice:
The dojox.rpc.Rest requires the URL to end in a "/"
The dojox.data.JsonRestStore defines idAttribute
If you define your WCF REST services "correct" the JsonRestStore works without requiring a service.
The POST and PUT body style is WebMessageBodyStyle.Bare, indicating that the parameter name "data" is not part of the request. Without this it is necessary to wrap the parameter in a "Data" container, for example, putData: dojo.toJson({ Data: {Value: 1} }).

links:
http://docs.dojocampus.org/dojox/rpc/Rest
http://docs.dojocampus.org/dojox/rpc/Service
http://dojotoolkit.org/reference-guide/dojox/data/JsonRestStore.html
http://dojotoolkit.org/reference-guide/dojo/data/ItemFileWriteStore.html
http://dojotoolkit.org/reference-guide/dojo/data/api/Write.html
using-the-dojo-toolkit-with-microsofts-wcf/
http://www.sitepen.com/blog/2008/11/21/effective-use-of-jsonreststore-referencing-lazy-loading-and-more/
http://www.sitepen.com/blog/2008/06/13/restful-json-dojo-data/
http://www.sitepen.com/blog/2008/03/19/pluggable-web-services-with-smd/

1 comment:

  1. DOJO Toolkit Online Training, http://www.21cssindia.com/courses/dojo-toolkit-online-training-174.html The 21st Century Software Solutions of India offers one of the Largest conglomerations of Software Training, IT Support, Corporate Training institute in India - +919000444287 - +917386622889 - Visakhapatnam,Hyderabad DOJO Toolkit Online Training, DOJO Toolkit Training, DOJO Toolkit, DOJO Toolkit Online Training| DOJO Toolkit Training| DOJO Toolkit| "Courses at 21st Century Software Solutions
    Talend Online Training -Hyperion Online Training - IBM Unica Online Training - Siteminder Online Training - SharePoint Online Training - Informatica Online Training - SalesForce Online Training - Many more… | Call Us +917386622889 - +919000444287 - contact@21cssindia.com
    Visit: http://www.21cssindia.com/courses.html"

    ReplyDelete