Friday, August 28, 2009

Getting Started with Telerik Extensions for ASP.NET MVC

I initially decided to try out the Telerik Extensions for ASP.NET MVC because I was looking to create a EditorTemplate (ASP.NET MVC v2 Preview 1 feature) for Date and I wanted to use the jQuery UI DatePicker wrapper that Telerik provides.

Not only was I pleased with the Fluent Interface that they used to wrap the jQuery UI Plugins, but I was also surprised and impressed by their Script and Style management system.

Web.config Changes

The first thing you’ll need to do is to make a couple of web.config changes to the Handler sections before starting to use the Telerik Extensions.

<?xml version="1.0"?>
<configuration>
    <system.web>
        <httpHandlers>
            <add verb="GET,HEAD" path="asset.axd" validate="false" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc"/>
        </httpHandlers>
    </system.web>
    <system.webServer>
        <handlers>
            <remove name="AssetHandler"/>
            <add name="AssetHandler" preCondition="integratedMode" verb="GET,HEAD" path="asset.axd" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc"/>      
        </handlers>
    </system.webServer>    
</configuration>

Including jQuery & jQuery UI

Before you can start using the jQuery UI wrappers, you’ll need to first include jQuery & jQuery UI into your project. For my simple project, I just did the following…

Site.Master MasterPage

<%@ Import Namespace="Telerik.Web.Mvc.UI"%>
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <% Html.Telerik().StyleSheetRegistrar()
        .DefaultGroup(group => group
            .Add("Site.css")
            .Add("jquery-ui-1.7.2.custom.css").Render(); %>              
</head>        
<body>
    <!-- Misc -->
    <%  Html.Telerik().ScriptRegistrar().Render(); %>            
</body>
</html>

The code will automatically insert jQuery by default and if you happened to use one of the Telerik jQuery UI Extensions then it will insert jQuery UI as well.

Note: It is important to know that the ScriptRegistrar must be directly before the end body tag in order to work.

Date EditorTemplate

Before creating the EditorTemplate, I annotated the DateOfBirth property with DataType.Date so the Template framework has additional metadata to work with.

Employee.cs View Model

using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using NestedTemplates.Helpers;

namespace TelerikExtensions.Models
{
    public class Employee
    {
        [UIHint("Hidden")]
        public long Id { get; set; }

        [Required(ErrorMessage = "First Name Required")]
        [StringLength(50, ErrorMessage = "Must be less than 50 characters")]
        [DisplayName("First Name")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "Last Name Required")]
        [StringLength(50, ErrorMessage = "Must be less than 50 characters")]
        [DisplayName("Last Name")]
        public string LastName { get; set; }

        [Required(ErrorMessage = "Social Security Required")]
        [StringLength(50, ErrorMessage = "Must be less than 50 characters")]
        [RegularExpression(@"^[0-9]{3}-?[0-9]{2}-?[0-9]{4}$", ErrorMessage = "Invalid Social Security Number Format")]
        [DisplayName("Social Security Number")]
        public string SocialSecurity { get; set; }

        [Required(ErrorMessage = "Date of Birth Required")]
        [StringLength(50, ErrorMessage = "Must be less than 50 characters")]
        [DataType(DataType.Date, ErrorMessage = "Date of Birth must be expressed as a date")]
        [DisplayName("Date of Birth")]
        public DateTime DateOfBirth { get; set; }
    }
}

Then I went ahead and made a EditorTemplate called Date.ascx (which matches the DataType.Date name) using the Telerik DatePicker Extension

Date.ascx EditorTemplate

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

<%@ Import Namespace="Mvc.UI.jQuery"%>

<% Html.jQuery().DatePicker()
    .Name("dateField")
    .Value((DateTime) Model).Render(); %>

Since we annotated the DateOfBirth property in our View Model with DataType.Date there isn't anything really special you need to do for ASP.NET MVC v2 Preview 1 to use it other than calling Html.EditorFor(m => m.DateOfBirth). Behind the scenes it matches up the types and uses the above EditorTemplate.

