August 2009 - Posts

[Update: I have updated the images with a recent version which more clarifies the whole picture, the result shows the parallel version is 2x fast comparing to the plain.]

In this post, I will give you a sneak preview of the ScriptRegistrar major enhancement. Those who have checked our ScriptRegistrar or followed my blog for last few weeks already know that it has out of box support for Grouping. Combining, Caching, Compressing, Synchronizing statements between Master/Content and as far as I know, no other component including the other commercial vendors has all these features that we are providing for free and as well as open sourced. Currently we are working on parallel script downloading support that we are going to include in our next release, if you do not know about parallel script downloading let me first show you a regular example, lets say you have a page which contains five script tags:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Plain Script Loading</title>
</head>
<body>
    <h1>Plain Script Loading example</h1>
    <p>Here goes the sample body..</p>
    <div id="status" style="font-family:Consolas;background-color:#ccc"></div>
    <% string ticks = DateTime.Now.Ticks.ToString(); %>
    <script type="text/javascript" src="Scripts/plainScript1.js?t=<%= ticks %>"></script>
    <script type="text/javascript" src="Scripts/plainScript2.js?t=<%= ticks %>"></script>
    <script type="text/javascript" src="Scripts/plainScript3.js?t=<%= ticks %>"></script>
    <script type="text/javascript" src="Scripts/plainScript4.js?t=<%= ticks %>"></script>
    <script type="text/javascript" src="Scripts/plainScript5.js?t=<%= ticks %>"></script>
    <script type="text/javascript">
        document.getElementById('status').innerHTML += 'You must have seen all the messages.<br>';
    </script>
</body>
</html>

If you run the above page with Firebug, you will find, it loads the page similar to the following:

plain

Check the above red marked area which shows as steps of a stairway. It indicates when a browser encounters a script tag it stops its rendering until it downloads the script file. Since we have included five script files there are five steps (total six, the first one is for the page), each for a script. Now lets add the same number of script files with our ScriptRegistrar:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Next ScriptRegistrar</title>
</head>
<body>
    <h1>ScriptRegistrar : Parallel script loading example</h1>
    <p>Here goes the sample body..</p>
    <div id="status" style="font-family:Consolas;background-color:#ccc"></div>
    <% string ticks = DateTime.Now.Ticks.ToString(); %>
    <% Html.Telerik().ScriptRegistrar()
                     .Scripts(script =>
                              script.Add("~/Scripts/parallelScript1.js?t=" + ticks)
                                    .Add("~/Scripts/parallelScript2.js?t=" + ticks)
                                    .Add("~/Scripts/parallelScript3.js?t=" + ticks)
                                    .Add("~/Scripts/parallelScript4.js?t=" + ticks)
                                    .Add("~/Scripts/parallelScript5.js?t=" + ticks)
                             )
                     .OnDocumentReady(() =>
                                      {%>
                                        document.getElementById('status').innerHTML += 'You must have seen all the messages.<br>';
                                      <%}
                                     )
                     .Render(); %>
</body>
</html>

(I have intentionally removed the default jQuery script form the ScriptRegistrar and did not merge it as a group to show the parallelization).

When you run the ScriptRegistrar version with the Firebug, you will get the following picture:

parallel

Now check the red marked area again, as you can see there are no steps which means download of this scripts starts almost at the same time, we are initially loading our tiny script loader(Telerik.ScriptRegistrar.js) which then loads these scripts without blocking each other. We are still working on different cases and how you can more easily define the dependencies between the groups/script files.

So to those folks who thinks that a msbuild/nant task that minifies and combines script files of a predefined directory on post build and a ScriptInclude helper method is all the optimization that can be done when it comes to script management, maybe it is okay for a small application where the number of javascript files are same or less than your hand’s finger, but for today’s highly ajax application, there are a lot of cool things that you can do to enhance its performance and we are fully committed for doing that.

Shout it

Convention over Configuration is getting more and more popular in the .NET space, especially after the release of ASP.NET MVC. In our extensions, there are quite a few places where you will find this concept, lets consider the following snippet of ScriptRegistrar:

