Sunday 1 November 2009

MVC How Cool Is That?!

Possibly one of the coolest things to happen to ASP.NET in the last year is the MVC, which stands for Model View Controller which are the three main elements to this new technology. The first thing that strikes me about MVC is the efficiency of it. With very little work a developer can put together web applications which would have taken much more effort with standard ASP.NET.

Model
Most developers are now used to building a data access layer for their applications. The 'Model' part of the MVC is just this. My personal preference is to use Linq to SQL here in pretty much exactly the same way as I've been doing since Linq emerged. It seems slightly off topic to go into this further as building a data access layer for use in MVC is exactly the same as building a data access layer for any ASP.NET application. The one difference is that all your model classes should reside inside the 'Model' folder which is located in the root of the application. If you're using Visual Studio and have created a new MVC project, the Model folder should have been created for you.

When you need to access methods from these classes you must reference them in exactly the same way as you would do normally in .NET development.

View
The view is the actual .aspx page which is loaded in the browser. To make things a little clearer, lets assume we're dealing with a part of an application managing user information. By default we can choose from several view templates intended to represent CRUD screens (Create, Read, Update and Delete). These pages are intended to have a minimal amount of code in them - just enough to display whatever data is required. Data can be passed to the view as either ViewData (which is used in a similar way to ViewState, eg. ViewData["Employees"]) or by generating a strongly typed View and passing an object directly to it. The code for doing either of these things is in the Controller which I'll cover below.

A view can have a master page, which can in turn have many other master pages, just like in ASP.NET. Probably the most distinctive thing about a View is how data is rendered to the page.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<div>
<%= Html.Encode(ViewData["Employees"]) %>
</div>

Here we see a very basic example of displaying some data from the ViewData which could have been passed to the page from a Controller. What's of note is that the output is entered in-line which although not unusual for ASP.NET, is very much the main mode of controlling output to the page within MVC. Here's an example of adding data to the screen using strongly typed View.

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable
<MvcApplication1.Models.Movie>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Index
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Index</h2>
<table>
<tr>
<th></th>
<th>
Id
</th>
<th>
Title
</th>
<th>
Director
</th>
<th>
DateReleased
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new { id=item.Id }) %> |
<%= Html.ActionLink("Details", "Details", new { id=item.Id })%>
</td>
<td>
<%= Html.Encode(item.Id) %>
</td>
<td>
<%= Html.Encode(item.Title) %>
</td>
<td>
<%= Html.Encode(item.Director) %>
</td>
<td>
<%= Html.Encode(String.Format("{0:g}", item.DateReleased)) %>
</td>
</tr>
<% } %>
</table>
<p>
<%= Html.ActionLink("Create New", "Create") %>
</p> </font>
</asp:Content>


Notice how MVC relies much more on writing ACTUAL HTML as opposed to dragging server controls onto the page and tying them into a code behind page. For many of us this is a welcome return to the nuts and bolts of what the internet is all about.

It is also possible to generate HTML output directly from HtmlHelper classes which can be called directly from the page. In this way the way the page is built is turned on its head; instead of writing code behind to insert controls into place holders we're calling the class which will return the required XHTML directly from the location we want to use it. For developers who remember the days of classic asp this will be familiar ground.

Controller
A Controller is the thing which accepts your web request and builds the response using Models and Views. Below is an example of a Controller with two actions, both returning different Views.
namespace MVCApp.Controllers
{
public class ItemController : Controller
{
//
// GET: /Item/
public ActionResult Index()
{
// Add action logic here
return View();
}

//
// GET: /Item/Detail/4
public ActionResult Detail(int? id)
{
if(!id.HasValue)
RedirectToAction("Index");

return View(model.getDetailFromID(id));
}
}
}



This Controller has two actions, Index() and Detail(). The views which this Controller maps to MUST be in the folder \Views\Item\ in the root of the application. There is nothing else but the name of the controller mapping this controller to the Item folder so it is essential that the controller is named correctly. Also, it must be suffixed with the word 'Controller' otherwise it will not work.