Edit.aspx View

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<TelerikExtensions.Models.Employee>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Edit</h2>
    
    <%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
    
    <% using (Html.BeginForm()) {%>
        <p>
            <%= Html.LabelFor(m => m.FirstName) %>
            <%= Html.EditorFor(m => m.FirstName) %>
            <%= Html.ValidationMessage("FirstName", "*") %>
        </p>
        <p>
            <%= Html.LabelFor(m => m.LastName) %>
            <%= Html.EditorFor(m => m.LastName) %>
            <%= Html.ValidationMessage("LastName", "*") %>
        </p>
        <p>
            <%= Html.LabelFor(m => m.SocialSecurity) %>
            <%= Html.EditorFor(m => m.SocialSecurity) %>
            <%= Html.ValidationMessage("SocialSecurity", "*") %>
        </p>
        <p>
            <%= Html.LabelFor(m => m.DateOfBirth) %>
            <%= Html.EditorFor(m => m.DateOfBirth) %>
            <%= Html.ValidationMessage("DateOfBirth", "*") %>
        </p>   
        <p>
            <input type="submit" value="Save" />
        </p>
    <% } %>
    
    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>
</asp:Content>

jQuery UI Goodness

The result is what you would expect if you had manually wired up the jQuery UI DatePicker into your project, but this time with strong type checking and a nice Fluent Interface.

jQueryUiDatePickerGoodness

Compress, Combine, & Cache

Now, what I thought was even cooler than that was that I could specify to combine, compress, and cache the scripts & styles… how cool is that!?!

<%@ Import Namespace="Telerik.Web.Mvc.UI"%>
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <% Html.Telerik().StyleSheetRegistrar()
        .DefaultGroup(group => group
            .Add("Site.css")
            .Add("jquery-ui-1.7.2.custom.css")
            .Combined(true)
            .Compress(true)).Render(); %>              
</head>        
<body>
    <!-- Misc -->
    <%  Html.Telerik().ScriptRegistrar().
            DefaultGroup(group => group
                .Combined(true)
                .Compress(true)
                .CacheDurationInDays(365)).Render(); %>            
</body>
</html>

Instead of compressing, combining, & caching everything together you could also choose to separate like scripts in groups like the following…

<% Html.Telerik().ScriptRegistrar().Scripts(script => script
        .AddGroup("Validation", group => group
            .Add("~/Content/Scripts/jquery.validate.min.js")
            .Add("~/Content/Scripts/xVal.jquery.validate.js")
            .Combined(true)
            .Compress(true)
            .CacheDurationInDays(365))
        .AddGroup("TableSorter", group => group
            .Add("~/Content/Scripts/metadata.js")
            .Add("~/Content/Scripts/jquery.tablesorter.js")
            .Add("~/Content/Scripts/jquery.tablesorter.pager.js")
            .Combined(true)
            .Compress(true)
            .CacheDurationInDays(365))                
    ).Render(); %>   

Gotchas

The next step was to integrate the test code into my main project. I had some initial issues resolving the jQuery & jQuery UI scripts. Initially, the Telerik Extensions look in the standard Scripts folder that the ASP.NET MVC project creates. However, I moved my Scripts folder under the Content folder alongside the Styles folder. Thanks to Todd Anglin, Kazi Manzur Rashid, & some research into their codebase I was able to put the following two lines of code in my Global.asax to override the default folder for the scripts.

using System.Web.Mvc;
using System.Web.Routing;
using Telerik.Web.Mvc;
using Telerik.Web.Mvc.UI;

namespace TelerikExtensions
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);

            ScriptRegistrar.FrameworkScriptPath = "~/Content/Scripts";
            WebAssetDefaultSettings.ScriptFilesPath = "~/Content/Scripts";
        }
    }
}

Summary

All in all, this is a very cool open source library that I think would be beneficial for most any ASP.NET MVC application.

Feel free to download the sample project I put together using most of the above code.

Wednesday, August 26, 2009

jQuery UI Dialog w/ Resizable iFrame

Today I went looking for a jQuery Modal Plugin that would allow me to display resizeable iframe content.

Although there are many jQuery Modal Plugins out there, there are not many that support iframe content. Out of those that openly support the iframe, I personally didn’t think they look all that good and I didn’t see any that supported the resize feature.

So, then I decided to take a deeper dive into the the jQuery UI Dialog Plugin to see what could be possible. Upon further scrutiny, I found that as of June 25, 2008 @rworth added functionality to the the plugin to support autoResize.

All I really had to do was create an iframe, call the jQuery UI Dialog, turn on the autoResize, do some initial resizing, and presto chango… a resizable modal with iframe content was born!

