Saturday, August 20, 2011

ASP.NET MVC 3 updating and handling the jQuery libraries

When installing the ASP.NET MVC 3, we'll be getting some tools for Visual Studio 2010 along with Nuget.Nuget is nothing but an Visual studio extension which can be used to install and update open source libraries. It handles the task of including the library files into the project, adding the required references, including the respective entries in the config files and some other tasks based on the package we install.

We can access the Nuget tools using Visual Studio 2010 from, Tools > Library Package Manager > Package Manager Console / Manage Nuget Packages. One we add the ASP.NET MVC 3 project to a solution, by default we'll get few jQuery and related packages got installed.

Package Manager Console
We can view the installed packages by typing the "get-package" command in the Package Manager Console. By default jQuery packages like jQuery (core library), jQuery.UI.Combined, jQuery.Validation and jQuery.vsdoc will be installed while adding the ASP.NET MVC 3 project. In order to update these default jQuery packages, use the following command in the Package Manager Console.

update-package jquery

In order to get info about Nuget Package Manager commands type "get-help nuget".    

Manage Nuget Packages
Apart from the Tools menu this option is also avaliable when we right click(context menu) on the project. This option is some what similar to the Extension Manager menu where we can visually manage the packages.



Summary
Using any of the above specified two options you can update the packages which will update the related files by removing the old ones and adding the new ones. This helps us handling the updating process smoothly without any miss-outs.

Monday, August 15, 2011

ASP.NET MVC - Identifying the nature of request using IsAjaxRequest()

HttpRequestBase class is provided with an extension method called IsAjaxRequest() which specifies whether the request has been initiated as an AJAX call/request. Actually it looks for a specific header (x-requested-with: XMLHttpRequest) in the HTTP request made and acts accordingly.

From the Controller class we can access this method using Request.IsAjaxRequest(), as the Request property holds/gets the HttpRequestBase object for the current HttpRequest.

Ok, now let us see the real use of this IsAjaxRequest() method. If you see the ProjectMemberDetailsController in my previous post ASP.NET MVC 3 and jQuery templates - Part2, I've used two methods ProjectMemberList() and ProjectMemberList(string experience) with [HttpPost] attribute. Each serves the following purpose: 
  1. ProjectMemberList() - Called when the view is rendered initially by the view engine. Here we need to return the related view and this is a non-AJAX call by nature.
  2. ProjectMemberList(string experience) [HttpPost] - Invoked whenever the AJAX call is initiated using POST request. Here we need to return the JSON result.
 With the help of IsAjaxRequest(), let us see how can we change the ProjectMemberDetailsController.

Snippet 1 (ProjectMemberDetailsController with IsAjaxRequest())

public class ProjectMemberDetailsController : Controller
{
    public ActionResult ProjectMemberList(string experience)
    {
        SampleData sampleData = new SampleData();

        if (Request.IsAjaxRequest())
        {
            if (string.IsNullOrEmpty(experience) || experience.Equals("All"))
            {
                return Json(sampleData.ProjectMemberList, JsonRequestBehavior.AllowGet);
            }
            else
            {
                return Json(sampleData.GetProjectMembersWithExpGreaterThan(int.Parse(experience)), JsonRequestBehavior.AllowGet);
            }
        }

        return View();
    }
}

Summary
From the above snippet we can clearly infer that how effectively we can utilize the IsAjaxRequest() method. It'll be very much helpful and can be used effectively in lot of scenarios. One such scenario I faced is while customizing the Authorize attribute, in order to determine the authorization logic based on the nature of the request.

References
http://msdn.microsoft.com/en-us/library/system.web.mvc.ajaxrequestextensions.isajaxrequest.aspx

Sunday, August 14, 2011

ASP.NET MVC 3 and jQuery templates - Part2

In part 1, we saw the basic implementation of jQuery template with the help of html file. In this part we'll look into a simple implementation using ASP.NET MVC 3. Following few steps will define the steps I've followed to create the sample which helps readers to dive into the code with better understanding.