The View() referenced in the Index() Action is the file \Views\Item\Index.aspx and the View referenced by the Detail() Action is \Views\Item\Detail.aspx. The only thing linking these Actions to the Views is the name, so again this is critical to the operation of the application.

Index() simply returns the Index view without passing any data to it. The Detail() action, however, pulls data from the modal and passes it to the Detail View which can access the data as in the strongly typed view example above (foreach (var item in Model)...).

An action can be accessed by a Form Post, an AJAX call or both. If an action is called using AJAX then it's most likely you'll want to return a PartialView rather than a full View. A partial view should map to a .ascx file in the relevant Views folder. You could also return JSON instead of HTML. In fact there are several different types of data which can be returned as an ActionResponse. You'll find excellent coverage of Actions and what can be included in an ActionResponse here.

Templates
Finally I want to mention the templates which can be found below the Common7 folder of Visual Studio (have a search for a folder called MVC). When a new View is generated, the developer is asked to choose what template is used. By default the templates listed in this folder are offerred up as options. Copying the Templates folder into the root of your application will override the default options and allow you to generate your own templates based on the original ones. In order for your application to build however, you must first set the Build Behaviour of the templates to 'None'.

Although the templates are not particularly well advertised, for larger projects these will undoubtedly become more important. It should be noted that once a View or Controller (both can be templated) has been generated from a template, altering the template will not alter the generated file. This means it's important to set up your templates before generating files. It's also important to understand that these do not replace Master Pages. Templates should only control the bare minimum amount of markup required to output data to the page in a usable format.

This has really been a very brief overview of MVC. Some excellent tutorials can be found at http://www.asp.net/learn/mvc/ (the examples here originated there) and Scott Hanselman has made a must see video at http://www.asp.net/learn/mvc-videos/video-7093.aspx. Scott's Nerdinner video is the perfect place for experienced developers to start with MVC, I can't recommend it enough.


Wednesday 9 September 2009

Preventing Page Navigation While an AJAX Queue is Working

AJAX is quick. As internet technologies go, it's as fast a server call as you're likely to make. This having been said, it's not instantaneous. While the callback is occurring there is plenty of time for your users to do stuff you'd rather they didn't, such as navigating away from the page or closing the browser altogether. If you've implemented a good, scalable AJAX solution for your custom calls and built a queuing object, then there might even be server calls which haven't been initiated by the time the user decides to move onto the next screen in your application.

There is a solution to this problem. The following method takes care of processing links while making sure that an AJAX queue has finished running.

function doNav(path)
{
    if(ajaxQueue.running)
    {
        setTimeout('doNav(path)', 50);
    }
    else window.location = path;
}