<% Html.Telerik().ScriptRegistrar()
                 .Scripts(script => script.AddGroup(
                                                        "validation",
                                                        group => group.Add("jquery.validate.js")
                                                                      .Add("xVal.jquery.validate.js")
                                                                      .Combined(true)
                                                   )
						 )
				 .Render(); %>

Check that we did not mention any path for the script files, by default it assumes that all the script files are located in the default “Scripts” folder that is created when you create a ASP.NET MVC Application in Visual Studio. Now what if the script files resides in a different folder.

<% Html.Telerik().ScriptRegistrar()
                 .Scripts(script => script.AddGroup(
                                                        "validation",
                                                        group => group
                                                                      .DefaultPath("~/Scripts/Validation") // Setting the default path of a Group.
                                                                      .Add("jquery.validate.js")
                                                                      .Add("xVal.jquery.validate.js")
                                                                      .Combined(true)
                                                   )
						 )
				 .Render(); %>

Now what if one of the file in a group resides in a different folder:

<% Html.Telerik().ScriptRegistrar()
                 .Scripts(script => script.AddGroup(
                                                        "validation",
                                                        group => group
                                                                      .DefaultPath("~/Scripts/Validation")
                                                                      .Add("jquery.validate.js")
                                                                      .Add("~/SomeOtherPath/xVal.jquery.validate.js") // Check that we are setting the complete path.
                                                                      .Combined(true)
                                                   )
						 )
				 .Render(); %>

Okay, now what if you want to change the default location of both scripts and stylesheet files, Just add the following lines in your application start (global.asax maybe):

WebAssetDefaultSettings.StyleSheetFilesPath = "~/assets/stylesheets";
WebAssetDefaultSettings.ScriptFilesPath = "~/assets/scripts";

So by convention we are assuming the default locations (for script “~/Scripts” and Stylesheet “~/Content”) but with configuration (the above 2, 3, 4 code snippets) you can completely override it. Let me show one more case before completing this post.

We all know we should minify our script and stylesheet files with tools like Yahoo compressor before making the application live. Lets say we have minified the above two files with a minifying tool and saved in the Scripts directory with .min.js extension. Now, if you run the application in release mode debug = “false” in web.config, you will find that the ScriptRegistrar is picking up the .min.js instead of .js or debug.js and the vice versa when debug=”true” and the same holds true for StyleSheetRegistrar.

Shout it

Recently there has been a talk of Actionless Controller in ASP.NET MVC space. Basically we are doing a lot of things in the controller and that is the reason we often finds our controllers with number of dependencies in the constructor. Jeffrey Palermo initially suggested a version where he separated each action as a standalone controller which is good to reduce the number of dependency but it does not sound right to me. At the bottom of that post Neal Blomfield hinted about the Command Pattern which makes absolute sense. Since the release of our initial version, I have got some time to breathe, so I decided to give it a try. Initially the idea was, each Controller action method will accept a command object as parameter and the Controller will call the Execute method. The Command object will be responsible to perform the action which the Controller action methods usually do. Let me show you a sample controller which has nothing but some CRUD methods with Command objects:

public class ProductController : Controller
{
    public ActionResult Index(ProductListCommand command)
    {
        return command.Execute();
    }