First created an empty ASP.NET MVC3 web application. Then created a model by adding an Employee class in the Models folder.

Snippet 1(Model - Employee)

public class Employee
{
    public string EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int Experience { get; set; }
    public string Designation { get; set; }
}

For the purpose of this example have created a SampleData class in the Models folder.

Snippet 2 (SampleData)

public class SampleData
{
    #region Class Level Variables
    private List<Employee> projectMemberList;
    #endregion

    #region Properties
    public List<Employee> ProjectMemberList
    {
        get
        {
            if (projectMemberList == null)
            {
                LoadProjectMemberList();
            }
            return projectMemberList;
        }
        set { projectMemberList = value; }
    }
    #endregion

    #region Public Methods
    public IEnumerable<Employee> GetProjectMembersWithExpGreaterThan(int experience)
    {
        return ProjectMemberList.Where(emp => emp.Experience > experience);
    }
    #endregion

    #region Private Methods
    private void LoadProjectMemberList()
    {
        projectMemberList = new List<Employee>();

        projectMemberList.Add(new Employee { EmployeeId = "E1001", EmployeeName = "Member1", Experience = 7, Designation = "Project Lead" });
        projectMemberList.Add(new Employee { EmployeeId = "E1002", EmployeeName = "Member2", Experience = 4, Designation = "SSE" });
        projectMemberList.Add(new Employee { EmployeeId = "E1003", EmployeeName = "Member3", Experience = 9, Designation = "Tech Lead" });
        projectMemberList.Add(new Employee { EmployeeId = "E1004", EmployeeName = "Member4", Experience = 3, Designation = "SE" });
        projectMemberList.Add(new Employee { EmployeeId = "E1005", EmployeeName = "Member5", Experience = 5, Designation = "Team Lead" });

    }
    #endregion

}

Next in the Controllers folder have created a ProjectMemberDetailsController.

Snippet 3 (ProjectMemberDetailsController)

public class ProjectMemberDetailsController : Controller
{
    
    public ActionResult ProjectMemberList()
    {
        return View();
    }

    [HttpPost]
    public JsonResult ProjectMemberList(string experience)
    {
        SampleData sampleData = new SampleData();

        if (string.IsNullOrEmpty(experience) || experience.Equals("All"))
        {
            return Json(sampleData.ProjectMemberList, JsonRequestBehavior.AllowGet);
        }
        else
        {
            return Json(sampleData.GetProjectMembersWithExpGreaterThan(int.Parse(experience)), JsonRequestBehavior.AllowGet);
        }

    }
}

Finally added a ProjectMemberList.cshtml file under the Views/ProjectMemberDetails folder.

Snippet 4 (ProjectMemberList)   

@model String
@{
    ViewBag.Title = "ProjectMemberList";
}
<h2>
    ProjectMemberList</h2>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.js"
    type="text/javascript"></script>

<script id="memberDetailTemplate" type="text/html">
    <tr>
        <td>
            ${EmployeeName}
        </td>
        <td>
            ${Experience}
        </td>
        <td>
        {{if Designation == 'Tech Lead'}}
        <span style="color:Green; font-weight: bold;">${Designation}</span>
        {{else}}
        <span style="color:Blue;">${Designation}</span>
        {{/if}}            
        </td>
    </tr>  
</script>
<script type="text/javascript">
    $(document).ready(function () {
        $.ajax({ type: "POST", url: "ProjectMemberDetails/ProjectMemberList", success: jsonProjectMemberListSuccessCallback });
    });

    function jsonProjectMemberListSuccessCallback(data) {
        var targetElement = $('#memberData');

        targetElement.empty();

        $("#memberDetailTemplate").tmpl(data).appendTo('#memberData');
    }
</script>
<div id="loadingFeedback" style="display: none; color: Red; font-weight: bold;">
    <p>
        Loading details....
    </p>