This method assumes that the queue object is called ajaxQueue and this has a boolean property named 'running'. The reason we call setTimeout is because JavaScript isn't threaded in the same way as some server side languages. If you don't call setTimeout and instead call doNav with direct recursion, the script engine will enter an infinite loop as the thread will never allow the queue processing time to complete its task. The call to setTimeout here will cause the thread to let other things to get on with their job for 50 milliseconds and then, once the script engine completes the task it is currently running (setTimeout doesn't exactly time the process by 50 ms, it does guarantee a minimum of 50 ms however) doNav will be fired again.

Directing all page navigation in your AJAX application through a method like doNav will help make your application more robust and reliable.



Tuesday 26 May 2009

Copying Hierarchical Data with Transient Links

This problem came up in a current project. Initially the problem appears quite straight forward but it’s actually quite tricky. Let’s start by explaining what I mean by transient links in hierarchical data.

In the original project, I was working with a hierarchy of 5 levels but I think we can simplify that a little and work with just 3. For argument’s sake lets use ‘Document, ‘Section’ and ‘Paragraph’ as the three levels. Although blatantly contrived, this structure could possibly be used in a system managing changes to documents.

Figure 1
Figure 1

Figure 1 shows a very simple data structure for this situation. Documents are made up of Sections which are made up of Paragraphs. In this system any of our three entities can be copied by creating a new record with the LInkedToID field referencing the Primary Key for the original record. If a Section record is copied, then new Paragraph records are also generated which are copies of the original Section’s Paragraphs. Similarly, if a Document record is copied then its Sections and Paragraphs are also copied.

The first sign of this getting tricky is encountered when we add in the next requirement: when a Section record is copied, the new Paragraph records shouldn’t all link back to where they were copied from – the new records should generate a copy of the same structure of copied Paragraphs which were in the original Section. The root record for the new structure of Paragraphs should reference the original root Paragraph record. Figure 2 contains some XML formatted data showing how the Paragraph records of a parent Section and it’s copy would relate to each other.

Figure 2.
<Paragraph>
    <ParagraphID>1</ParagraphID>
    <SectionID>1</SectionID>
    <LinkedToID>null</LinkedToID>
    <Text>This is the text for paragraph 1</Text>
</Paragraph>
<Paragraph>
    <ParagraphID>2</ParagraphID>
    <SectionID>1</SectionID>
    <LinkedToID>1</LinkedToID>
    <Text>This is text for paragraph 1 which has been re-versioned.</Text>
</Paragraph>
<Paragraph>
    <ParagraphID>3</ParagraphID>
    <SectionID>1</SectionID>
    <LinkedToID>2</LinkedToID>
    <Text>This is the text for paragraph 1 which has been re-versioned a second time.</Text>
</Paragraph>
<Paragraph>
    <ParagraphID>4</ParagraphID>
    <SectionID>2</SectionID>
    <LinkedToID>1</LInkedToID>
    <Text>This is the text for paragraph 1 in the copied section.</Text>
</Paragraph>
<Paragraph>
    <ParagraphID>5</ParagraphID>
    <SectionID>2</SectionID>
    <LinkedToID>4</LinkedToID>
    <Text>This is the first revision of the paragraph in the copied section.</Text>
</Paragraph>
<Paragraph>
    <ParagraphID>6</ParagraphID>
    <SectionID>2</SectionID>
    <LinkedToID>5</LinkedToID>
    <Text>This is the second revision of the paragraph in the copied section.</Text>
</Paragraph>

In the Figure 2 scenario, Section 1 is made up of a single Paragraph which has been revised twice. Section 2 is a revision of Section 1, so the root Paragraph references the root Paragraph of Section 1 while the other Paragraphs of Section 2 link back to Section 2’s root Paragraph.

The requirement is for this pattern to apply for all levels. So if a Document is copied then the Sections will be copied maintaining the references. Likewise, each Section copied to the new Document would also have their Paragraphs generated with the same linked structure of their parent Paragraphs in the original Document.

Now we have some understanding of what I mean by transient links in hierarchical data. Copying data in this way might seem quite simple. In fact initially I thought it was a no brainer and wrote a method similar to the one in Figure 3.

Figure 3.
public void CopyDocument(Document doc)
{
    var newDoc = new Document
        {
            Name = String.Concat(“Copy of “, doc.Name),
            LinkedToID = doc.DocumentID
        };
    dataContext.Document.InsertOnSubmit(newDoc);
    dataContext.SubmitChanges();

    var sections = dataContext.Section.Where(s=>s.DocumentID==doc.DocumentID);

    foreach(var section in sections)
    {
        var newSection = new Section
            {
                DocumentID = newDoc.DocumentID,
                LinkedToID = section.SectionID,
                Text = section.Text
            } ;
        dataContext.Section.InsertOnSubmit(newSection);
        dataContext.SubmitChanges();

        var paragraphs = dataContext.Paragraph.Where(p=>p.SectionID==section.SectionID);

        foreach(var paragraph in paragraphs)
        {
            var newParagraph = new Paragraph
                {
                    SectionID = newSection.SectionID,
                    LinkedToID = paragraph.ParagraphID,
                    Text = paragraph.Text
                };
            dataContext.Paragraph.InsertOnSubmit(newParagraph);
            dataContext.SubmitChanges();
        }
    }
}

At first glance this might look like it could do the job but in fact this would link each new record back to the record it was copied from rather than maintaining the original structure.

So how is it done?

The example in Figure 2 is pretty simple. For that situation, the LinkedToID could be followed back to the root Paragraph record and then the children created one at a time pointing to the new root record and the first child respectively. Unfortunately this is a hugely oversimplified example. In actuality the root record may have already been copied into several other Section records already, and have other children which are linked via the LinkedToID but shouldn’t be copied in this process. What’s more, we may not always be copying a root node!

To accomplish the task, we need to introduce two new fields into each entity: ProcessID and CopiedFromID (I would normally use ProcessGuid instead of ProcessID but typing out a guid in a blog is tedious so an integer field will suffice here). Figure 4 contains C# code to accomplish this.

Figure 4.
public void CopyDocument(Document doc)
{
    // GetNewProcessID() is a method which returns an
    // integer which hasn’t been used as a ProcessID yet.
    var processID = GetNewProcessID();

    var thisDoc = document;
    CopyDocumentMaintainingLinks(thisDoc, processID);

    var originalSections = dataContext.Section.Where(s=>
        s.DocumentID==doc.DocumentID);
    foreach(var section in originalSections)
    {
        var thisSection = section;
        CopySectionMaintainingLinks(thisSection, 
            thisSection.SectionID, processID);

        var originalParagraphs = dataContext.Paragraph
            .Where(p=>p.SectionID==thisSection.SectionID);

        foreach(var paragraph in originalParagraphs)
        {
            var thisParagraph = paragraph;
            CopyParagraphMaintainingLinks(thisParagraph,
                thisParagraph.ParagraphID, processID);
        }
    }
}

public void CopyDocumentMaintainingLinks(Document doc,
    int linkedToID, int processID)
{
    var newDoc = new Document
        {
            Name = String.Concat(“Copy of “, doc.Name),
            LinkedToID = linkedToID,
            CopiedFromID = doc.DocumentID,
            ProcessID = processID
        };

    dataContext.Document.InsertOnSubmit(newDoc);
    dataContext.SubmitChanges();

    var linkedDocuments = dataContext.Document
        .Where(d=>d.LinkedToID == doc.DocumentID);
    foreach(var document in linkedDocuments)
    {
        var thisDoc = document;
        CopyDocumentMaintainingLinks(thisDoc,
            newDoc.DocumentID, processID);
    }
}

public void CopySectionMaintainingLinks(Section section, 
    int linkedToID, int processID)

    var newParentDocument = dataContext.Document
        .SingleOrDefault(d=>
        d.CopiedFromID == section.DocumentID &&
        d.ProcessID == processID);

    var newSection = new Section
        {
            LinkedToID = linkedToID,
            CopiedFromID = section.SectionID,
            Text = section.Text,
            DocumentID = newParentDocument.DocumentID,
            ProcessID = processID 
        };
    dataContext.Section.InsertOnSubmit(newSection);
    dataContext.SubmitChanges();

    var linkedSections = dataContext.Section.Where(s=>
        s.LinkedToID==section.SectionID
        && s.DocumentID==section.DocumentID);
   
    foreach(var section in linkedSections)
    {
        var thisSection = section;
        CopySectionMaintainingLinks(thisSection, 
            newSection.SectionID, processID);
    }
}