    public ActionResult Create()
    {
        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(ProductCreateCommand command)
    {
        return command.Execute();
    }

    public ActionResult Edit(ProductGetCommand command)
    {
        return command.Execute();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(ProductUpdateCommand command)
    {
        return command.Execute();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Delete(ProductDeleteCommand command)
    {
        return command.Execute();
    }
}

Now, let see what is happening inside the Commands, first the ProductCreateCommand:

public class ProductCreateCommand : RESTifyCommand
{
    private readonly IRepository<Product> repository;

    public ProductCreateCommand(IRepository<Product> repository)
    {
        this.repository = repository;
    }

    public Product Product
    {
        get;
        set;
    }

    protected override void ExecuteCore()
    {
        // You should use a powerful validation engine like DataAnnotation or xVal 
        // over here, I am using the dumb if/else for the shake of simplicity.

        if (string.IsNullOrEmpty(Product.Name))
        {
            ModelState.AddModelError("Product.Name", "Name cannot be blank.");
        }

        if (!Product.Price.HasValue)
        {
            ModelState.AddModelError("Product.Price", "Price cannot be blank.");
        }

        if (Product.Price.HasValue && (Product.Price <= 0))
        {
            ModelState.AddModelError("Product.Price", "Invalid price. Price cannot be zero or negative.");
        }

        if (ModelState.IsValid)
        {
            repository.Create(Product);
            ViewData.Model = Product;
        }
    }
}

First, it is inherited from a special base class RESTifyCommand, next we are injecting our dependency in the constructor as we do for the Controllers and at last, we are overriding the ExecuteCore method to perform our actual operation. Also check that we not writing any code to populate the Product, instead we are relying on the ASP.NET MVC Framework to populate it for us. The little difference between the ExecuteCore with a regular Controller action method is instead of returning any ActionResult(the method is a void()) we are only setting up the Model and ModelState. I will get back to the Execute() method after a little while, for the moment lets see how this Command object is created and passed backed to the Controller. One of the important thing when creating the Command Object is, we have to inject the dependencies in its constructor or more specifically we have to give the opportunity so that you can use your prefered IoC/DI framework to create these commands, also we need to utilize the rich ASP.NET MVC underlying features to automatically populate the other parts of the Command (for ex the Product property of the above example) and the thing that I really love of ASP.NET MVC framework is its extensibility. To create and populate the Command object we use a custom ModelBinder. Our ModelBinder is inherited from the DefaultModelBinder of ASP.NET MVC as we want to reuse the common behavior of the default binder, but instead of overriding the BindModel that you often see in most of the available ModelBinders, we are overriding the CreateModel method.

public class CommandBinder : DefaultModelBinder
{
    private readonly Func<Type, IRESTifyCommand> factory;
    private readonly IFormatDetector formatDetector;

    public CommandBinder(Func<Type, IRESTifyCommand> factory, IFormatDetector formatDetector)
    {
        Invariant.IsNotNull(factory, "factory");
        Invariant.IsNotNull(formatDetector, "formatDetector");

        this.factory = factory;
        this.formatDetector = formatDetector;
    }

    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        Invariant.IsNotNull(controllerContext, "controllerContext");
        Invariant.IsNotNull(modelType, "modelType");

        IRESTifyCommand command = factory(modelType);
        RESTifyFormats format = formatDetector.Detect(controllerContext.HttpContext.Request);

        command.SetRequestFormat(format);
        command.SetControllerContext(controllerContext);

        return command;
    }
}

As you can see in the constructor we are accepting a Func to create the Command so that we do not have to refer to any external IoC/DI component, we are also accepting another object IFormatDetector. Initially, my plan was to introduce the Command object in ASP.NET MVC, but after seeing both Nate Kohari’s Siesta and MS ASP.NET MVC REST SDK, I thought why not add some REST love into this. So the idea was after the Command objects performs its actual operation which we have seen in the above, it should also decide in which format it will return the data, the associated controller should not have any clue about this, all it has to do is call the Excecute() method of command and the rest it taken care by the Command. In the above, the formatDetector detects the requested format from HttpRequest and sets the Command requested format, so that Command can later return the result depending upon that. Although it is in very early stages and I am still working on it, yet there are some advantages of using it comparing to the above:

  1. Out of the box support for HTML/XML/JSON/JSONP. There is no generic representation of ATOM/RSS, you need to write special formatters(IResultFormatter) to support those.
  2. Serialization support other than DataContractSerializer, which means you can serialize anything including the anonymous objects.
  3. Support for Registering JavaScriptConverter to shape up the json output. (It is still missing in the ASP.NET MVC Framework).
  4. Support for Registering KnownTypes for the DataContractSerializer.
  5. Fully extensible, anything can be replaced without modifying the core.
  6. 200+ Unit Tests which include more than 99% code coverage.

You can view the complete live demo, over here. As you can see the same Controller method is responsible for returning different formats, no condition checking, no if/else nothing, just call the Execute() of the Command. In the demo, I am using plain javascript instead of any library like jQuery/ASP.NET AJAX to show you that it is completely independent of the client side, you can use your prefered javascript library with this extension when working with your browser application.

Now lets get back to the original discussion, so far we have set the Model and ModelState, but did not see how the result is delivered to the client, lets see what is happening in the RESTIfyCommand’s Execute method:

public virtual ActionResult Execute()
{
    if (!CanExecute)
    {
        return Unsupported();
    }

    ExecuteCore();

    return BuildResult();
}

First, we are checking whether the Command can execute, there are severeal reasons a Command cannot execute, for example the request format is not supported by the Command, which usually happens when you want to restrict certain formats from delivering to the client or formatter for the requested type is not registered or your code as you can override the method, if the command cannot execute we are returning a special ActionResult RESTifyUnsupportedResult which is basically returning HttpStatusCode 415(Unsupported Media Type). If the command is allowed to execute then it is calling the ExecuteCore() which means the code that we have written in the above and finally it is returning the result. Now lets see the code of BuildResult method.

protected virtual ActionResult BuildResult()
{
    if (RequestedFormat == RESTifyFormats.Html)
    {
        return new ViewResult { ViewData = ViewData, TempData = TempData };
    }

    IResultFormatter formatter = ResultFormatters[RequestedFormat];

    if (RequestedFormat == RESTifyFormats.Jsonp)
    {
        IJsonpResultFormatter jsonpFormatter = formatter as IJsonpResultFormatter;

        if (jsonpFormatter == null)
        {
            throw new InvalidOperationException(TextResource.InvalidResultFormatterTypeRegisteredForJsonp.FormatWith(formatter.GetType().FullName));
        }

        jsonpFormatter.JsonpCallbackFunction = JsonpFunctionNameDetector.Detect(HttpContext.Request);
    }

    return new RESTifyResult(RequestedFormat, formatter, HttpContext.Request.ContentEncoding, Model, ModelState);
}

As you can see, for the Html, we are returning the regular ViewResult, next for JSONP we are checking whether the registered formatter is appropriate for JSONP, as JSONP needs the additional callback method name, the rest of the part is very simple, we are returning our custom RESTifyResult with the required data, the RESTifyResult uses the provided ResultFormatter to write in the Response.

public override void ExecuteResult(ControllerContext context)
{
    Invariant.IsNotNull(context, "context");

    HttpResponseBase response = context.HttpContext.Response;

    response.Clear();

    response.ContentType = contentTypes[Format];

    if (ContentEncoding != null)
    {
        response.ContentEncoding = ContentEncoding;
    }

    string output = Formatter.Format(ContentEncoding, Model, ModelState);

    response.Write(output);
}

One last thing that you have to do, is adding some bootstrapping code in the global.asax or more preferably in your Bootstrapper.

public void ConfigureRESTify()
{
    RESTifySettings.Current
                   .SetCommandFactory(type => ServiceLocator.Current.GetInstance(type) as IRESTifyCommand)
                   .RegisterCommands();
}

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);