</div>
@using (Ajax.BeginForm(new AjaxOptions
{
    LoadingElementId = "loadingFeedback",
    OnSuccess = "jsonProjectMemberListSuccessCallback",
    Url = Url.Action("ProjectMemberList")
}))
{
    <table border="0" cellpadding="0" cellspacing="5">
        <thead>
            <tr style="font-weight: bold;">
                <td>
                    Member Name
                </td>
                <td>
                    Experience
                </td>
                <td>
                    Designation
                </td>
            </tr>
        </thead>
        <tbody id="memberData">
        </tbody>
    </table>
    <p>
        @Html.Label("", "Member with experience greater than : ")
        @Html.DropDownList("experience", new SelectList(new[] { "All", "1", "2", "3", "4", "5", "6", "7", "8", "9" }, (Model ?? "All")))
        <input type="submit" name="Submit" value="Submit" />
    </p>   
   
}

The ProjectMemberList view will automatically use the /Views/Shared/_Layout.cshtml as the layout/master page which is specified in the /Views/_ViewStart.cshtml file.

In order to run invoke the specific action by default, have modified the RegisterRoutes method of MvcApplication class in the Global.asax.cs file as follows:

Snippet 5 (Default Route - Global.asax.cs)

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "ProjectMemberDetails", action = "ProjectMemberList", id = UrlParameter.Optional } // Parameter defaults
    );

}

After doing the above changes, when the application is run, the URL ProjectMemberDetails/ProjectMemberList is invoked which in turn invokes the ProjectMemberList action in the ProjectMemberDetailsController. The ProjectMemberList() action returns the related view and this execution happens when the page is first rendered. When the page is rendered, the script we specified in the $(document).ready(...); will be executed. Since we've made a jQuery AJAX call over there with type "POST" and URL("ProjectMemberDetails/ProjectMemberList"), it causes an AJAX call over our action ProjectMemberList(string experience) with attribute [HttpPost] which returns the required result in JSON format. The jQuery script, handles the returned result with the success callback method we specified, which renders the data using the jQuery template on the client side.

The main thing need to be noted is the ProjectMemberList(string experience) action in the ProjectMemberDetailsController which returns the result in the JSON format(JsonResult). Also our view is designed in such a way that the specific action is invoked only using the AJAX call.

You might have also observed that, a predefined dropdown list and a submit button are accompanied inside the AJAX Form represented by @using (Ajax.BeginForm(..)){...} with relevant AjaxOptions as parameter. This AJAX Form ensures that every submit made through the Form will be made as AJAX request. Hence if any submit is made through the submit button click, the ProjectMemberList action specified in the AjaxOptions is invoked passing the option selected in the dropdown list. It is the ASP.NET MVC framework that renders the parameter value, since the parameter specified is same as the name of the dropdown list.