<html>
<head>
    <link rel="stylesheet" href="./styles/smoothness/jquery-ui-1.7.2.custom.css" type="text/css" media="screen" />
    <script type="text/javascript" src="./scripts/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="./scripts/jquery-ui-1.7.2.custom.min.js"></script>
    <script type="text/javascript">
    $(function() {
        $('a').click(function(e) {
            e.preventDefault();
            var $this = $(this);
            var horizontalPadding = 30;
            var verticalPadding = 30;
            $('<iframe id="externalSite" class="externalSite" src="' + this.href + '" />').dialog({
                title: ($this.attr('title')) ? $this.attr('title') : 'External Site',
                autoOpen: true,
                width: 800,
                height: 500,
                modal: true,
                resizable: true,
                autoResize: true,
                overlay: {
                    opacity: 0.5,
                    background: "black"
                }
            }).width(800 - horizontalPadding).height(500 - verticalPadding);            
        });
    });
    </script>
</head>
<body>
    <ul>
        <li><a href="http://www.google.com" title="Google Dialog">Google</a></li>
        <li><a href="http://jquery.com" title="jQuery Dialog">jQuery</a></li>
        <li><a href="http://jqueryui.com" title="jQuery UI Dialog">jQuery UI</a></li>
    </ul>
</body>
</html>

Feel free to check out the online demo of the above code and/or download the files yourself if you want.

Tuesday, August 25, 2009

Unblocking Assembly Due to AspNetHostingPermission Security Exception

Ok, I am one of those strange birds who jumped over Windows Vista and went straight from Windows XP to Window 7, so I haven’t had the pleasure to experience many of the security features that supposedly protect the user from themselves.

After banging my head on the proverbial wall one too many times, I finally figured out the cause of a Security Exception I was getting while trying to add xVal Validation Framework into my ASP.NET MVC v2 Preview 1 project.

“System.Security.SecurityException: Request for the permission of type 'System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.”

SecurityException

It appears that Windows 7 (and from what I’ve heard Windows Vista also does this as well) attempted to protect me from a potential threat! When looking at the file properties dialog of the xVal.dll there was a security message at the bottom stating…

“This file came from another computer and might be blocked to help protect this computer.”

UnblockAssemblyIt turns out that all I had to do is click the “Unblock” button next to the message, remove & readd my Visual Studio project reference, and viola my problems were solved!

Next time, I hope not to waste half my day trying to figure this out. If you have not already faced this pain, I hope that you don’t have to in the future, or that this post will help you resolve it quickly!

Friday, August 21, 2009

ASP.NET MVC V2 Preview 1 Strongly Typed UI Helper Performance

I am sure many of you ASP.NET MVC enthusiasts have either examined, downloaded, or started to play around with the ASP.NET MVC V2 Preview 1 release.

One of the many new features is the concept of Strongly Typed UI Helpers such as Html.DisplayFor() & Html.EditorFor() which take a Lambda Expression as their argument. This is a great new feature because we can now get compile time checking of our arguments and it provides the ability to easily refactor changes across our project. The old version of the Html Helpers were littered with Magic Strings that were susceptible to error and painfully resistant to change.

I was talking to a co-worker at Sommet Group, Alex Robson, about the new Strongly Typed UI Helpers and he immediately became curious as to whether the helpers use Lambda Compiles to obtain the Model’s value. I checked the source code of the ASP.NET MVC V2 Preview 1 release and found the following code snippet from TemplateHelpers.cs…

internal static void TemplateFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templateName, string htmlFieldId, DataBoundControlMode mode) where TModel : class {
   object modelValue = null;
   try {
      modelValue = expression.Compile()(html.ViewData.Model);
   }
   catch (NullReferenceException) { }  // Okay if it throws a null ref exception, we can infer types without the actual data
   //Etc...
}

The reason for the concern is that he read a recent slide deck by Rudi Benkovic reviewing several performance issues of which Lambda Compiles were a hot topic.

The Experiment

With Alex’s experience developing the Open Source project Nvigorate, he has had a lot of experience working with Lamdas, Reflection, and the like. So, he started on a mission to compare various dynamic access methods and to compare their performance. The following graph provides a high level summary of Alex's findings. You can also read his detailed post from his blog and download his sample code. 

DynamicAccessMethodPerformance

