Blog Archives

Using jQuery with Client-Side Data Binding Templates

A few weeks back I posted about a JavaScript data binding template solution that I’ve been using that makes it easy to bind JSON data to a client-side template without having to write a lot of JavaScript code.  One of the people that commented on that post asked if I could put together a sample that demonstrated the templates in action.  It took me a few weeks to get to it, but I finally made some time to put a sample together that demonstrates the fundamentals of using the client-side templates and binding JSON data to them.  As a review (in case you didn’t read my earlier post), the template solution I’ve been using recently on a client project is based on some code written by John Resig (creator of jQuery) which is extremely compact.  Here’s a tweaked version of his original code that I wrapped with a jQuery extender function (credit goes to Rick Strahl as well for a few tweaks he added):

$.fn.parseTemplate = function(data)
{
    var str = (this).html();
    var _tmplCache = {}
    var err = "";
    try
    {
        var func = _tmplCache[str];
        if (!func)
        {
            var strFunc =
            "var p=[],print=function(){p.push.apply(p,arguments);};" +
                        "with(obj){p.push('" +
            str.replace(/[rtn]/g, " ")
               .replace(/'(?=[^#]*#>)/g, "t")
               .split("'").join("\'")
               .split("t").join("'")
               .replace(/<#=(.+?)#>/g, "',$1,'")
               .split("<#").join("');")
               .split("#>").join("p.push('")
               + "');}return p.join('');";

            //alert(strFunc);
            func = new Function("obj", strFunc);
            _tmplCache[str] = func;
        }
        return func(data);
    } catch (e) { err = e.message; }
    return "< # ERROR: " + err.toString() + " # >";
}

The parseTemplate method can be applied against a client-side template like the one below.  Notice that the template is wrapped in a script block with the type set to text/html so that it isn’t rendered by the browser.  JSON properties are written out by using the <#= …  #> syntax and the template engine has full support for embedded JavaScript code.

<script id="MyTemplate" type="text/html">
    <table style="width:400px;">
        <thead>
            <tr>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Address</th>
            </tr>
        </thead>
        <tbody>
        <#
            for(var i=0; i < d.length; i++)
            {
               var cust = d[i];
        #>
                <tr>
                   <td id="CustomerRow_<#= i.toString() #>">
                        <#= cust.FirstName #>
                   </td>
                   <td>
                        <#= cust.LastName #>
                   </td>
                   <td>
                      <#= cust.Address.Street #>
                      <br />
                      <#= cust.Address.City #>, <#= cust.Address.State #>
                      &nbsp;&nbsp;<#= cust.Address.Zip #>
                   </td>
                </tr>
        <#
            }
        #>
        </tbody>
    </table>
    <br />
    <#= d.length #> records shown
</script>

This template outputs a simple table like the one shown next.  Sure, I could’ve generated the table using DOM manipulation techniques, but being able to tweak a data template is much easier and productive in my opinion.

image


In order to use the template you’ll need to have some JSON data available.  Here’s an example of creating JSON by hand and binding it to the template using the parseTemplate method shown earlier.  The data returned from the template data binding operation is passed to the html method of the target div which displays the data in the browser.  Note:  I’m defining the “d” property in the JSON object since WCF uses that name by default when it returns serialized JSON data.

var json =
        {
            "d":
            [
               { "FirstName": "John", "LastName": "Doe",
                 "Address":
                  { "Street": "1234 Anywhere St.", "City": "Phoenix",
                    "State": "AZ", "Zip": 85044 }
               },
               { "FirstName": "Jane", "LastName": "Doe",
                   "Address":
                  { "Street": "435 Main St.", "City": "Tempe",
                    "State": "AZ", "Zip": 85245 }
               },
               { "FirstName": "Johnny", "LastName": "Doe",
                 "Address":
                  { "Street": "643 Chandler Blvd", "City": "Chandler",
                    "State": "AZ", "Zip": 85248 }
              },
               { "FirstName": "Dave", "LastName": "Doe",
                 "Address":
                  { "Street": "18765 Cloud St.", "City": "Mesa",
                    "State": "AZ", "Zip": 85669 }
               }
            ]
        };
var output = $('#MyTemplate').parseTemplate(json);
$('#MyTemplateOutput').html(output);

Of course, in the real-world you’ll probably get the JSON data from some type of service (WCF, ASMX, REST, etc.).  Here’s a WCF service that returns a List of Customer objects and converts them to JSON.  The service has the client script behavior enabled so that serialization from CLR objects to JSON objects occurs behind the scenes automatically.

[ServiceContract(Namespace = "http://www.thewahlingroup.com")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class CustomerService
{
    [OperationContract]
    public List<Customer> GetCustomers()
    {
        return new List<Customer>
        {
            new Customer {FirstName="John",LastName="Doe",
                          Address=new Address{Street="1234 Anywhere St.",City="Phoenix",State="AZ", Zip=85044}},
            new Customer {FirstName="Jane",LastName="Doe",
                          Address=new Address{Street="435 Main St.",City="Tempe",State="AZ", Zip=85245}},
            new Customer {FirstName="Johnny",LastName="Doe",
                          Address=new Address{Street="643 Chandler Blvd",City="Chandler",State="AZ", Zip=85248}},
            new Customer {FirstName="Dave",LastName="Doe",
                          Address=new Address{Street="18765 Cloud St.",City="Mesa",State="AZ", Zip=85669}}
        };
    }

}


jQuery’s ajax method can then be used to call the WCF service and retrieve the data (jQuery provides other methods such as getJSON that could be used too if desired):

$.ajax(
{
    type: "POST",
    url: "CustomerService.svc/GetCustomers",
    dataType: "json",
    data: {},
    contentType: "application/json; charset=utf-8",
    success: function(json)
    {
        var output = $('#MyTemplate').parseTemplate(json);
        $('#MyTemplateOutput').html(output);

        //Add hover capabilities
        $('tbody > tr').bind('mouseenter mouseleave', function()
        {
            $(this).toggleClass('hover');
        });
    }
});

This code defines the type of operation, service URL to call, any data passed to the service, the content type and a success callback.  Once the service call returns, the JSON data is bound to the template shown earlier by locating the area where the template should be rendered to (MyTemplateOutput in this example) and then calling parseTemplate.  Hover capabilities are also added using jQuery’s bind method to highlight rows as the user moves the mouse in and out of them. 

You can see that the amount of custom Javascript that has to be written is kept to a minimum by combining jQuery with the client-side template which ultimately leads to easier maintenance down the road.  This is just one of several different client-side template solutions out there.  ASP.NET 4.0 will also include a custom client-side template solution as well as mentioned in my previous post.

Download the sample code here

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

Minimize Code by Using jQuery and Data Templates

I’m currently working on a heavily AJAX-oriented ASP.NET MVC web application for a business client and using jQuery to call controller actions, retrieve JSON data and then manipulate the DOM to display the data. Several of the pages have quite a bit of dynamic HTML that has to be generated once a JSON object is returned from an MVC controller action which generally leads to a lot of custom JavaScript.  After working through my first page on the project I realized that I was creating a maintenance nightmare due to the amount of JavaScript being written and decided to look into other options.

The first thing I looked for was some type of JavaScript template that would work much like GridView templates in ASP.NET.  I wanted to be able to define a template in HTML and then bind a JSON object against it.  That way I could easily tweak the template without having to actually touch my JavaScript code much.  I found several potential template solutions (and Microsoft will be releasing a nice option with ASP.NET 4.0 as well) that were nice but many were so CSS class centric that they ended up being a turn off since I felt like I had to learn yet another coding style just to use them.  I eventually came across one by John Resig (creator of jQuery and overall JavaScript genius) that was so small that I wasn’t sure it would even be viable.  I mean we’re talking tiny as far as code goes…so tiny that I figured it wouldn’t work well for what I needed.  After doing more searching and research I came across a post by my world famous buddy Rick Strahl (if you don’t currently follow his blog you won’t find a better one out there IMHO) that mentioned John’s micro template technique and had a few tweaks in it.  I tried it and was instantly hooked because it gave me the power to use templates yet still embed JavaScript to perform basic presentation logic (loops, conditionals, etc.) as needed.

The Template Engine (chipmunk power)

So here’s how the template works.  The first thing I did was add the template function as a jQuery extension so that I could get to it using familiar jQuery syntax.  This isn't required at all, it’s just something I wanted to do.  I ended up going with Rick’s slightly tweaked version and I only changed how the error was reported.  I’m not going to go into how to extend jQuery in this post, but here’s what the extension function looks like:

$.fn.parseTemplate = function(data)
{
    var str = (this).html();
    var _tmplCache = {}
    var err = "";
    try
    {
        var func = _tmplCache[str];
        if (!func)
        {
            var strFunc =
            "var p=[],print=function(){p.push.apply(p,arguments);};" +
                        "with(obj){p.push('" +
            str.replace(/[rtn]/g, " ")
               .replace(/'(?=[^#]*#>)/g, "t")
               .split("'").join("\'")
               .split("t").join("'")
               .replace(/<#=(.+?)#>/g, "',$1,'")
               .split("<#").join("');")
               .split("#>").join("p.push('")
               + "');}return p.join('');";

            //alert(strFunc);
            func = new Function("obj", strFunc);
            _tmplCache[str] = func;
        }
        return func(data);
    } catch (e) { err = e.message; }
    return "< # ERROR: " + err.toString() + " # >";
}

That’s all the code for the template engine.  Unbelievable really…runs on chipmunk power.

Creating a Template

Once the extension function was ready I had to create a template in my MVC view (note that this works fine in any web application, not just ASP.NET MVC) that described how the JSON data should be presented.  Templates are placed inside of a script tag as shown next (I chopped out most of the template to keep it more concise). 

<script id="MenuSummaryTemplate" type="text/html">
     <table style="width:100%;">
        <tbody>
            <tr>
                <td class="OrderHeader">Totals:</td>
            </tr>
            <tr>
                <td style="font-size:12pt;">
                    <table style="width:400px;">
                        <tr>
                            <td style="width:50%;">Sub Total:</td>
                            <td>$<span id="FinalSubTotal"><#= FinalSubTotal #></span></td>
                        </tr>
                        <tr>
                            <td>Sales Tax:</td>
                            <td>$<span id="FinalSalesTax"><#= FinalSalesTax #></span></td>
                        </tr>
                        <# if (DeliveryFee > 0) { #>
                        <tr>
                            <td>Delivery Fee:</td>
                            <td>$<span id="DeliveryFee"><#= DeliveryFee #></span></td>
                        </tr>
                        <# } #>
                        <tr>
                            <td>Admin Fee:</td>
                            <td>$<span id="AdminFee"><#= AdminFee #></span></td>
                        </tr>
                        <tr style="border-top:1px solid black;">
                            <td>Total:</td>
                            <td>$<span id="FinalTotal"><#= FinalTotal #></span></td>
                        </tr>
                        <tr>
                            <td colspan="2">&nbsp;</td>
                        </tr>
                        <tr>
                            <td colspan="2">Will be charged to your credit card ending with <#= CreditCard #></td>
                        </tr>
                    </table>
                </td>
            </tr>           <!-- More of the template would follow -->
        </tbody>
    </table>
</script>

You can see that the script block template container has a type of text/html and that the template uses <#=  #> blocks to define placeholders for JSON properties that are bound to the template. The text/html type is a trick to hide the template from the browser and I suspect some may not like that…you’re call though…I’m just showing one option.  The template supports embedding JavaScript logic into it which is one of my favorite features. 

After a little thought you may wonder why I didn’t simply update the spans and divs using simple JavaScript and avoid the template completely.  By using a template my coding is cut-down to 2 lines of JavaScript code once the JSON object is created (which you’ll see in a moment) and this is only part of the template. Here’s another section of it that handles looping through menu items and creating rows:

 

<#
   if (MainItems == null || MainItems.length == 0)
   {
#>
    <tr>
        <td>No items selected</td>
    </tr>
<#
   }
   else
   {
       for(var i=0; i < MainItems.length; i++)
       {
         var mmi = MainItems[i];
#>
        <tr>
           <td>
                <#= mmi.Name #>:  <#= mmi.NumberOfPeople #> ordered at $<#= mmi.PricePerPerson #> per person
           </td>
        </tr>
<#
       }
   }
#>


Binding Data To a Template

To bind JSON data to the template I can call my jQuery extension named parseTemplate(), get back the final HTML as a string and then add that into the DOM.  Here’s an example of binding to the template shown above.  I went ahead and left the JSON data that’s being bound in so that you could see it, but jump to the bottom of LoadApprovalDiv() to see where I bind the JSON object to the template….it’s only 2 lines of code.

function LoadApprovalDiv()
{
    var subTotal = parseFloat($('#SubTotal').text());
    var salesTaxRate = parseFloat($('#SalesTaxRate').val()) / 100;
    var salesTaxAmount = subTotal * salesTaxRate;
    var deliveryFee = parseFloat($('#DeliveryFee').val());
    var adminFee = (subTotal + salesTaxAmount + deliveryFee) * .05;
    var total = subTotal + salesTaxAmount + deliveryFee + adminFee;
    var deliveryAddress = $('#Delivery_Street').val() + ' ' + $('#Delivery_City').val() +
                          " " + $('#Delivery_StateID option:selected').text() + ' ' + $('#Delivery_Zip').val();
    var creditCard = $('#Payment_CreditCardNumber').val();
    var abbrCreditCard = '*' + creditCard.substring(creditCard.length - 5);

    var json = {
                   'FinalSubTotal'  : subTotal.toFixed(2),
                   'FinalSalesTax'  : salesTaxAmount.toFixed(2),
                   'FinalTotal'     : total.toFixed(2),
                   'DeliveryFee'    : deliveryFee.toFixed(2),
                   'AdminFee'       : adminFee.toFixed(2),
                   'DeliveryName'   : $('#Delivery_Name').val(),
                   'DeliveryAddress': deliveryAddress,
                   'CreditCard'     : abbrCreditCard,
                   'DeliveryDate'   : $('#Delivery_DeliveryDate').val(),
                   'DeliveryTime'   : $('#Delivery_DeliveryTime option:selected').text(),
                   'MainItems'      : GenerateJson('Main'),
                   'SideItems'      : GenerateJson('Side'),
                   'DesertItems'    : GenerateJson('Desert'),
                   'DrinkItems'     : GenerateJson('Drink')
               };

       var s = $('#MenuSummaryTemplate').parseTemplate(json);
       $('#MenuSummaryOutput').html(s);
}


You can see that I call parseTemplate(), pass in the template to use and JSON object and then get back a string.  I then add the string into a div with an ID of MenuSummaryOutput using jQuery.  Here’s a sample of what the template generates:


 image


Going this route cut down my JavaScript code by at least 75% over what I had originally and makes it really easy to maintain.  If I need to add a new CSS style or modify how things are presented I can simply change the template and avoid writing custom JavaScript code.  By using the template and AJAX calls I’ve been able to significantly minimize the amount of server code being written and meet the client’s requirement of having an extremely fast and snappy end user experience.  If you’re writing a lot of custom JavaScript currently to generate DOM objects I’d highly recommend looking into this template or some of the other template solutions out there.  I can’t say I’ve tested performance but can say that I’m working with some fairly large templates which are loading in < 1 second.  I personally feel it’s the way to go especially if you want to minimize code and simplify maintenance.  I think Microsoft’s entry into this area with ASP.NET 4.0 further validates the usefulness of client-side templates.

 

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

Handling MouseEnter and MouseLeave Events in jQuery

I have a simple table generated by an ASP.NET MVC view and needed to switch out CSS classes as the user hovered over rows.  Initially I used the rather obvious “hover” feature built-into jQuery since it provides a way to write code that’s called as the user enters and leaves an object.  I ended up doing something like this:

$(this).closest('tr').hover(
    function()
    {
        $(this).addClass('Over');
    },
    function()
    {
        $(this).removeClass('Over');
});

While this works, I was looking into another scenario today and realized that it’s much easier to do the toggle effect using the jQuery bind() function combined with toggleClass().  Either way works, but I’m all for less code where possible.  Here’s how to achieve the same “hover” effect with less code:

$(this).closest('tr').bind("mouseenter mouseleave", function(e)
{
    $(this).toggleClass("Over");
});


The toggleClass() function automatically handles adding and removing the Over CSS class and the bind() function handles attaching to the mouseenter and mouseleave events.  Nice and clean…

 

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

Selecting Parent Nodes using jQuery

Here’s a quick tip on selecting parent nodes based on something I had to do yesterday with jQuery on a client project.  I have an ASP.NET MVC page that outputs a basic table containing search results and as a user hovers over an item in a map I needed to highlight the appropriate row in the search results by changing its CSS class.  I debated simply adding an ID on the row to make it easy to find but decided I didn’t want to deal with another ID in the DOM.  Here’s what a portion of the view page looks like: 

<tr>
    <td style="width:25%;">
        <span id='restID_<%= rest.RestaurantID %>' desc='<%= addr %>'
          class="Restaurant" lat='<%= rest.Address.Latitude %>' lon='<%= rest.Address.Longitude %>'>
            <%= rest.Name %>
        </span>
    </td>
    <td style="width:55%;">
        <span><%= addr %></span>
    </td>
    <td style="width:20%;">
        <%= Html.ActionLink("View Menu","Details","Menu") %>
    </td>
</tr>

On my first attempt I selected the target row the way I typically would do back in the day with plain old JavaScript (I guess we could call it POJ…those that know about POCO and similar terms will understand :-) ) which is to select the target span, move up to its parent (the td) and then move up to its parent (the tr).  This works fine, but I ended up going with the following to make it more flexible in case other parents nodes were introduced down the road in the HTML:

function PushPinOver(e)
{
    var shape = $(mapObj)[0].map.GetShapeByID(e.elementID);
    if (shape != null)
    {
        //Find restaurant and highlight it
        current = $('#' + shape.RestaurantID);
        current.parents('tr:eq(0)').addClass('Over');
    }
}

Notice that the last line of code uses the parents() method and says to look for the first tr tag parent (eq(0) filters it down to the first parent).  The code is much more flexible compared to what I originally had especially if I decide to add other tags into the table cells.  As the user hovers off of a map item I then call the following code to locate the same tr parent and remove the CSS class:

function PushPinOut(e)
{
    var shape = $(mapObj)[0].map.GetShapeByID(e.elementID);
    if (shape != null)
    {
        //Find restaurant and highlight it
        if (current != null) current.parents('tr:eq(0)').removeClass('Over');
        current = null;
    }
}

jQuery provides a lot of different options for selecting objects which is why I like it so much….selectors rule!  I’ve cut down my JavaScript coding by at least 50-60% I’d guess as a result of using it.

Update: Another way to do this is to use the closest() method: current.closest(‘tr’)… which is even easier and I like it more for my particular scenario.  Thanks to Raj for commenting about that.

5 Reasons You Should Take a Closer Look at ASP.NET MVC

I’m an ASP.NET Web Forms fan…always have been since ASP.NET was first released.  But, I like to keep an open mind when it comes to new technologies and I decided to experiment with the new ASP.NET MVC framework that Microsoft just released so I knew how it could be used with consulting projects and for training my company provides.  I was so impressed with some of the things I could do that I’m now using ASP.NET MVC on a customer project and thought I’d share some of the things I really like about the framework.

Before moving on, I know what some of you are already thinking because I thought the same things: “I don’t need all that testing stuff promoted by MVC people!” or “That’s an overly complex framework for ‘letter of the law’ developers!” or “I can’t use all my familiar ASP.NET server controls!” or “I don’t care about absolute control over the HTML that’s output!”.  I can tell you that while I do believe in unit testing and use it in my ASP.NET Web Forms consulting projects (see my previous post on the subject), I’m far from a letter of the law type developer (opinionated for sure….but not annoyingly opinionated :-) ) and don’t really need absolute control over HTML output in many cases.  However, there are several other reasons why I personally think you should look at ASP.NET MVC and see if it can benefit your projects at all. 

In this post I’m going to outline 5 things I really like about ASP.NET MVC and separation of concerns, unit testing, complete control over HTML, etc. aren’t going to be covered.  If you want those things you get them too so keep that in mind before yelling, “You didn’t mention testing Dan!”.  It’s up to you to create test projects or not and ASP.NET MVC provides a very testable framework if you want to leverage it.  Having said that, let’s get started with a few terms before jumping into the details:

  • Model: Represents data used in the application that’s ultimately retrieved and manipulated using business rule and data access classes (you could/should have these classes in ASP.NET Web Forms as well)
  • View: Handles presenting data to the end user (Similar to an .aspx page in ASP.NET Web Forms)
  • Controller: Retrieves data from the Model and passes it to a View (somewhat analogous to a code-behind page in ASP.NET Web Forms…but quite a bit different in functionality)

Reason #1 – Automatic Mapping of Control Values to Object Properties

I don’t enjoy writing tedious code and am always coming up with ways to minimize and refactor where possible. One of the nicest features in the ASP.NET MVC framework is the built-in ability to automatically map control values to objects.  With ASP.NET Web Forms you find yourself doing the following quite often (although some controls when used with the <%# Bind %> expression can do some mapping too):

protected void btnSubmit_Click(object sender, EventArgs e)
{
    Person p = new Person();
    p.FirstName = FirstName.Text;
    p.LastName = LastName.Text;
    UpdatePerson(p);
}

This is a simple example that can quickly get more complex depending upon the number of controls in your forms.  ASP.NET MVC uses specialized objects called Controllers to serve up pages (called Views) and within a controller class you can write methods (called Actions).  Actions can capture the form data submitted by an end user and automatically map it to custom object properties without you having to write any mapping code as shown above.  For example, consider the following ASP.NET MVC controls defined with a View named EditCustomerProfile (only a portion of the view is shown for the sake of brevity).  To prove I’m not a letter of the law person you’ll see I went with a table here (yeah I know, divs would work too..wasn’t in a div mood today):

<table width="640" cellspacing="5">
    <tr>
        <td style="width:30%"><label for="Customer.FirstName">First Name:</label></td>
        <td style="width:70%">
            <%= Html.TextBox("Customer.FirstName", Model.Customer.FirstName)%>
            <%= Html.ValidationMessage("FirstName", "*")%>
        </td>
    </tr>
    <tr>
        <td><label for="Customer.LastName">Last Name:</label></td>
        <td>
            <%= Html.TextBox("Customer.LastName", Model.Customer.LastName) %>
            <%= Html.ValidationMessage("LastName", "*")%>
        </td>
    </tr>
    <tr>
        <td><label for="Customer.Company">Company:</label></td>
        <td>
            <%= Html.TextBox("Customer.Company", Model.Customer.Company)%>
            <%= Html.ValidationMessage("Company", "*")%>
        </td>
    </tr>
    <tr>
        <td><label for="Customer.Phone">Phone:</label></td>
        <td>
            <%= Html.TextBox("Customer.Phone", Model.Customer.Phone)%>
            <%= Html.ValidationMessage("Phone", "*")%>
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="submit" value="Update Profile" />&nbsp;&nbsp;
            <span class="StatusMessage" style='color:<%= Model.StatusColor %>'><%=Model.StatusMessage %></span>
        </td>
    </tr>
</table>

The first thing you’ll notice is that controls are defined differently in ASP.NET MVC then they are in ASP.NET Web Forms.  That’s a topic for a later post so I’m not going to focus on controls here.  The “classic ASP” style <% tags gave me heartache at first but having built many Views now I actually like the simple syntax for defining controls (no more runat=”server”!).  But…I digress.  Take a look at the ID for each control and notice that they all have “Customer” prefixing the name (Customer.FirstName, Customer.LastName, Customer.Company, etc.).  This is all the mapping code you need.  The method (Action) that handles the posted data simply needs to define a type that has properties that map with the form fields and the mapping happens “automagically”.  You can even customize the mapping if desired or perform mapping using built-in controller methods such as UpdateModel(). 

Here’s what the EditCustomerProfile() method (Action) looks like that handles the posted data.  You can see that it accepts a Customer parameter named customer that will automatically receive the posted control values and update the appropriate values.  The parameter name is key here since that’s what makes the auto-mapping possible (recall that each control was prefixed with “Customer”…case doesn’t matter here).  There’s a lot more that could be said about this particular topic, but this should give you an idea of how the auto-mapping works.  A nice discussion of the different mapping options available in ASP.NET MVC (referred to as ModelBinders) can be found here.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditCustomerProfile(Customer customer)
{
    try
    {
        if (customer.IsCustomerValid)
        {
            OperationStatus opStatus =_CustomerRepository.Update(customer);            if (opStatus.Status)
            {
                ViewData["Status"] = "true";
                return View("EditCustomerForm",
                    new CustomerViewModel(customer,"Navy","Your profile information was saved."));
            }
        }
    }
    catch
    {         //Log
    }
    ViewData["Status"] = "false";
    ModelState.AddModelErrors(customer.GetRuleViolations());
    return View("EditCustomerForm", new CustomerViewModel(customer, "Red", "There was a problem updating your profile."));
}

Reason #2: Automatic Generation of Views

Views display the data given to them by Controllers as mentioned earlier.  If you have a strongly-typed object (such as Customer above) that you will be passing to a View, Visual Studio can automatically generate the View for you and even add the controls that map to the respective object properties that will be bound as well as validation controls (although you’ll have to write the code to actually do the validation).  When creating Views using the IDE you can use the following Add View window:

image

This saves a tremendous amount of time defining controls.  It also save times in mapping control IDs to object properties.  If you don’t like the default code that’s output you can change the templates or add new custom templates.  They’re located at C:Program FilesMicrosoft Visual Studio 9.0Common7IDEItemTemplatesCSharpWebMVCCodeTemplates by default.  For example, if you prefer tables for your forms you could tweak one of the template files such as Edit.tt as shown next:

        <fieldset>
            <legend>Fields</legend>
               <table style='width:100%;'>
<#
    foreach(KeyValuePair<string, string> property in properties) {
#>
                    <tr>
                        <td style='width:30%'>
                            <label for='<#= property.Key #>"><#= property.Key #>:</label>
                        </td>
                        <td style='width:70%'>
                            <%= Html.TextBox('<#= property.Key #>", <#= property.Value #>) %>
                            <%= Html.ValidationMessage("<#= property.Key #>", "*") %>
                        </td>
                    </tr>
<#
    }
#>

                    <tr>
                        <td colspan="2">
                            <input type="submit" value="Save" />
                        </td>
                    </tr>
                </table>
        </fieldset>

    <% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

Reason #3: UpdatePanel-Like AJAX Support – But on a Serious Diet

If you use AJAX in your applications and are fond of the UpdatePanel control in ASP.NET Web Forms (some like it…some hate it) you may be aware that it can transmit a lot of data during an asynchronous postback (ViewState, ControlState, etc.) if you’re not careful.  ASP.NET MVC has built-in AJAX support as well and is just as easy to use.  You can create forms that perform partial-page updates and you don’t even have to work hard to do it.  Here’s an example of using the AjaxHelper to do the equivalent of an UpdatePanel.
 

<% using (Ajax.BeginForm("EditCreditProfile", new AjaxOptions { UpdateTargetId = "CreditForm", OnSuccess = "onEditOfficeProfileSuccess" }))
   {
%>
    <div id="CreditForm">
        <% Html.RenderPartial("EditCreditForm",Model.CreditProfileViewModel); %>
    </div>
<% } %>


The Ajax.BeginForm() call says that when the form is submitted (the form controls are defined in an EditCreditForm View User Control) a Controller Action named EditCreditProfile should be called asynchronously.  When the call returns the div with an id of CreditForm will be updated automatically with the resulting data.  This sends significantly smaller payloads as compared to the UpdatePanel which is nice when you need that type of functionality. 

Built-in support for adding AJAX functionality to links is also available in ASP.NET MVC through the AjaxHelper.  Check out the ActionLink() method if you’re interested in hooking a link to an Action using AJAX techniques.

Reason #4: Integration with Other JavaScript Libraries such as jQuery

image I mentioned earlier that I don’t always care about having complete control over the exact HTML that is output as long as it’s valid.  However, I do care about the ID of the controls that are output because with ASP.NET Web Forms IDs are auto-generated depending upon the container control that they live in (ASP.NET 4.0 will give you more control over IDs though).  While there are certainly workarounds for this, it can be a bit painful at times especially working with controls nested in a GridView or User Control.  ASP.NET MVC gives you 100% control over the IDs that are output so using script libraries such as Prototype or jQuery are that much easier.  And, like ASP.NET Web Forms, you get jQuery intellisense if the proper documented script files are available.

Here’s a simple example of handling the AjaxHelper (shown earlier) object’s OnSuccess event to load and process JSON data using jQuery:

function onEditOfficeProfileSuccess()
{
    GetOfficeProfiles();
}

function GetOfficeProfiles()
{
    CallService('/Account/GetOfficeProfiles', { customerID: $('#CustomerID').val() }, GetOfficeProfilesComplete);
}

function GetOfficeProfilesComplete(json)
{
    var s = $().parseTemplate($('#OfficeProfilesTemplate').html(), json);
    $('#OfficeProfilesOutput').html(s);
}

function CallService(url, data, callback)
{
    $.ajax({
        url: url,
        cache: false,
        dataType: "json",
        data: data,
        success: callback
    });
}

Reason #5: Promotes Better Coding Practices and a Solid Application Architecture

I’ll admit that this final reason isn’t as sexy as the others, but it’s definitely a benefit especially to larger enterprises with a lot of applications to build and maintain.  ASP.NET MVC helps guide developers down the path of designing architecturally sound applications from the start.  Now, don’t get me wrong, you can build solid applications using Web Forms as well and I’ve built many that had Presentation, Business, Data and Model layers.  However, a lot of developers (at least based on what I hear in some of the training classes we run) still put a lot of code in the code-behind file of a Web Form.  That works, but isn’t very re-useable and definitely isn’t very testable.  ASP.NET MVC forces gently guides developers to build architecturally sound applications that separate presentation, business and data logic so that it’s more reusable (and testable).  That doesn’t mean that the code is good as every developer has different skills of course, but it helps when people start things off on the right foot. If you’ve tried both frameworks (WebForms and MVC) I’d love to hear your thoughts on this final reason. 

To Sum Up….

Microsoft is going to support both ASP.NET Web Forms and ASP.NET MVC so you can go with either framework and be fine down the road (until some new technology is invented of course).  Having had a chance to use both frameworks I can tell you that each has its own set of pros and cons.  Hopefully, this post has given you a few reasons to research the ASP.NET MVC framework more and take a closer look at what it offers.  I’ll still be using Web Forms on some projects but it’ll be harder for me to choose between the two frameworks now….I’m really liking the control that ASP.NET MVC gives you.

 

 

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

Reflecting over JSON Data to Simplify Control Updates with jQuery

My company is currently working on a consulting project that uses ASP.NET MVC and a lot of jQuery and JSON behind the scenes for data transfer which is a lot of fun.  I’m personally tasked with the back-end processes but also handling user interface updates as JSON data is received.  I have a form with several different controls in it that are updated once JSON is returned from a controller action and the controls are updated using jQuery selectors.  Something like this:

$('#OfficeProfile_CustomerID').val(json.OfficeProfile.CustomerID);
$('#OfficeProfile_OfficeProfileID').val(json.OfficeProfile.OfficeProfileID);
$('#OfficeProfileAddress_AddressID').val(json.OfficeProfile.AddressID);
$('#OfficeProfile_OfficeTitle').val(json.OfficeProfile.OfficeTitle).convertNullToEmptyString();
$('#OfficeProfile_OfficeContactName').val(json.OfficeProfile.OfficeContactName).convertNullToEmptyString();
$('#OfficeProfile_NumberOfPeople').val(json.OfficeProfile.NumberOfPeople).convertNullToEmptyString();
$('#OfficeProfile_Phone').val(json.OfficeProfile.Phone).convertNullToEmptyString();
$('#OfficeProfile_Comments').val(json.OfficeProfile.Comments).convertNullToEmptyString();
$('#OfficeProfileAddress_Street').val(json.OfficeProfile.Address.Street).convertNullToEmptyString();
$('#OfficeProfileAddress_City').val(json.OfficeProfile.Address.City).convertNullToEmptyString();
$('#OfficeProfileAddress_StateID').val(json.OfficeProfile.Address.StateID).convertNullToEmptyString();
$('#OfficeProfileAddress_Zip').val(json.OfficeProfile.Address.Zip).convertNullToEmptyString();

While this code works fine, it quickly becomes a pain as JSON properties change and it’s just too much typing for my taste.  I decided that there must be a more compact way to do this given that there’s definitely a pattern to the ID names used in the jQuery selectors and the value assigned to each control.  After thinking about it more I realized that I need to use “reflection” (a technique used to inspect objects in the .NET framework) to access the JSON properties and then handle updates to the controls.  But, how do you reflect over a JSON object and figure out what properties it has?  Turns out it’s pretty easy…after a quick Google/Live search anyway.  You can iterate through the JSON object’s properties using a normal JavaScript for loop and then access each property name and value.  Here’s what I ended up doing to simplify the code above and make it more dynamic:

var prefix = '#OfficeProfile_';
var addrPrefix = '#OfficeProfileAddress_';
for (prop in json.OfficeProfile)
{
    var propVal = json.OfficeProfile[prop];
    if (prop == 'Address') //Object property within JSON..loop through Address object properties
    {
        for (addrProp in propVal)
        {
            $(addrPrefix + addrProp).val(propVal[addrProp]).convertNullToEmptyString();
        }
    }
    else
    {
        $(prefix + prop).val(propVal).convertNullToEmptyString();
    }
}

The json variable in the previous code represents the JSON returned from the call to the server and it exposes an OfficeProfile property.  The code loops look through each property in the OfficeProfile object, stores the value and then uses the property name to locate the appropriate control within the form that I want to update (using jQuery selector syntax).  I suspect there’s additional refactoring that I could apply but has worked out nicely so far.

 

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

Video – Getting Started with LINQ in .NET 3.5

A few weeks back my company offered a free online webinar on LINQ technologies to help developers more easily make the transition to LINQ.  While there was a great turn out at the webinar, I received several emails from people who couldn’t attend asking if I could provide a video recording of the webinar.  It turns out that the audio for the recording wasn’t up to my standards so I put together a video that provides an introductory look at different LINQ technologies including:

  • Lambda Expressions
  • Extension Methods
  • LINQ to Objects
  • LINQ to XML
  • LINQ to SQL
  • LINQ to Entities

You can view the video here (46 minutes).  If you’re interested in additional video tips or want to know about future webinars on .NET, SharePoint and Silverlight topics you can sign-up for the video tips newsletter here.

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.TheWahlinGroup.com

Getting Started with SharePoint 2007 Development – Q & A

I was recently asked a few questions from a magazine publisher about my thoughts on SharePoint 2007 development and some of the challenges it brings for developers who are new to the game.  There’s no one right answer to these questions of course (talk to another developer and you’ll probably get different answers), but these were my thoughts so I thought I’d share them.

1. What is the most difficult thing for .NET developers to grapple with when entering the SharePoint development space?

The sheer magnitude of the product is difficult for developers to grasp initially.  A lot of developers I've encountered consider SharePoint to only be an Intranet portal or meeting/document collaboration tool when in reality it's much more than that. It's quite difficult to master everything within SharePoint which is why some developers are good at Features, others at creating WebPart classes, while others know the Business Data Catalog inside and out. It's rare to meet a developer that knows every feature well. Just when you think you have a good handle on the product you learn something new that you didn't realize was there.

If I had to pick one SharePoint item that trips up .NET developers it would be the creation, packaging and deployment of Features and solutions since the files involved aren’t used at all when building standard .NET applications and feel foreign at first. When I first started doing SharePoint development I felt comfortable with the C#/VB coding but was confused by the various SharePoint XML files. Without good tools it can be challenging and quite unproductive to create Features and solutions and deploy them to SharePoint sites. Fortunately, several different tools are available on CodePlex.com and from Microsoft.

2. What are some common mistakes or oversights that developers new to SharePoint tend to make?

I don’t know if there’s one main mistake or oversight I can identify, but I’ve seen things built that could’ve been simplified quite a bit had the developer taken the time to see what SharePoint had to offer as far as built-in features. For example, event receivers can be created and deployed fairly easily and can be more appropriate than custom workflows in some cases (and much less code intensive). The SharePoint API offers a large amount of functionality but knowing how to leverage all of it can mean climbing an intimidating learning curve. Taking the time to research different tools and features (3rd party and those built into SharePoint) can also minimize the learning curve significantly, minimize a lot of custom XML document coding and lead to increased productivity.

Another area that is challenging for .NET developers is the CAS configuration required when doing things like BIN deployment of WebParts. With ASP.NET you drop an assembly in the BIN folder and you’re good to go in the majority of scenarios. With SharePoint it’s more involved and requires at least a basic knowledge of how partial trust settings work.

3. In your opinion, what kind of job is Microsoft doing bridging the gap between SharePoint and developers? Do the VS extensions for SharePoint  sufficiently support SharePoint dev in VS?

Microsoft’s definitely catching up with developer tools support although the popularity of free 3rd party tools out there gives a good indication that they still have a ways to go. The Visual Studio 2008 Extensions for SharePoint make it a lot easier to work with things like Features, Lists, WebParts and Site Definitions and significantly reduce the amount of custom XML coding that’s required. The latest CTP release adds a lot of nice deployment features to simplify building, packaging and deploying a solution to SharePoint and even integrates with environments that are using continuous integration processes. The extensions also run on 64-bit systems which is great for developers working on machines with a lot of RAM available. The current release provides a nice solution until Visual Studio 2010 comes out which will provide developers with much more direct access to SharePoint functionality from within the IDE.

4. Are there times when you don’t recommend building on top of SharePoint, even if it’s already deployed and available? What kinds of scenarios or situations might make what seems like a good SharePoint app opportunity not such a good idea?

SharePoint provides a centralized way to access documents, data and applications. If SharePoint is already deployed it makes a lot of sense to train employees to go to one place for everything they're doing. If SharePoint isn't deployed then I'd need to hear more about the customer's needs. From a development and maintenance standpoint I think it can be easier in some situations to integrate new or existing ASP.NET applications into SharePoint by simply providing a gateway into the application using something like the PageViewerWebPart or even a direct link. Security and other aspects of the application have to be thought through and taken into consideration when going this route but it offers a "loosely coupled" option. It really depends on how much direct interaction the custom application needs with SharePoint such as querying lists, the ability to search application data in SharePoint, access to the SPContext object, the authentication scheme, etc. It also depends on the amount of data to be retrieved and stored and whether or not using SharePoint's Web Service functionality is an option.

Developers can certainly build and deploy applications built specifically for SharePoint which can be the appropriate route to take in some situations. Finding qualified SharePoint developers can be challenging and costly in some areas though. By linking standard ASP.NET applications into SharePoint a wealth of developers can be tapped for development and end users still go to a single place to launch applications. There are certainly objections that can be brought up against this approach, but it's a viable solution when the situation is appropriate. I'm a "keep it simple" kind of person. The more complex an application is the more difficult it can be to support and maintain in the future especially when employee turnover and software upgrades are taken into consideration.

Logo

For more information about online and video training solutions for .NET, SharePoint or Silverlight please visit www.TheWahlinGroup.com.

Custom ASP.NET Server Controls and Language Localization

One of the products my company sells is an ASP.NET server control called SmartChart that generates OrgCharts from hierarchical data sources.  Up until recently the vast majority of our sales were to companies in the US so we never worried much about language localization support.  In the back of my mind I always knew we’d need to get to that, but always put it at the bottom of the feature list since it wasn’t overly exciting.  A few days ago we had a customer from France contact us and mention that they really needed to localize some of the strings we display in the control such as Edit, Delete, Insert into other languages for their clients.  I decided it was time to make the update. 

There are a lot of articles on localization so I’m not going to explain the overall concept in this post.  Check out the following links if you’re new to the topic and want to know more:

Creating Satellite Assemblies

The first solution that I tried to add localization capabilities into the server control was to use the built-in satellite assembly functionality in .NET.  I had worked with these in the past so I started with something I knew. Satellite assemblies allow language resources to be deployed separately from an application’s main .dll providing more flexibility.  Here are the basic steps to create a satellite assembly:

  1. Create a file named Resource.fr-FR.resx and add the appropriate keys and values for the localized strings (French in this case).  .resx files can be created by adding a new Resource File item into a project.
  2. Add the keys and values into the .resx file.  In this case the values would be in French.  The keys will always be the same across different language .resx files.
  3. Run the following command to create a resources file:   
    • resgen Resource.fr-FR.resources
  4. Run the following command to create a satellite assembly from the .resources file:   
    • al /t:lib /embed:Resource.fr-FR.resources,SmartWebControls.Localization.Resource.fr-FR.resources /culture:fr-FR /out:SmartWebControls.SmartChart.resources.dll
  5. Create a folder under your Website’s bin named fr-FR (the folder is named after the target culture)
  6. Copy SmartWebControls.SmartChart.resources.dll created in Step 4 into the fr-FR folder

Once the satellite assembly is ready you can use .NET’s ResourceManager class to get to individual keys and their associated values based on a specific language culture (English, French, German, etc.).  Problem is, the test satellite assembly I created didn’t work even though I knew all of the steps were being followed properly.  The localized language strings were never read for some reason.

After playing around with it more I realized that the problem was due to strong names.  Because the server control assembly was signed with a strong name key file and the satellite wasn’t (the customer would create the satellite assembly and we weren’t going to give out our strong name key file to be used for signing) it wouldn’t work properly.  Turns out that both the satellite assembly and the main application assembly have to signed by the same key…which makes sense.  After figuring out the problem I realized that satellite assemblies weren’t going to get the job done in this case.  On to some other more simple options….

Using HttpContext.GetGlobalResourceObject

I considered building my own resource solution specific to my control but after thinking through the options more I realized that the simplest solution would be to leverage the HttpContext object’s static GetGlobalResourceObject method along with ASP.NET’s support for .resx files.  GetGlobalResourceObject allows you to pass in the resource class name (for SmartWebControls.SmartChart.fr-FR.resx the class name would be SmartWebControls.SmartChart) followed by the key that you’d like to retrieve from the resource. 

If the customer supplied a localized resource file for a particular culture such as fr-FR or de-DE and placed it in an ASP.NET folder named App_GlobalResources, I would read in the appropriate key value and use it in the server control.  If they didn’t I’d read in my embedded resource values from the default Resources.resx file embedded in the control’s assembly.  An example of what the default Resources.resx file looks like in Visual Studio is shown next:

image

The simple wrapper class named ResourceManager that checks for a customer resource file and resorts to the default file if nothing is found is shown next:

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Globalization;

namespace SmartWebControls.Localization
{
    internal class ResourceManager
    {
        const string RESOURCE_BASE = "SmartWebControls.SmartChart";
        internal static string GetValue(string key)
        {
            CultureInfo culture = CultureInfo.CurrentCulture;
            //First try to load resource value from App_GlobalResources in case user is localizing control
            object val = HttpContext.GetGlobalResourceObject(RESOURCE_BASE, key, culture);
            if (val != null)
            {
                return val.ToString();
            }
            else
            {
                //If no value is found then load it from the embedded resource file (Localization/Resource.resx)
                return Resource.ResourceManager.GetString(key, culture);
            }
        }
    }
}


To retrieve a localized value I can call the ResourceManager’s GetValue method.  The following example shows how to retrieve the localized value for the SaveText key:

saveSpan.InnerText = ResourceManager.GetValue("SaveText");


I’m still playing around with it and may ultimately change how it works, but going this route allows customers to use standard .NET .resx files to define localized resources and allows me to access the resource strings easily without writing a custom resource solution.  A definite win-win situation.

WP Like Button Plugin by Free WordPress Templates