BlogEngine.net and Live Writer work together. How very cool.

I just found out that Live Writer supports BlogEngine.NET. With this plus the cool extension Code Snippet I now don’t have to deal with formatting the code entries. I think they look better too. One of the things driving this all however is that the RSS feed doesn’t seem to like my old code formatting. Check out the new style. I hope to update my older posts soon.

var changeSet = [];
var entityChange = {};
//Setting Id for entityChange, not the entity key but how the changeset tracks each change if there is more than one
entityChange.Id = 0;
entityChange.Entity = { '__type': "PocoEntity:#jQueryDemo.Web", 'EntityKey': 4, 'EntityData': 'Entity 4 Client Data' };
//Set the type of Operation to be performed on the Entity
//2 - insert
//3 - update
//4 - delete
entityChange.Operation = 2;
changeSet.push(entityChange);
var changsetPayload = JSON.stringify({ "changeSet": changeSet });
//Create jQuery ajax request
var Params = {}
Params.type = "POST";
Params.url = 'jQueryDemo-Web-PocoDomainService.svc/JSON/' + 'SubmitChanges';
Params.dataType = "json";
Params.data = changsetPayload;
Params.contentType = "application/json"
Params.success = function (data) {
    //{"SubmitChangesResult":[{"Entity":{"__type":"PocoEntity:#jQueryDemo.Web","EntityData":"Entity 4 Client Data","EntityKey":"4"},"EntityActions":null,"HasMemberChanges":false,"Id":0,"Operation":2}]}
    for (i in data.SubmitChangesResult) {
        result = data.SubmitChangesResult[i];
        $('body').append('<p>' + result.Entity.EntityData + '</p>');
    }
}
//Make the ajax request
$.ajax(Params);

Update:

Larry asked what settings I chose to connect to BlogEngine.net. I chose Other services and then entered my website & admin user info. I was a little surprised myself that everything just lit up.

WCF RIA Services, jQuery, and JSON endpoint – Part 2

In order to perform CUD operations with WCF RIA Services a changeset must be built. All of the operations use JSON/SubmitChanges. What is performed on the entity depends on the Operation enum.

Lets look at the Insert first:

function Insert() {
    var changeSet = [];
    var entityChange = {};
    //Setting Id for entityChange, not the entity key but how the changeset tracks each change
    entityChange.Id = 0;
    entityChange.Entity = { '__type': "PocoEntity:#jQueryDemo.Web", 'EntityKey': 4, 'EntityData': 'Entity 4 Client Data' };
    //Set the type of Operation to be performed on the Entity
    //2 - insert
    //3 - update
    //4 - delete
    entityChange.Operation = 2;
    changeSet.push(entityChange);
    var changsetPayload = JSON.stringify({ "changeSet": changeSet });
    //Create jQuery ajax request
    var Params = {};
    Params.type = "POST";
    Params.url = 'jQueryDemo-Web-PocoDomainService.svc/JSON/' + 'SubmitChanges';
    Params.dataType = "json";
    Params.data = changsetPayload;
    Params.contentType = "application/json"
    Params.success = function (data) {
        for (i in data.SubmitChangesResult) {
            result = data.SubmitChangesResult[i];
            $('body').append('<p>' + result.Entity.EntityData + '</p>');
        }
    }
    //Make the ajax request
    $.ajax(Params);
}
//JSON result from server after submit
{ "SubmitChangesResult": [{
    "Entity": { "__type": "PocoEntity:#jQueryDemo.Web",
        "EntityData": "Entity 4 Client Data",
        "EntityKey": "4"
    },
    "EntityActions": null,
    "HasMemberChanges": false,
    "Id": 0,
    "Operation": 2
}]
}

A changeset is an array of entity changes which have their own id, operation and entity to be modified. Here is the JSON:

{"changeSet":[    
    {"Id":0,     
    "Entity":{
        "__type":"PocoEntity:#jQueryDemo.Web",
        "EntityKey":4,
        "EntityData":"Entity 4 Client Data"},
     "Operation":2}
]}

