Showing posts with label MVC3. Show all posts
Showing posts with label MVC3. Show all posts

Saturday, October 27, 2012

ASP.NET MVC ~ JSON decimal binding problem

With ASP.NET MVC, we will face problem when mapping JSON decimal values in an AJAX call to the model. For example consider the following class and the action method:

public class MyClass {
  
public decimal decValue1 { get; set; }
  
public int intValue1 { get; set; }
  
public decimal decValue2 { get; set; }
}

public ActionResult MyMethod(MyClass mc) {
  
return View();
}

and assume the following jquery ajax call:

$.ajax({
   type
: "POST",
   url
: "/Default/MyMethod",
   contentType
:'application/json',
   data
:JSON.stringify({decValue1:21.00,intValue1:3,decValue2:6.36})
});

On executing the above code, we will notice that the value for decValue1 will not be binded properly and that it will hold a value of 0. The reason is that the method JSON.stringify converts the value as follows before actually posting:

{"decValue1":21,"intValue1":3,"decValue2":6.36}

The default model binding behaviour believes the value of decValue1 to be of type integer (21) and therefore ignores to map this value to the destination type which is decimal. In order to overcome this problem, we will have to create our custom decimal binder and then register that in the application start event. The following is the code provided by Phil Haack to manage the custom binding of decimal types:

using System;
using System.Globalization;
using System.Web.Mvc;

public class DecimalModelBinder : IModelBinder
{
                  public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
                  {
                         ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                         ModelState modelState = new ModelState { Value = valueResult };
                         object actualValue = null;

                         try
                        {
                                             actualValue = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture);
                         }
                        catch (FormatException e)
                        {
                                             modelState.Errors.Add(e);
                         }

                         bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
                         return actualValue;
                  }
}

and then we should register this custom decimal binder class in the application start event in the Global.asax.cs file as follows:

protected void Application_Start() 
{
    AreaRegistration.RegisterAllAreas();
    
    ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
 
    // All that other stuff you usually put in here...
}

Now, if we execute the same code, we should see the values mapped properly.

Sunday, July 08, 2012

Delivering Compressed and Combined files for MVC 3 applications

It is very difficult to stay in the race without delivering application that performs “The Best” in the web world. To help us be in the race, we have lot of resources available in the internet to search for and plug in to our web application to gain optimal performance. One such tool is Squish It.

SquishIt is a framework for ASP.NET web application that compresses and combines javascript and css files. There are lot more options available with the SquishIt framework, but let’s walk-through the quick process of setting up the framework for ASP.NET MVC 3 application to compress and combine the css and javascript files.

Ok here we go…

1.       Download the latest framework from the GitHub from the following location: https://github.com/jetheredge/SquishIt/downloads

2.       Extract the zip file and reference the SquishIt.Framework.dll and SquishIt.Mvc.dll in your MVC application.
Note: If the dlls are not available in the bin folder of the extracted zip file, then you will have to open the solution in VS and built it (in release mode) and then reference the dlls in your MVC application.

3.       Next open the page (cshtml) where you have references to javascript and css files

4.       Add the following library references at the top of the cshtml page:

@using SquishIt.Framework
@using SquishIt.Mvc

5.       Next we have to transform the code that references the css files from:

<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
       <link href="@Url.Content("~/Content/ jquery.alerts.css")" rel="stylesheet" type="text/css" />
       <link href="@Url.Content("~/Content/bootstrap.css")" rel="stylesheet" type="text/css" />

                to

                @(Bundle.Css()
            .Add("~/Content/Site.css")
            .Add("~/Content/jquery.alerts.css")
            .Add("~/Content/bootstrap.css")
            .ForceRelease()
            .MvcRender("~/Content/Site_#.css")
       )

6.       And then we transform the code that references the javascript files from:

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>

                to           

       @(Bundle.JavaScript()
            .Add("~/Scripts/jquery.validate.min.js")
            .Add("~/Scripts/jquery-ui-1.8.11.min.js")
            .Add("~/Scripts/MicrosoftAjax.js")
            .ForceRelease()
            .MvcRender("~/scripts/combined_#.js")
)

And that’s it! Go ahead and run your application. Open the Firefox YSlow plugin and verify the number of requests for the css and javascript files. It should be two. Also, you would find that the size of the output file is a reduced one.

Happy programming!!!


Monday, July 02, 2012

MVC 3 Get the Html ID of a control for jQuery calls

jQuery makes the life of web developer simpler by addressing most of the browser compatibility issues. Every developer wants to make use of jQuery library to leave (most of) the browser related compatibilities to be taken care of by jQuery and concentrates on the actual requirements instead of worrying about other factors.

Integration of jQuery in any web project is as easier as it can be. The only important thing is to carefully pass the correct or appropriate id to jQuery calls. It is easier to view the generated source and hard code the corresponding ID to the jQuery calls. Ofcourse this would work and good for short term projects however for long term projects hard coding is not the best idea and nor is it recommended.

With traditional ASP.NET application, we use the following method to get hold of the Html ID that will  be generated for a control:

var id = $(“#<%=aspNetDotnetControl.ClientID %”>

This technique doesn’t work with ASP.NET MVC architecture. The following is one of the easiest way to do this in MVC 3:

1.       Define the extension method for the HtmlHelper class to return the fully qualified name for the given html (partial) field
2.       Define another extension method that just takes the fully qualified name and return the ID of the HTML element

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"),
        System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public static string NameFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return htmlHelper != null ? htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(ExpressionHelper.GetExpressionText(expression)) : string.Empty;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"),
        System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
        public static string IdFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            return HtmlHelper.GenerateIdFromName(NameFor(htmlHelper, expression));
        }

                After defining the above two extension methods, we are now ready to make use of it in our cshtml files as follows:

                $('#@Html.IdFor(m => m.Service.Name)')

       And that’s it.