    ConfigureServiceLocator();
    ConfigureRESTify();
}

We are setting the factory method which you have seen in the CommandBinder in the above in the SetCommandFactory, I usually prefer to abstract the underlying IoC/DI with the CommonServiceLocator, if you do not like it, you use your preferred DI directly over here. Next, we are registering all Commands with our CommandBinder by scanning the referenced assemblies, if you do not like to scan you can use the overloaded version which accepts specific types or single assembly.

Now let me answer some of the common questions:

Q: How do I redirect to a action after the command executes, for example, in a CRUD operation when an object is created I want to redirect back to Index for the Html and for the others formats I just want to return the data.

A: There are few overloaded methods in the Command which you can use to redirect to other actions for a special format after the command executes. For example, in the above ProductController’s Create you can use the following:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(ProductCreateCommand command)
{
    return command.ExecuteAndRedirectToAction("Index").WhenFormatIsHtml();
}

The WhenFormatIsHtml is an extension methods there are other versions of it. Don’t worry about the validation it will not redirect if the validation fails (ModelState.IsValid == false).

Q: What about the other facilities that we often gets in the regular Controllers like Try/UpdateModel, UrlHelper etc etc.

A: Most of the facilities that are available in Controller is also available in Command but it does not includes those which are contradictory (methods that returns ActionResult (w/o redirecting) are excluded).