The Id should be incremented for each operation if there are multiple in the submit. The Entity is the fields to insert plus a special __type string. (Special note: make sure you have two underscores before type or the serializer will not treat it as a special instruction). The format is <type>:#<namespace>. The Operation value lets WCF RIA Services know what to do with the entity. The result on success passes back the entity that the server has. For example if there is an auto-increment database key the client will be able to update its copy of the entity.

Delete is almost identical to Insert with Operation set to 4 instead. I also perform a Load after the delete to refresh the page (rather than find the entity in html and removing that node). To keep things simple I have created a Submit function that handles all CUD operations.

function Delete() {
    var changeSet = [];
    var entityChange = {};
    entityChange.Id = 0;
    entityChange.Entity = { '__type': "PocoEntity:#jQueryDemo.Web", 'EntityKey': 2 };
    //Delete
    entityChange.Operation = 4;
    changeSet.push(entityChange);
    var changsetPayload = JSON.stringify({ "changeSet": changeSet });
    //Create jQuery ajax request
    var Params = {}
    Params.type = "POST";
    Params.url = 'jQueryDemo-Web-PocoDomainService.svc/JSON/' + 'SubmitChanges';
    Params.dataType = "json";
    Params.data = changsetPayload;
    Params.contentType = "application/json"
    Params.success = function (data) {
        Load();
    }
    //Make the ajax request
    $.ajax(Params);
}
//JSON result from server after submit
{ "SubmitChangesResult": [{
    "Entity": {
        "__type": "PocoEntity:#jQueryDemo.Web",
        "EntityData": null,
        "EntityKey": "2"
    },
    "EntityActions": null,
    "HasMemberChanges": false,
    "Id": 0,
    "Operation": 4
}]
}

Update requires an OriginalEntity object with the key and any required fields.

function Update() {
    var changeSet = [];
    var entityChange = {};
    entityChange.Id = 0;
    entityChange.Entity = { '__type': "PocoEntity:#jQueryDemo.Web", 'EntityKey': 3, 'EntityData': 'Entity 3 Client Updated' };
    //Update
    entityChange.Operation = 3;
    //Which entity is being updated. Only has to contain required parameters and keys.
    entityChange.OriginalEntity = { '__type': "PocoEntity:#jQueryDemo.Web", 'EntityKey': 3 };
    changeSet.push(entityChange);
    var changsetPayload = JSON.stringify({ "changeSet": changeSet });
    //Create jQuery ajax request
    var Params = {}
    Params.type = "POST";
    Params.url = 'jQueryDemo-Web-PocoDomainService.svc/JSON/' + 'SubmitChanges';
    Params.dataType = "json";
    Params.data = changsetPayload;
    Params.contentType = "application/json"
    Params.success = function (data) {
        Load();
    }
    //Make the ajax request
    $.ajax(Params);
}
//JSON result from server after submit
{ "SubmitChangesResult": [{
    "Entity": {
        "__type": "PocoEntity:#jQueryDemo.Web",
        "EntityData": "Entity 3 Client Updated",
        "EntityKey": "3"
    },
    "EntityActions": null,
    "HasMemberChanges": true,
    "Id": 0,
    "Operation": 3
}]
}

To improve the sample project I also included an Invoke method that resets the in memory ‘database’. To allow the method to be called with GET, HasSideEffects must be set to false for the Invoke attribute.

$.get('jQueryDemo-Web-PocoDomainService.svc/JSON/ResetData', Load);

The request passes the Load method as a callback so it refreshes the pages data on completion.

WCF RIA Services, jQuery, and JSON endpoint – Part 1

Here I will show how to perform a simple load using jQuery and RIA Services.

Pre-requisites:

Server Setup

I start with the server because the namespace and class names affect the jQuery code. To keep things simple (and remove the need for a database and DAL) I will use a POCO DomainService. There is a PocoEntity with a key and data field. It is exposed by the GetPoco method.

PocoEntity.cs