public void CopyParagraphMaintainingLinks(
Paragraph paragraph, int linkedToID, int processID)
{
    var newParentSection = dataContext.Section
        .SingleOrDefault(s=>
        s.CopiedFromID == paragraph.SectionID &&
        s.ProcessID == processID);

    var newParagraph = new Paragraph
        {
            SectionID = newParentSection.SectionID,
            LinkedToID = linkedToID,
            Text = paragraph.Text,
            CopiedFromID = paragraph.ParagraphID,
            ProcessID = processID
        };
    dataContext.Paragraph.InsertOnSubmit(newParagraph);
    dataContext.SubmitChanges();

    var linkedParagraphs = dataContext.Paragraph
        .Where(p=>p.LinkedToID == paragraph.ParagraphID &&
        p.SectionID == paragraph.SectionID);

    foreach(var para in linkedParagraphs)
    {
        var thisParagraph = para;
        CopyParagraphMaintainingLinks(thisParagraph,
            newParagraph.ParagraphID, processID);
    }
}

The method CopyDocument is pretty straight forward, the fun bits are in the other three methods. Because the target parent object isn’t necessarily known, we have to find it using the CopiedFromID and the ProcessID fields we added earlier. In this way there are two types of transient relationships defined: linked records and copied records. Of course, a record might be copied dozens of times which means the ProcessID field is needed to restrict the scope of the query to just this copy process.