Q: Looks like the Command object itself inherited from Controller.

A: No, it is not. This is the declaration:

public abstract class RESTifyCommand : IRESTifyCommand, IHideObjectMembers

Q: How do I on/off supported format?

A: To on/off supported formats globally use the RESTifySettings like the following:

RESTifySettings.Current
               .SetCommandDefaultFormats(RESTifyFormats.Html | RESTifyFormats.Json);

Now all your command will only support html and json or you can override the SupportedFormats property if you want to set it for a specific command, for example, now the ProductListCommand will only support Html and ATOM:

public class ProductListCommand : RESTifyCommand
{
    protected override RESTifyFormats SupportedFormats
    {
        get
        {
            return RESTifyFormats.Html | RESTifyFormats.Atom;
        }
    }
}

Q: How do I register custom Result Formatter?

A: To register a formatter that will be applied to all, use the RegisterResultFormatter method, there is also Command specific version which will set the formatter for only that Command.

Q: How does the Serialization works?

A: Well when it comes to serialization in .NET Framework, we have two sets of serializers the regular serializers like XmlSerializer/JavaScriptSerializer and the new DataContractSerializers, but none of it can serve our purpose. For example, DataContractSerializers can only work when the serialized object is decorated with its required attributes, which means you cannot serialize anonymous objects or the objects that are beyond your control also if your object is buildup with other objects it requires to know those other objects. There are also issues with regular serializers. So instead of supporting only a single set, we are supporting both. When serializing we are first first checking whether the object is a known type to us, if it is a known type we use the DataContractSerializers if not we are using the regular serializers. By known type, I mean an object is decorated with DataContractSerializers attributes and it is registered to this extension. To register known types, you can use the RegisterKnownTypes method of RESTifySettings, it has similar overloaded versions of RegisterCommands.

Q: How can I play with it, where is the source code located?

A: You can check the live version over here or if you want to get the source, checkout my first open source project in GitHub.

That’s it for the day.
Shout it

[Update: We have just upload the source code in CodePlex. Check it out.]
[Update: Also checkout the Atanas post where he detailed our plans and goals of this product.]

Today, we have released our first public community technology preview of our ASP.NET MVC Extensions. This is a very lightweight framework for developing ASP.NET MVC View Components that we are working for last few months. There are few key points that I like to mention:

  • It is Open Source (dual licensed), yes you heard me. It is the first Open Source project of Telerik released under MS-PL.
  • It is free for the time being we will be developing our commercial components based upon this tiny framework.
  • It is based upon jQuery, yes we know how much the community loves it.
  • It supports multiple view engines. The sample contains the Webform, Spark and NHaml examples.
  • The CTP contains the popular jQueryUI components as a proof of concepts but you can use it in your application with complete confidence. Since, we will be releasing our own version, it would be difficult for us to give it the same priority, instead we expect the open source community will be responsible for its further development(enhancing, bug fixing and adding new components) and we will be accepting patch/new components for the jQuery components from the community.

You can download it with complete source/tests/samples/docs from our ASP.NET MVC Product page (we will be also uploading it in CodePlex), please check back if the page is still not available.

You can also check the jQueryUI Webform demo over here.

I will be blogging more about this very soon.

Stay tuned!!!

Shout it
More Posts