using System.ComponentModel.DataAnnotations;
namespace jQueryDemo.Web
{
    public class PocoEntity
    {
        [Key]
        public string EntityKey { get; set; }
        public string EntityData { get; set; }
    }
}

PocoDomainService.cs

namespace jQueryDemo.Web{    using System.Collections.Generic;    using System.Linq;    using System.ServiceModel.DomainServices.Hosting;    using System.ServiceModel.DomainServices.Server;     [EnableClientAccess()]    public class PocoDomainService : DomainService    {        private static List pocoList;         public PocoDomainService()        {            pocoList = new List();            pocoList.Add(new PocoEntity() { EntityKey = "1", EntityData = "Entity 1 Server Data" });        }         public IQueryable GetPoco()        {            return pocoList.AsQueryable();        }    }}

Client Setup

On the client include the json2 and jquery-1.4.2.js. I prefer to create a separate file for my javascript code.

jQueryDemo.html

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="scripts/json2.js" type="text/javascript" />
    <script src="scripts/jquery-1.4.2.js" type="text/javascript" />
    <script src="scripts/jQueryDemo.js" type="text/javascript" />
</head>
<body>
</body>
</html>

scripts/jQueryDemo.js

$(document).ready(function () {
    var Params = {};
    Params.type = 'GET';
    Params.url = 'jQueryDemo-Web-PocoDomainService.svc/' + 'JSON/' + 'GetPoco';
    Params.dataType = 'json';
    Params.success = function (data) {
        var returnedEntity;
        for (var i in data.GetPocoResult.RootResults) {
            returnedEntity = data.GetPocoResult.RootResults[i];
            $('body').append('<p>' + returnedEntity.EntityData + '</p>');
        }
    };
    $.ajax(Params);
});

At this point we can view the data on the client and will see a new paragraph tag containing “Entity 1 Server Data”.

Breaking down the jQuery code

Params.type = 'GET';

Using GET (instead of POST) for the query request.

Params.url = 'jQueryDemo-Web-PocoDomainService.svc/' + 'JSON/' + 'GetPoco';

String section 1: jQueryDemo.Web is the namespace that the PocoDomainService class exists in. Dashes are used instead of periods.

String section 2: JSON is the name given to the endpoint in the web.config ex:

<add name="JSON" type="Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory,  Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral,  PublicKeyToken=31bf3856ad364e35" />

String section 3: GetPoco is the name of the Query method defined in PocoDomainService.cs

Params.dataType = 'json';

The data should be in the json format.

Before I explain the next section I want to show the results of visiting the url:

{"GetPocoResult":
    {"TotalCount":1,"RootResults":
        [{"EntityData":"Entity 1 Server Data","EntityKey":"1"}]
    }
}

Now we can see that there is a GetPocoResult object with a RootResults array containing our entity. Knowing this we can loop through each entity in the RootResults array and process it. In this case we simply append the EntityData inside <p> tags to the <body>.

Params.success = function (data) {
    var returnedEntity;
    for (var i in data.GetPocoResult.RootResults) {
        returnedEntity = data.GetPocoResult.RootResults[i];
        $('body').append('<p>' + returnedEntity.EntityData + '</p>');
    }
};

Multiple Entities

Let’s add a few more entities to the PocoDomainService constructor.

public PocoDomainService()
{
    pocoList = new List();
    pocoList.Add(new PocoEntity() { EntityKey = "1", EntityData = "Entity 1 Server Data" });
    pocoList.Add(new PocoEntity() { EntityKey = "2", EntityData = "Entity 2 Server Data" });
    pocoList.Add(new PocoEntity() { EntityKey = "3", EntityData = "Entity 3 Server Data" });
}

Now the returned string looks like this. You should notice jQueryDemo.js doesn’t need to be updated to handle multiple entities.

{"GetPocoResult":
    {"TotalCount":3,"RootResults":
          [{"EntityData":"Entity 1 Server Data","EntityKey":"1"},
           {"EntityData":"Entity 2 Server Data","EntityKey":"2"},
           {"EntityData":"Entity 3 Server Data","EntityKey":"3"}]
    }
}