Another possible pit fall is when selecting the linked items. Because of the way things are copied, we’re only interesting in copying Sections which are in the source Document and for each individual Section we don’t need to copy linked Paragraphs from outside that Section. So we can constrain the query as so.

It’s worth  noting that this technique will continue to work no matter how many levels of data exist. Originally I was using 5 levels but there are certainly applications for this technique using more than this. It’s also worth noting that although I’ve written these methods out ‘long hand’ if you like, it would be possible to write a single method to handle all data levels as long as the classes implemented an interface defining the ID, LinkedToID, CopiedFromID and ProcessID fields. This slightly more complex recursive method would need to use reflection to determine what level of data was being copied in any given iteration in order to create the new record.

That’s pretty much all I have to say on this subject. I thought it was an interesting problem which I couldn’t find a solution for elsewhere on the web (although I’m sure they’re out there).

NB: I didn’t copy the code directly from my project so don’t expect it to work perfectly after a copy and paste.

Tuesday 12 May 2009

New Website

Finally my website is available!

If you’re looking for a company software development services you might want to consider contacting me. All details are on my site: www.e-netservices.co.uk.

Friday 13 March 2009

AJAX DIY

It’s been a long time between blogs and a very busy start to the year for me. One of my clients has some pretty hefty requirements for a web based, SQL Server backed, SharePoint integrated production system to be accessible world wide via their less than super fast WAN. I’ve been kept very busy and I’m yet to hit the really tricky bits.

Whilst designing and building this system, I’ve found myself writing a lot of bespoke AJAX. I’m used to working on a fast company LAN so I’ve always talked about AJAX as being an efficient use of bandwidth. I now had my eyes opened to just how badly conceived some AJAX frameworks actually are. For example, Microsoft’s AJAX control toolkit offers a wide range of easy to use components but partial page renderings often end up costing as much (if not more) in bandwidth as a full page refresh! This is something which I was only vaguely aware of until I tried running my AJAX pages from an office in Shenzhen!

It quickly became obvious that Microsoft’s AJAX tools weren’t up the job at hand so I had a look at what else was out there. There are some excellent toolkits available, Telerik's RAD Controls are undoubtedly one of the best with some very flashy looking elements and some very good reviews (from people I know as well as on their site). But though they are more efficient than the Microsoft tools, I would still have had to work extensively to craft the feature rich GUI which my client was looking for. In my mind it seems silly to pay for something which ultimately isn’t going to save time or increase the value of the build. Also, even the Telerik controls had performance problems in the environment in question.

This was when I started thinking back many years to a time before .NET, when possibly the most powerful tool in a web developer’s arsenal was their knowledge of JavaScript. I spent quite a few years making the DOM dance to my tune long before I discovered asp.NET and server controls. There are so many AJAX ‘helper’ kits out there that it’s easy to forget how straight forward an AJAX call is to make. In fact, over the last few months I’ve realised that much of what is provided by these tools is pretty straight forward to code yourself.

My message to any developer is this:

Don’t automatically think that because something is available for download and looks flashy that it will make your application better / quicker / smarter. Just because something is for sale doesn’t make it any better than what you could build yourself. Think about what your client REALLY needs and how much work it would take both with or without 3rd party kit. You might just find that you’re quite capable of going it alone!