Recently about .NET

Have you ever had an enum in your server code that you wanted to access in client side code? Or wanted the safety of compile time errors when there are discrepancies between your server-side and client-side code? Or had a C# Data Transfer Object (DTO) that you wanted to enable Intellisense for in JavaScript? I hadn't found a good solution either ... until now.

Compiling C# to What!?

Compiling C# code into JavaScript may seem foreign, but Script# is a mature technology that is absolutely worth a look. Our team has been using it very happily for about three months. We've found a number of benefits including:

  • Consistently working Intellisense
  • Better encapsulation
  • Simpler Object Orientation
  • Easier deployment (Script# compiles multiple files to a single, optionally minified file)
  • Safer refactoring
  • Simpler unit testing
  • Type safety; and
  • Design time syntax checking (no more mistyping a variable and accidentally declaring it to the global scope)

Scott Hanselman covered most of these topics in last month's Hanselminutes episode: Script# Compiles to JavaScript. If you have a spare car ride I definitely recommend the listen. But what wasn't covered were some additional benefits provided by an off the beaten path approach to this great technology. The main benefit is tighter server side C# to client side JavaScript integration. A secondary benefit is less of a dependency on Script#.

To the Command Line

Typically to get going with Script# you:

  1. Install the Script# Visual Studio plug-in
  2. File -> New project
  3. Select "Script Library" and
  4. Compile to generate JavaScript

Nice and easy. The down side to this approach is you can't easily include files outside of your project. Specifically, you can't include data transfer objects or enum's from your server side code. Furthermore, all of your team members must install Script#. If instead you compile with Script#'s "ssc.exe" command you obtain more control and get less dependency.

How-To

The how-to looks something like this:

  1. Download and install Script#
  2. Add a Class Library (not a Script# project)
  3. Project properties -> Build -> Advanced -> "Do not reference mscorlib"
  4. Ideally move the Script# files (C:\Program Files (x86)\ScriptSharp) locally to the solution and check them into source control to a Libs or something similar
  5. Remove all references, but add: ScriptSharp.dll, ScriptSharp.Web.dll, Script.Jquery
  6. Edit your .csproj to manually reference Script#'s mscorlib (right click, Unload project, Edit MyProject.csproj)

    <Reference Include="mscorlib, Version=0.7.0.0, Culture=neutral, PublicKeyToken=8fc0e3af5abcb6c4, processorArchitecture=MSIL">
      <
    SpecificVersion>True</SpecificVersion>
      <
    HintPath>..\Libs\ScriptSharp\v1.0\mscorlib.dll</HintPath>
    </
    Reference>


  7. Modify AssemblyInfo.cs and remove the following lines:

    [assembly: ComVisible(false)]
    [assembly: Guid("b5e2449f-193c-46d1-9023-9143618d8491")]

  8. Modify AssemblyInfo.cs and add the following:

    [assembly: ScriptAssembly("ScriptSharpDemoAssembly")

  9. Ensure it compiles in Visual Studio
  10. Create a batch script or PowerShell script that compiles using ssc.exe like this:

    ..\Libs\ScriptSharp\v1.0\ssc.exe ^
        /debug ^
        /out:MyScriptSharp.js ^
        /ref:"..\Libs\ScriptSharp\v1.0\Framework\mscorlib.dll" ^
        .\Properties\AssemblyInfo.cs ^
        .\Class1.cs

Notice the last two lines in the script are a list of the files that you want to include. The point of this exercise is that you can now include files outside of your main Script# project in that list.

Now for completeness if you put a simple static method in Class1.cs, something like this:

namespace MyScriptSharp
{
    public class Class1
    {
        public static string HelloWorld()
        {
            return "Hello World!";
        }
    }
}

Then run the batch file you should get something like this:

Type.registerNamespace('MyScriptSharp');

////////////////////////////////////////////////////////////////////////////////
// MyScriptSharp.Class1

MyScriptSharp.Class1 = function MyScriptSharp_Class1() {
}
MyScriptSharp.Class1.helloWorld = function MyScriptSharp_Class1$helloWorld() {
    return 'Hello World!';
}

MyScriptSharp.Class1.registerClass('MyScriptSharp.Class1');

Obviously you could get these results faster with approach #1. But now you have a lot more control.

Summary

The main downside to this approach is maintaining the batch file is a bit of a hassle. But the upsides are that you can include any file from your server-side C# code. And any changes in that server-side code are automatically reflected in your JavaScript. And any breaking changes in your server-side code generate compile time errors in your client side code. And furthermore none of your team members need to install Script#. For our team it's an easy tradeoff. What about for yours? Please share your thoughts in the comments or on twitter.


Problem: The domain model contains the idea of a document, and one of the documents in the model has multiple purposes. By purpose, I mean that the physical document is filled out with different data depending on who the document is for. Each purpose may or may not have different logic associated with the creation. The document abstractions should be easily testable to make document creation as robust as possible.

A Solution: One solution that I found was based on the template method from the GoF book. The intent of this solution was to simplify the creation of the known views of the document. The key idea of the solution is to put as much of the logic involved in document creation into to the base class.

Implementation:

abstract class Document
{
	IDictionary FormTextFields
	{
		get
		{
			return new Dictionary
			{
				{ "NameField", this.NameField },
				{ "AgeField", this.AgeField }
			};
		}
	}
	
	private string NameField
	{
		get
		{
			if(this.DocumentType == DocumentType.Big)
			{
				return "Big name";
			}
			else if(this.DocumentType == DocumentType.Small)
			{
				return "Small name";
			}
			
			return string.Empty;
		}
	}
	
	private string AgeField
	{
		get
		{
			if(this.DocumentType == DocumentType.Big)
			{
				return "42";
			}
			
			return string.Empty;
		}
	}
	
	protected abstract DocumentType DocumentType { get; }
}

class BigDocument : Document
{
	protected override DocumentType DocumentType
	{
		get
		{
			return DocumentType.Big;
		}
	}
}

Benefits: As previously stated, the main purpose of the base class is to simplify the creation of the subclasses. This solution does just that by reducing the amount of work needed to create a new subclass. The subclasses have only two main actions required for creation. The first action is to define the type of the document which is an abstract method in the base class. The second action, not shown in the subclass, is the validation of the specific concrete document type. Just doing these two actions, as oppose to adding new creation logic, speeds up the creation of new subclasses.

Two other benefits to this solution are centralization of the logic for document creation and having reduced unit testing needs for the subclasses. When the logic of the document creation is centralized into a single base class, reasoning about the document creation becomes easier. Problems arising from document creation are easier to track down. The document base class becomes the focal point for the majority of the unit tests written for document creation. The focal point reduces the need to test the subclasses since the vast majority of the behavior is in the base.

Drawbacks: A large drawback of placing all the logic relating to the document creation in the base is that the rules for creation have to be completely available. If the rules of the creation of the document are not known then the base class will be incomplete. When the base class is incomplete, it has to be reopened every time a new rule is found. The problem of adding rules leads to the main drawback of the solution: extensibility. This solution is in no way extensible since all the logic is congregated in the base class. This drawback does pose problems, however with a little rejiggering the impact of this drawback can be minimized. One possible fix, that will reduce the extensibility problem, but will increase the work to create a subclass, is to add an abstract method to the base that filters the dictionary before it is sent out. 

abstract class Document
{
	IDictionary FormTextFields
	{
		get
		{
			return new Dictionary
			{
				{ "NameField", this.NameField },
				{ "AgeField", this.AgeField }
			};
		}
	}
	
	protected abstract IDictionary FilterTextFields(IDictionary textFields);
}

class SmallDocument : Document
{
	protected override IDictionare FilterTextFields(IDictionary textFields)
	{
		textFields["NameField"] = SmallLogic();
		return textFields;
	}
	
	protected override DocumentType DocumentType
	{
		get
		{
			return DocumentType.Small;
		}
	}
}

Unlike many ORM solutions MS Entity Framework does not lazy fetch accessed tables. Coming from LINQ to SQL I didn't like this feature at first because it meant adding a bunch of loosely typed include statements to every SQL call. But I quickly realized the performance benefits, not to mention theN+1 problem just goes away. But, I still had heartburn over the loose typing of the include statement, so I came up with my own include. But first to set the stage let me show you what you currently have to write.

  ctx.Users.Include("Order.Item");

This will fetch all Users as well as all the items that they ordered.

To fix this we need to add some method to Users which is of type ObjectQuery. To do that we will use extension methods to add my own include to ObjectQuery. Here is the code for that.

public static class ObjectQueryExtensionMethods {
  public static ObjectQuery<T> Include<T>(this ObjectQuery<T> query, Expression<Func<T, object>> exp) {
    Expression body = exp.Body;
    MemberExpression memberExpression = (MemberExpression)exp.Body;
    string path = GetIncludePath(memberExpression);
    return query.Include(path);
  }

  private static string GetIncludePath(MemberExpression memberExpression) {
    string path = "";
    if (memberExpression.Expression is MemberExpression) {
      path = GetIncludePath((MemberExpression)memberExpression.Expression) + ".";
    }
    PropertyInfo propertyInfo = (PropertyInfo)memberExpression.Member;
    return path + propertyInfo.Name;
  }
}

Using C# expressions and extension methods we now can write this

  ctx.Users.Include(u => u.Order.Item);

Refactor and type-safe

Entity Framework still has it's annoyances, but hopefully this will make it a little less painful. Now if it would only throw an exception if you tried to access a non-included entity instead of just returning null.

Occasionally I hear complaints that LINQ is hard to unit test. These complaints aren't about LINQ to objects, mind you, they're specific to the complexities of the flavors of LINQ that turn C# code into something else like SQL or CAML using expression trees. The most common technologies are LINQ to SQL, the Entity Framework, or in my case at the moment LINQ to SharePoint. In this post I'm going to propose a technique that makes testing LINQ not just easy, but downright elegant - assuming you're ok with extension methods - lots of extension methods. And assuming you're ready to kill your Data Access Objects (DAO) tier.

The Unit Testing Problem

Any architecture needs a place to put code that finds entities. For instance FindBySocialSecurityNumber(). In a traditional architecture we might put a method like this is in a DAO layer. If so our method will look something like this:

public class EmployeesDao {
    public Employee FindBySSN(Context ctx, string ssn) {
        return ctx.Employees.SingleOrDefault(e => e.Ssn == ssn);
    }
}

So how would we go about unit testing this?

One fairly typical solution would be to use an in-memory database. That approach works if our data store is a database, but it certainly doesn't work if the data store is something less traditional like SharePoint. But even if our store is a database, we'll still have the hassle of setting up the in-memory database.

Another solution might be to use a mock Context that returns an IQueryable. But wouldn't it be wonderful if we could avoid mocking all together?

Killing the DAO

The first question is why we even have a DAO tier to begin with. The original idea was that we wanted a place to put code specific to a particular data store. In other words we wanted to isolate the code that will need to be changed should the data store switch from SQL Server to Oracle. But isn't that exactly what LINQ does? I'd be pretty surprised if there wasn't a decent LINQ provider for just about any data store at this point that required more than minimal code changes. So why not embrace LINQ and reconsider alternatives to a DAO tier?

One alternative that I've been using for over a month now is to switch to extension methods. To give credit where it's due the idea originated with a conversation with fellow Near Infinity employee Joe Ferner. And I'm sure the idea isn't particularly original (please post in the comments if you know others that use this approach).

Using this technique our code changes from something like this:

var employeeDao = new EmployeesDao(); // or use IOC of course
employeeDao.FindBySSN(ctx, "111-11-1111");

To something like this:

ctx.Employees.FindBySSN("111-11-1111");

Among other things I find this far more aesthetically pleasing because each of the three elements to the statement represent a subsequent filtering of data. It's a more functional way of looking at things.

We could implement this off of the Employees property of the context if we have control over that (which I don't with spmetal). But if we implement this as an extension method like this:

public static class EmployeeExtensions {
    public static Employee FindBySSN(this IQueryable<Employee> employees, string ssn) {
        return employees.SingleOrDefault(e => e.Ssn == ssn);
    }
}

We now have something that's considerable easier to unit test.

Testing It

Once we've refactored our function as an extension method that filters down the corpus of entities, we can test the code using in-memory objects with a call to .AsQueryable(). For instance:

public void FindBySSN_OneSsnExists_EmployeeReturned() {
       var employees = new [] { new Employee { Ssn = "111-11-1111" } };
       var actual = employees.AsQueryable().FindBySSN("111-11-1111");
       Assert.IsNotNull(actual);
}

Notice we didn't have to mock anything.

Testability, but at What Cost?

This technique works great for the example above, but how does it scale to harder problems and what other downsides are there?

As far as scalability I've found this technique works great for every scenario I've run across in the month I've been doing it. It works for joins, aggregations, and even for inserts, update, and deletes.

As far as downsides the astute reader may be wondering about mockability. For instance what if we want to mock the call to FindBySSN and give it the exact Employee that will be returned. This scenario is admittedly harder. But what I've found is that far more often than not I don't really need to mock the types of things that used to live in the DAO tier. Instead I just mock the Employee object off of context to return in-memory objects and make my tests slightly larger in scope. Most of the time I find the larger scope increases the usefulness of the test. In the occasional case where I do really want to mock the "DAO" tier I use a technique described in this post by Daniel Cazzulino.

Conclusion

Obviously there is more to this architecture, for instance how do you handle insert and update operations? The short answer is it's easy, but I'll save that topic for a future post. For now why not give this approach a try? You weren't really happy with that useless old DAO tier anyway, were you? I say we eradicate it and never look back.

This is part 4 of a multi-part series exploring building client side AJAX applications with ASP.Net AJAX 4 Templating and the WCF Data Services (aka ADO.Net Data Services, aka oData, aka Astoria) in SharePoint 2010.

Part 1 - Exploring WCF Data Services in SharePoint 2010
Part 2 - Creating a read-only page with ASP.Net AJAX 4.0 Templates
Part 3 - Writing data back to SharePoint with ASP.Net AJAX 4.0 Templates
Part 4 - jQuery and Manual JSON Object Manipulation

In the previous posts in this series I've shown how you can access SharePoint data using WCF Data Services, how you can display that data using ASP.Net AJAX 4.0 Templates, and how you can write data back to SharePoint.

In this post I'll take writing data back to SharePoint a step further by showing how you can modify non-visible fields by modifying JSON objects directly. More specifically I'll enable dragging user story index cards on a virtual bulletin board using a jQuery plugin, save the X and Y coordinates back to JSON objects, and then save the updated records back to SharePoint.

Cards on a Corkboard

The first thing I'll do is style the cards and display them with absolute position. While I'm at it I'll also reference the draggable jQuery UI plugin. If you're following along at home just built a custom .js download from the jQuery UI site, drop it in your layouts directory and add a reference. So my PageHead content control now looks like this:

<asp:content
    id="PageHead"
    contentplaceholderid="PlaceHolderAdditionalPageHead"
    runat="server">

    <script type="text/javascript"
        src="../ajax/MicrosoftAjax.js"></script>
    <script type="text/javascript"
        src="../ajax/MicrosoftAjaxDataContext.js"></script>
    <script type="text/javascript"
        src="../ajax/MicrosoftAjaxTemplates.js"></script>
    <script type="text/javascript"
        src="../ajax/MicrosoftAjaxAdoNet.js"></script>
    <script type="text/javascript"
        src="../jquery-ui-1.8.custom/js/jquery-1.4.2.min.js"></script>
    <script type="text/javascript"
        src="../jquery-ui-1.8.custom/js/jquery-ui-1.8.custom.min.js">
    </script>
    <style type="text/css">
        .sys-template
        {
            display: none;
        }
        .userstorycard
        {
            border: 1px solid #777777;
            width: 200px;
            position: absolute;
            cursor: move;
        }
        .carddescription
        {
            font-size: 13px;
            background-image: url('card_bg.jpg');
            padding: 0px 5px 5px 5px;
        }
        .cardtitle
        {
            font-size: 15px;
            font-weight: bold;
            padding: 0px 0px 0px 0px;
            border-bottom: 1px solid red;
            background-color: White;
            padding: 0px 5px 0px 5px;
        }

        ...

The next thing to do is add X and Y fields to the user story list in SharePoint. And finally display the cards with absolute positioning:

<div xmlns:sys="javascript:Sys" class="background">
  <div id="userStories" class="sys-template">
    <div class="userStoryCard"
      sys:style="{{ 'left: ' + X + 'px; top: ' + Y + 'px;'}}">

      <div class="userStoryTitle">{{ Title }}</div>
      <div class="userStoryBody"><div>{{ Description }}</div>
    </div>
  </div>
</
div>

Notice the sys:style attribute. The sys: part is the namespace you need to add for attributes when using templating that I mentioned in part three. Also notice the JavaScript string concatenation inside the binding. You can put in any JavaScript in there that you like. So now if you manually set X and Y values in SharePoint for a card the card shows in the right place. But we're still missing the ability to drag cards.

Making Cards Draggable with jQuery

In order to enable dragging support you're supposed to call the draggable() function on the DOM elements you want to make draggable. Simple right? You just call $(".userstorycard").draggable() which should find every element with a class of userstorycard and call draggable() on it.

But if you do this onLoad() then ASP.Net AJAX Templating engine hasn't had a chance to render the new DOM elements yet. Fortunately the DataView has the JavaScript equivalent of an OnRendered event that you can tie into:

function onLoad() {
    dataContext = $create(
        Sys.Data.AdoNetDataContext,
        { serviceUri: "/demoprep/_vti_bin/ListData.svc" }
        );

    dataView = $create(
        Sys.UI.DataView,
        {
            autoFetch: true,
            dataProvider: dataContext,
            fetchOperation: "UserStories",
            fetchParameters: { $top: 20 }
        },
        {
            rendered: onRendered
        },
        null,
        $get('userStories')
    );
}

function onRendered() {
    // from http://jqueryui.com/demos/draggable/
    $(".userstorycard").draggable();
}

And that's it for enabling dragging. Pretty simple. The result looks like this:

Ok, well you can't see the dragging support, but it's there, trust me. And it's pretty cool except for one thing.

Saving Non-Visible Properties

The problem is that every time you refresh the page the nice layout you've done disappears and everything goes back to being stacked one on top of the other in the upper left. My first thought was to create input type=hidden form elements on the page. This approach causes a lot more plumbing code than is necessary. The better way is that you can access the underlying in-memory JSON objects. Step one is to register an "event" for when the user stops dragging a card.

function onRendered() {
    // from http://jqueryui.com/demos/draggable/
    $(".userstorycard").draggable({
        stop: onDragStop
    });
}

Once you wire that up the onDragStop() function is where all the interesting stuff happens:

function onDragStop(event, ui) {
    var userStoryCard = ui.helper[0];
    var selectedUserStoryJsonObject =
        dataView.findContext(userStoryCard).dataItem;

    var newX = ui.position.left;
    var newY = ui.position.top;

    Sys.Observer.setValue(selectedUserStoryJsonObject, "X", newX);
    Sys.Observer.setValue(selectedUserStoryJsonObject, "Y", newY);
    dataContext.saveChanges();
}

The first line gets the DOM element that just the user just completed dragging. The second line retrieves the in memory JSON object represented by that DOM element. The next couple of lines get the X and Y that the user story card was dragged to relative to their parent DOM element. And then something odd happens.

Sys.Observer.setValue looks so complicated. Why couldn't we just call selectedUserStoryJsonObject.X = newX?

Well, if we'd done that the DataView wouldn't know about the change we just made. If we then tried to call dataContext.saveChanges() nothing would get sent back to the server. Sys.Observer.setValue notifies any interested parties, in this case the DataView, that a value has been changed. And this enables the functionality we saw in part two where the DataView only sends the relevant records back to SharePoint instead of the entire set of JSON objects.

And so, with this code in place, we can now move user story cards around on the page and when we refresh the page or come back days later our layout has persisted back into SharePoint.

Conclusion

In this post you've seen how to directly modify the in-memory JSON objects and send them back to SharePoint. Our application is finally getting interesting and I find it quite remarkable how little code it's taken. In the next post I'll show how to do master-detail scenario's for editing user story cards.