Summary
As a general practice, in the above specified scenarios, the first time when the view is rendered (as the AJAX call won't happen), we'll be using the partial view for rendering the templated region and as we used AJAX Forms, further submit will be directed as AJAX calls. But here, I've specified an example of making an AJAX request from jQuery inside the $(document).ready(...);, because several developers having questions about raising the AJAX request during the initial rendering of the view, which is also answered here.

References
http://api.jquery.com/jQuery.ajax/


Update - 05Nov2011 (Representing the implementation with {{each}} template tag and handling date)

Based on the question asked, I'll specify the modification need to be done to the snippets above in order to see the implementation of {{each}} template tag and displaying date values.

Scenarios included : Have added two more columns Technical Expertise and Date of Joining for display and modified the sample data based on that.
In the case of technical expertise, I receive the list of string values and display each item in the list inside the div element.
In the case of joining date, the received date need to be converted to Date() type in javascript and then formatted accordingly. There exists several ways to achieve that. For this sample I'll use the way specified in one of the stackoverflow.com questions. Here are the refered links - http://stackoverflow.com/questions/206384/how-to-format-a-json-date and http://blog.stevenlevithan.com/archives/date-time-format.

Following are the changes need to be done in the above specified snippets to view the updated example.

Changes in Snippet 1(Model - Employee)
Add two more properties.

public class Employee
{
    public string EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int Experience { get; set; }
    public string Designation { get; set; }
    public List<string> TechnicalExpertise { get; set; }
    public DateTime JoiningDate { get; set; }
}

Changes in Snippet 2 (SampleData)
Alter the LoadProjectMemberList methods as follows.

private void LoadProjectMemberList()
{
    projectMemberList = new List<Employee>();

    projectMemberList.Add(new Employee { EmployeeId = "E1001", EmployeeName = "Member1", Experience = 7, Designation = "Project Lead", TechnicalExpertise = new List<string> { "ASP.NET", "C#", "Silverlight" }, JoiningDate = DateTime.Now.AddYears(-4) });
    projectMemberList.Add(new Employee { EmployeeId = "E1002", EmployeeName = "Member2", Experience = 4, Designation = "SSE", TechnicalExpertise = new List<string> { "ASP.NET", "C#" }, JoiningDate = DateTime.Now.AddYears(-2) });
    projectMemberList.Add(new Employee { EmployeeId = "E1003", EmployeeName = "Member3", Experience = 9, Designation = "Tech Lead", TechnicalExpertise = new List<string> { "ASP.NET", "C#", "Silverlight" }, JoiningDate = DateTime.Now.AddYears(-6) });
    projectMemberList.Add(new Employee { EmployeeId = "E1004", EmployeeName = "Member4", Experience = 3, Designation = "SE", TechnicalExpertise = new List<string> { "ASP.NET", "VB.NET" }, JoiningDate = DateTime.Now.AddYears(-3) });
    projectMemberList.Add(new Employee { EmployeeId = "E1005", EmployeeName = "Member5", Experience = 5, Designation = "Team Lead", TechnicalExpertise = new List<string> { "ASP.NET", "C#" }, JoiningDate = DateTime.Now.AddYears(-4) });

}

Changes in Snippet 4 (ProjectMemberList)
Download and add the "date.format.js" file from http://blog.stevenlevithan.com/archives/date-time-format. Then add the script reference in the page.
In our case it is


<script type="text/javascript" src="@Url.Content("~/Content/MVC3TestApp2/Scripts/date.format.js")"></script>

Replace the related matching items with the following snippets.
Replacement 1:

<script id="memberDetailTemplate" type="text/html">
    <tr>
        <td>
            ${EmployeeName}
        </td>
        <td>
            ${Experience}
        </td>
        <td>
        {{if Designation == 'Tech Lead'}}
        <span style="color:Green; font-weight: bold;">${Designation}</span>
        {{else}}
        <span style="color:Blue;">${Designation}</span>
        {{/if}}            
        </td>
        <td>
        {{each(i,technology) TechnicalExpertise}}
            <div style="font-style:italic;border-width : 1px; border-style: dotted;">
            ${i + 1}. ${technology}
            </div>
        {{/each}}
        </td>
        <td>
            ${FormattedDate}
        </td>
    </tr>  
</script>

Replacement 2:

function jsonProjectMemberListSuccessCallback(data) {
    var targetElement = $('#memberData');

    targetElement.empty();
    
    for (var i in data) {
        var date = eval(data[i].JoiningDate.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
        var formattedDate = date.format("m/dd/yyyy");
        data[i].FormattedDate = formattedDate;
    }

    $("#memberDetailTemplate").tmpl(data).appendTo('#memberData');
}


Replacement 3:

<table border="0" cellpadding="0" cellspacing="5">
    <thead>
        <tr>
            <th>
                Member Name
            </th>
            <th>
                Experience
            </th>
            <th>
                Designation
            </th>
            <th>
                Technical Expertise
            </th>
            <th>
                Date of Joining
            </th>
        </tr>
    </thead>
    <tbody id="memberData">
    </tbody>
</table>


Now in the resultant you can see the respecitve columns related values.

ASP.NET MVC 3 and jQuery templates - Part1

In .Net and jQuery, templates are nothing but specification of a format/structure in which the associated data need to be represented. Developers who worked with ASP.NET controls like GiridView, ListView, Repeater... would have felt the power of templates already. To achieve the power of templates in client side jQuery templates comes in a handy form.

It is easy to understand the core idea on the implementation of jQuery templates with the snippet in this post. To understand the complete details on jQuery template please visit here. Now I'll provide snippet which helps you to understand how to use the jQuery templates.

Snippet 1(General html snippet describing the core jQuery template implementation)

<!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>jQuery template core implementation</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
    <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
    <script id="memberDetailsTemplate" type="text/html">
            <tr>
                <td>
                    ${MemberName}
                </td>
                <td>
                    ${Designation}
                </td>
            </tr>

    </script>
    <script type="text/javascript">
        function applyTemplate() {
            var memberData = [
            { MemberName: "Member1", Designation: "Project Lead" },
            { MemberName: "Member2", Designation: "Tech Lead"}];

            $('#memberDetailsTemplate').tmpl(memberData).appendTo('#memberDetails');
        }

        $(document).ready(function () {
            applyTemplate();
        });
    </script>
</head>
<body>
    <table border="0" cellpadding="2" cellspacing="5">
        <thead>
            <tr style="font-weight:bold;">
                <td>
                    Member Name
                </td>
                <td>
                    Designation
                </td>
            </tr>
        </thead>
        <tbody id="memberDetails">
        </tbody>
    </table>
</body>
</html>


$('#memberDetailsTemplate').tmpl(memberData).appendTo('#memberDetails'); is the key statement that applies the template. Remaining are self explanatory. If the bound data is an array of object, then  the template will be repeated for each item in the array.

Three basic items required for applying jQuery template:
  1. template : Selector that specifies the template. $('#memberDetailsTemplate') in our case.
  2. data : Data to which the template need to be applied. memberData in our case.
  3. target : Selector that specifies the target element. ('#memberDetails') in our case.

.tmpl() is the method that help us achieving the template applied to the data. .appendTo() is one of the method that can be used in conjunction with the object(jQuery collection) returned from .tmpl().
So the statement specifies apply template $('#memberDetailsTemplate') over the data memberData and append the resultant to the ('#memberDetails').

Also, I've used the ${} template tag to read the value of the relevant property. Apart from this, there exists other template tags like {{if}}, {{else}}, {{each}}, {{html}}, {{tmpl}}, {{wrap}}. More details on those template tags can be got from http://api.jquery.com/category/plugins/templates/. We can also create named templates using .template() which you'll find helpful when using more number of templates frequently.

In this post, we just had an introduction for understanding the core idea behind jQuery templates. Part 2 focuses our topic of implementing the jQuery templates using ASP.NET MVC 3.

References
http://api.jquery.com/category/plugins/templates/

Saturday, August 6, 2011

Silverlight - Dependency property CLR wrapper setter/getter not executed

Several Silverlight developers raise this as issue when they first start implementing dependency properties in their custom controls in Silverlight. While developing custom controls when there is a need to expose a property that is target of some binding, animation ...., developers will end up in creating a dependency property of some specific type. For details on dependency properties, refer to the msdn documentation.

It is the CLR wrapper which is exposed in such a way that the values are get from or set to the dependency property identifier. The basic thumb rule for creating a dependency property is the hosting class should inherit from DependencyObject. DependencyObject is the one which stores and evaluates the value of dependency properties. DependencyObject exposes the GetValue() and SetValue() methods for storing and retrieving the values of related dependency properties. Hence the CLR wrappers will hold the GetValue() and SetValue() methods in their getter and setter respectively.

Any XAML binding expressions will be specified to the exposed CLR wrapper for binding values to the related dependency property. Ok, now think of a situation where we need to place some manipulation logic when the value of the dependency property is set or changes. When similar case arise for plain CLR properties, we'll obviously place the manipulation logic in the setter of the property. If we try to do the same in dependency property - CLR wrapper, we'll end up in the method not getting called as the CLR wrapper setter won't get executed. Actually the XAML processing engine is capable of interacting with the Silverlight property system directly and get or set the value of the related dependency property with the help of DependencyObject.

Hence if at all you want to have the logic executed when the value of dependency property changes, stuff it in the PropertyChangedCallback of the property metadata. Following is a brief sample on this.

Snippet: (Dependency property with PropertyChangedCallback)

public class MyCustomControl : Control
{
    public MyCustomControl()
    {
        this.DefaultStyleKey = typeof(MyCustomControl);
    }

    #region Dependency property with PropertyChangedCallback

    public string DisplayMessage
    {
        get
        {
            return (string)GetValue(DisplayMessageProperty);
        }
        set
        {
            SetValue(DisplayMessageProperty, value);

        }
    }

    public static readonly DependencyProperty DisplayMessageProperty =
        DependencyProperty.Register("DisplayMessage", typeof(string), typeof(MyCustomControl), new PropertyMetadata(string.Empty, OnDisplayMessageChanged));

    private static void OnDisplayMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Value change manipulation logic goes here......
    }

    #endregion
}


Placing additional logic in the CLR wrappers other than GetValue() and SetValue() should be avoided to eradicate any discrepancies.

References
http://msdn.microsoft.com/en-us/library/cc221408(v=vs.95).aspx
http://msdn.microsoft.com/en-us/library/cc903933(v=vs.95).aspx

Monday, August 1, 2011

Siverlight 4 - Using DependencyObjects or INotifyPropertyChanged as data objects / ViewModel

Making conviencing decision on representing data objects as whether to derive from DependencyObject or implement from INotifyPropertyChanged can sometimes become a daunting task. When implementing MVVM pattern this question arises while representing the ViewModel.
DependencyObject provides support for handling dependency properties. It is the dependency property which is capable of handling the data binding even through XAML (markup) extensions. There is no need for the manually notify the change in the property value, since the dependency property system automatically notifies the changes in the property.

Snippet 1 (Dependency property)

public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(ParameterMapControl), null);