As you can see from the graph above, the Lambda Compile is by far the least efficient way to obtain the model’s value when compared with Dynamic Methods, Type Descriptor, and Reflection. The worst part is that the Lambda Compile and Dynamic Method approaches both scaled poorly when the number of test cases increased.

Why Should I Care?

You might be thinking, “Who would actually use 1,000 or even 10,000 instances of the Html.EditorFor() anyway? Why does this really even matter?”.

The answer is that we shouldn’t just be concerned about the current page request, but also with the overall scalability of our website as the number of concurrent page requests increase.

What Now?

The good news is that the API for the Strongly Typed UI Helpers don’t need to change in order to accommodate these speed performances. All of Alex’s tests start with a Lambda Expression…

public static void Reflect<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression, TModel instance)
{
    var val = typeof(TModel).GetProperty(GetMemberFromExpression(expression)).GetValue(instance, new object[] {});
    Debug.Assert(val.Equals("Dude"));
}

public static void TypeDescriptorCall<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression, TModel instance)
{
    var properties = TypeDescriptor.GetProperties(typeof(TModel));
    var property = properties.Find(GetMemberFromExpression(expression), false);
    TProperty val = (TProperty)property.GetValue(instance);
    Debug.Assert(val.Equals("Dude"));
}

public static void DynamicMethodCall<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression, TModel instance)
{
    var delegateCall = DynamicMethodFactory.CreateGetter(typeof(TModel).GetProperty(GetMemberFromExpression(expression)));
    var val = delegateCall(instance);
    Debug.Assert(val.Equals("Dude"));
}

public static void LambdaCompile<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression, TModel instance)
{
    var val = expression.Compile()(instance);
    Debug.Assert(val.Equals("Dude"));
}

Summary

Based on some initial work done by Rudi Benkovic as seen in his slide deck, it came to our attention that Lamda Compiles can be very slow and actually affect website scaling when using ASP.NET MVC.

Thanks to Alex Robson, he compared 4 different dynamic access methods and compared their performance. His findings showed that using a Lamda Compile was the slowest of the 4 approaches tested when obtaining a Model’s value from a Lambda Expression. In contrast, Reflection was by far the fastest approach to consistently retrieve a Model’s value.

I hope the ASP.NET MVC team will take note of these findings and consider using Reflection instead of Compiling the Lamda inside of their next preview release.

Goodbye Google Adsense And Hello The Lounge

TheLounge2_thumb

Out With The Old

On my previous blog I used to use the Google AdSense, but it quickly became a nuisance. Not only was my webpage cluttered with irrelevant Ads (usually off topic & sometimes offensive), but I could only get at most pennies a day in earnings.

I tried several approaches to get higher click-rates (by rearranging my ads, placing multiple ad blocks, changing colors, etc…), but in the end I think it annoyed my readers and it really didn’t provide the revenue that I had expected or desired.

In With The New

Due to my experience with Google AdSense, my search for another web-based marketing tool began.

What I wanted out of my new provider…

  1. Ads that are actually relevant to my blog audience
  2. A trusted reputable service
  3. Potential for some actual revenue

After my search, I am pleased to inform you that I have joined The Lounge for my advertising network along-side these top bloggers…

If you blog about Microsoft technologies, then why don’t you consider joining The Lounge too?

Wednesday, August 19, 2009

12 Must Have Web Developer Bookmarklets

I’ve been reviewing my blog statistics and as expected (from my developer audience) 52% of traffic is from Firefox, Internet Explorer comes in around 27%, Google Chrome takes about 14%, and Safari, etc… take the rest.

Although Google Chrome only has 14%, that is pretty impressive considering that it is a relative newcomer to the browser scene.

Without a mature browser plugin model, it can be limiting when working with Google Chrome when doing web development… unless, that is, you have a great set of bookmarklets!

I have found that these 12 bookmarklets bring Google Chrome into a much more productive browser while doing web development.

Note: You can test out the bookmarklet by clicking the link or you can save it to your browser by dragging it up to your toolbar. Each bookmarklet has a Details link next to it that describes the functionality in further detail. If newer versions of the bookmarks exist, then they probably can be found from the Details link.

01. Firebug Lite (Details)

One of the most frequently used tools for any web developer is Firefox’s Firebug plugin. If you feel that your hands are tied when using another browser, then don’t you fret… Firebug Lite to the rescue! You can use this bookmarklet to simulate many of the features of the full Firebug plugin.