public string Value
{
    get
    {
        return (String)GetValue(ValueProperty);
    }
    set
    {
        SetValue(ValueProperty, value);
    }
}



Snippet 2 (INotifyPropertyChanged)

public class SampleViewModel : INotifyPropertyChanged
{
    private string reportName;

    public string ReportName
    {
        get { return reportName; }
        set
        {
            reportName = value;
            NotifyPropertyChanged("ReportName");
        }
    }


    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #endregion
}


Ok now think of in a different perspective, if the ViewModel is derived from the DependencyObject, exposed a dependency property and it is bind to the control in UI, any change in the property will notify the control. As an alternate we can implement the ViewModel from INotifyPropertyChanged which is usually represented as Plain Old CLR Objects (POCO) and manually provide the mechanism to notify the property changed.

The evaluation of property value, usage of resources (like memory) and the handling of binding sequence are well optimised to handle by the DependencyObject. Hence using DependencyObject to build data objects is not wrong. But we should also consider other factors.

Case 1
When we use INotifyPropertyChanged (POCO model) for data objects, in general the change notification code will be placed in the setter of the specific property. Also, the property change notification can be raised whenever required. This is especially helpful for read-only properties. While developing view model, several times we might be in a situation to specify a read-only property. For example, we can specify a read-only property which holds the functionality that represents a collection in sorted order and each and every time the original collection got changed, will trigger the change notification for the related read-only property.  But dealing this situation with DependencyObject is not pretty straightforward.

Case 2
Serialization of ViewModel will be your choice lot of time when you want to persist the state of the ViewModel for cases like reverting the object to a particular/previous state. Serialization mechanisms can be achieved over POCO easily where with DependencyObject,  we can't to do so.

Case 3
Passing as parameter to other services also favors POCO.

Case 4
Code readability, maintainability and flexibility are some of the main tenet of coding. DependencyObject lacks in these items when the ViewMode / data item goes a bit complex. Hence POCO is preferable here.

Summary
From the above, we can infer that implementing INotifyPropertyChanged for data items is handy in most of the cases. Dependency properties support great if it is the target of binding, animation, styles, template binding, etc, which will be very much helpful for us when we create custom controls.
Creative Commons License
This work by Tito is licensed under a Creative Commons Attribution 3.0 Unported License.