FirebugLite

02. jQuerify (Details)

This bookmarklet enables you to inject jQuery into a webpage that didn’t previously have it loaded on startup. If the website already included jQuery, then a message will indicate which version it has loaded.

jQuerified

03. WTFramework (Details)

If you ever have visited a website and was like, “What… that is awesome! I wonder what JavaScript framework they used to developer that awesome website!?!” then this is the bookmarklet for you :) A small rectangle will show up in the upper-right corner of the page indicating if any of the following frameworks were used… (MooTools, Yahoo User Interface, jQuery, Scriptaculous, Dojo Toolkit, Mochikit, etc.)

WTFramework

04. jQuery Plugin Detector (Details)

In the same light as the previous bookmark, you might also wonder which plugins were used when developing a particular website. Instead of digging through the View Source you can just click this bookmarklet to reveal a little window that reveals you all the jQuery plugins loaded for the current page.

jQueryPluginDetector

05. SelectorGadget (Details)

This bookmarklet is good for either a novice or expert alike. If you are needed some assistance creating a jQuery selector then try out this bookmarklet… it could surprise you with its quick and easy results. Once clicked, the bookmarklet inserts a command prompt at the bottom of your page and you interact with the DOM to help narrow down your selection. For more information, check out the short video exercising the features.

SelectorGadget

06. 960 Gridder (Details)

If you happen to be using the 960 Grid System, then this plugin can become very helpful when laying out your website. This bookmarklet will overlay a grid layout on top of your page. There are several options you can modify to fit your specific needs.

960Gridder

07. Design (Details)

There comes a time in most web development when you need to measure the dimensions of something on your webpage. This is where this bookmarklet comes in handy. There are several options to measure things in your DOM. It is pretty straightforward. Just click and drag :)

Design

08. BuiltWith (Details)

This is an interesting bookmarklet that redirects the current page to the BuiltWith service that interrogates the page to determine the server information, analytic tools, javascript libraries, frameworks, content delivery networks, aggregators, etc…

BuiltWith

09. W3C HTML Validator (Details)

This bookmarklet will redirect the current page to the W3C Markup Validation Service to reveal any errors and/or warnings in the document. As you can tell, it looks like I have a little clean-up work in my templates & blog posts :)

W3CHtmlValidator

10. W3C CSS Validator (Details)

This bookmarklet will redirect the current page to the W3C CSS Validation Service to reveal any issues that do not conform with the official standards. Again, it appears I have some cleanup work to do on this blog :)

W3CCssValidator

11. PageZipper (Details)

This isn’t exactly a hard-core web development bookmarklet, but I added it because I find that it saves time during the research and development stage. As I’m surfing around Google (or really any website that has a Next link/button) it gets pretty old to click the next button all the time. This bookmarklet will automatically retrieve the next results and load them dynamically into your current page once you have scrolled near the end of the page. It works well with Google, Twitter, and even my blog :)

PageZipper

12. BigTweet (Details)

As I scour the internet in search of the best and newest technology news, tools, plugins, etc… I have found the best tool to extract the title & URL for Twitter distribution is the BigTweet bookmarklet. A recent feature added to BigTweet has been the Delicious integration, which I use frequently. Although I tweet from BigTweet often, I usually just use it as an extraction tool and then transfer the Twitter text to a scheduler program.

BigTweet

Friday, August 14, 2009

How to Create Your Own jQuery Plugin

I just gave the following presentation at devLINK on “How to Create Your Own jQuery Plugin”.

SommetGroupjQueryPluginTshirtYou can download the code samples and slides and investigate them in more detail.

I am considering making a screencast or a blog series on the concepts described in my presentation. I find that just posting a bunch of code and slides don’t tell the whole story for those that didn’t actually attend the talk.

At the end of the talk I gave away custom made jQuery Plugin t-shirts for those that asked relevant questions. A huge thanks goes out to my company, Sommet Group, for making such awesome shirts!

Additional thanks go out to the follow resources that I used to help assist me with my presentation

I will create another blog post on some of the helpful bookmarklets & plugins that I find useful when developing in jQuery, but I did want to mention one website that is helpful when starting a jQuery Plugin from scratch.

It is called Starter: jumptstart Your jQuery Plugins and you just provide the new jQuery Plugin name, optional namespace, parameters, options, etc… and then you are on your way focusing on the guts of your Plugin.

starter