Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Saturday, December 15, 2012

Asp.Net MVC: Default parameters in action methods

In this article we will simplifies case of default parameter of action methods. These can be possible in 2 ways.

1. Using default value attribute:

The Default Value attribute of System.Componetmodel namespace lets you specify a parameter value which was not container in route values and action method will use that default value.

Public ActionResult  DoStuff(string  name, [DefaultValue(MyEnum.Alpha)] MyEnum enumToUse)
{
//Your Code Here
}

2. Using optional parameter in C# 4.0:

To pass default value in action method, we can also use C#4.0 optional parameter feature.

Public ActionResult  DoStuff(string  name, MyEnum enumToUse=myEnum.Alpha)
{
//Your Code Here
}

We can use both ways to pass default value, but if we are thinking about performance then, need to use second options because, Default value attribute will involve some reflection. I hope this will help you.

Saturday, November 17, 2012

Custom Json Convertor For Nullable Integer Type in MVC

Introduction :

Before a Few Days, I had facing a one problem when I post data to controller in mvc using jquery and serialize data from json to model at that time it will give me give error like "Can not convert string to int".

The above problem generated due to, when I passing data as JavaScript object to controller at that time integer value passed as a blank. So it will consider that blank as string so not able to convert that string to int. But here I am little bit surprise when that model property is nullable type then also it will give me error like this instead of it should consider as null value.

After explore about this problem I got solution which is describe below with example.

Implementation :

To explain above problem I have taken examples of the student Information. First I have added Controller named Student Controller in MVC Application.

In Student Controller, I have added action name index which will return Index View. The controller code will look like below.

   public class StudentController : Controller
    {
        //
        // GET: / Student /

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

After added action in controller, need to add model named Student. Model Class will look like below.

  public class Students
   {
      
        public int? StudentID{get;set;}
        public string StudentName;
        public string Address;
        public string City;
        public DateTime? BirthDate;
   }

After this, I have added view named Index.cshtml. Markup of View which is look like below.

@{
    ViewBag.Title = "Index";
}
<script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")"></script>
    
@model MvcApplication1.Students
<h2>Index</h2>
<table>
    
    <tr>
        <td>
            Student Name
        </td>
        <td>
            @Html.TextBoxFor(model=>model.StudentName)
        </td>
    </tr>
    <tr>
        <td>
            Address
        </td>
        <td>
            @Html.TextBoxFor(model=>model.Address)
        </td>
    </tr>
    <tr>
        <td>
            City
        </td>
        <td>
            @Html.TextBoxFor(model=>model.City)
        </td>
    </tr>
    <tr>
        <td>
            Student Marks
        </td>
        <td>
            @Html.TextBoxFor(model => model.StudentMarks)

        </td>
    </tr>
    <tr>
        <td>Birth Date</td>
        <td>
            @Html.TextBoxFor(model=>model.BirthDate)
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="button" onclick="SaveStudent()" value="SaveStudents"/>

        </td>

    </tr>
</table>

<script type="text/javascript">
    
    function SaveStudent() {
        var data = {
            StudentMarks: $('#StudentMarks').val(),
            StudentName: $('#StudentName').val(),
            Address: $('#Address').val(),
            City: $('#City').val(),
            BirthDate: $('#BirthDate').val()
        }
        $.ajax({
            type: 'POST',
            url: '/Student/SaveStudents',
            data:{Studentdata:JSON.stringify(data)},
            success: function (data) {
                alert("Student Saved Sucessfully");
            },
            dataType: 'JSON'
        });
    }

</script>

Now In a view, Save Student Button click, we are posting data using jquery to controller action named SaveStudent which will accept string as argument and serialize that json string into student model. The Saveaction method code is look like below.

  public JsonResult SaveStudents(string Studentdata)
  {
        Students obj = JsonConvert.DeserializeObject(Studentdata);
            
      return Json(new object { });
  } 

Now, run the application and try to save without enter data in student marks textbox. You will get below JsonReaderException.

Now, to resolve this exception we have two approaches,

In First approach, we are checking before send data to server, if marks field as blank then we passed as zero. This solution is only helpful when we have control to modify json. To implement this approach we need to modify save button JavaScript function which is described below.

  function SaveStudent() 
   {
      var StudentMarks=$('#StudentMarks').val();
      if(StudentMarks==’’)
      {
          StudentMarks=”0”;
      }
       var data = {
          StudentMarks: StudentMarks,
          StudentName: $('#StudentName').val(),
          Address: $('#Address').val(),
          City: $('#City').val(),
          BirthDate: $('#BirthDate').val()
        }
       $.ajax({
          type: 'POST',
          url: '/Student/SaveStudents',
          data:{Studentdata:JSON.stringify(data)},
          success: function (data) {
              alert("Student Saved Sucessfully");
          },
          dataType: 'JSON'
        });
    }

After above changes try to click save button you will get Message like Student Saved Successfully. Here we can check in firebug that Student marks passed as zero when marks field value is blank.

But what happen when we are received json from third party then we need to choose second approach.

In Second Approach, we are not going to change Json object which is passed into Jquery to controller. Here, Exception generates due to when it received blank value for Student Marks Field and it will not consider as a null but it will try converting that blank value into integer.

Now to resolve this issue, we need to define custom json convertor for the Student marks properties. For this, we need to add one class name integerJsonConverter which inherits from the JsonConverter class. Code of the integerJsonConverter is look like below.

public class integerJsonConverter: JsonConverter
    {

        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(int?);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
                return null;
            if (reader.TokenType == JsonToken.Integer)
                return reader.Value;

            if (reader.TokenType == JsonToken.String)
            {
                if (string.IsNullOrEmpty((string)reader.Value))
                    return null;
                int num;
                if (int.TryParse((string)reader.Value, out num))
                    return num;

                throw new JsonReaderException(string.Format("Expected integer, got {0}", reader.Value));
            }
            throw new JsonReaderException(string.Format("Unexcepted token {0}", reader.TokenType));
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            writer.WriteValue(value);
        }
    }

JsonConverter Class has three abstract methods which we need to override in derived class. But here, needs to understand ReadJson Method is important.

In ReadJson method, we checked that if it will receive blank value for integer type field than need to consider as null. After adding above class, we need to change in student model class Student Marks Property. Here, we need to assign JsonConverter attribute which is type of integerJsonConverter. Which is look like below.

public class Students
    {
        [JsonConverter(typeof(integerJsonConverter))]
        public int? StudentMarks{get;set;}
        public string StudentName;
        public string Address;
        public string City;
        public DateTime? BirthDate;
  }

After defined, JsonConverter attribute for student marks, when it will serialize from json to model at that time it will use integerJsonConverter and consider blank value as null. Now run the application and check student Object after json serialize.

It will display null value for the Student Marks Properties.

Conclusion :

The goal of this article is just wants to show you that we can parse blank value as null for integer properties while serialize from json using custom json convertor. Hope this will help you.

Tuesday, October 30, 2012

Display combo with grid using MVC and JQuery.

Introduction :

In most of web application, we have requirement to choose one option from the multiple list at that time we provide combo box to the end user to choose one option. But it will okay when value display into combo box is unique.

But if there is case when display one value is not enough for user to choose right option for this, there is need to give UI like grid, using this user will easily identify which option is right one.

Before few days, I came across very good Jquery pluginfor display Grid in Combo box. At that time, I think this one is great UI to solve above problem. so in this article we will show how to display grid in combo box using jquery easy ui plugin with asp.net mvc.

Implementation :

To implement this, you need download file from Jquery EasyUI.

Now, create new blank mvc application in visual studio and add following files into script folder from the downloaded zip files.

  • jquery-1.7.1.min.js
  • jquery.easyui.min.js

Add following folders/files into content folder of mvc application from the downloaded zip files.

  • easyui.css
  • icon.css
  • images folder
  • Icons folder

After adding files/folders into relevant folders, add one controller named combogrid and also add one action method for this also. Controller code of will look like below.

public class combogridController : Controller
{ 
  Public ActionResult Index()
  {
     Return view();
  }
}

Now, Create new view with name index.cshtml in combogrid Folder and Add reference of .js and .css files which mention above.

    <link href="@Url.Content("~/Content/JQueryEasyUI/demo.css")" rel="stylesheet"/>
    <link href="@Url.Content("~/Content/JQueryEasyUI/easyui.css")" rel="stylesheet"/>
    <link href="@Url.Content("~/Content/JQueryEasyUI/icon.css")" rel="stylesheet"/>
    <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")"></script>
    <script src="@Url.Content("~/Scripts/jquery.easyui.min.js")"></script>

Now I have taken example of the students data display into combo grid. For this, I have created one model class named Students. Model class will looks like a below.

public class Students
{
    public int StudentID;
    public string StudentName;
    public string Address;
    public string City;
}

After that, In View I have placed following html

<h2>ComboBox Plugins  Using JQuery Easy UI.</h2>
<hr />
 <h3>Combo Grid Plugin</h3>   
<select id="drpSelectStudents" name="Students" style="width:290px;"></select>

Now, to display combo with grid, need to write following JavaScript code in view.

<script>
      $(function(){
      $('#drpSelectStudents').combogrid
                     ({
    panelWidth:290,
    value:'006',
                                idField: 'StudentID',
    textField: 'StudentName',
    url: '/combogrid/GetStudentsInfo',
    columns:[[
     { field: 'StudentName', title: 'StudentName', width: 60 },
     { field: 'Address', title: 'Address', width: 100 },
     { field: 'City', title: 'City', width: 120 }
           ]]
    });
          });
  
</script>

Now, in combo grid function I have define StudentId as id field and StudentName as TextField.In url field, need to define controller action which will return json for the datasource of the grid.

To display column in grid, we need to define column field with its field name, title and width parameter.

After define this javascript block, we are define action in controller named GetStudentsInfo which will return Json of Students info.

 public JsonResult GetStudentsInfo()
 {
            List lstStudents = new List();
            lstStudents.Add(new Students { StudentID = 1, StudentName = "ABC", Address = "Main Road", City ="City1"});
            lstStudents.Add(new Students { StudentID = 2, StudentName = "DEF", Address = "Main Road", City = "City2" });
            lstStudents.Add(new Students { StudentID = 3, StudentName = "GHI", Address = "Main Road", City = "City3" });
            lstStudents.Add(new Students { StudentID = 4, StudentName = "JKL", Address = "Main Road", City = "City4" });

            return Json(lstStudents, JsonRequestBehavior.AllowGet);
}

Now run the application,and click on combo you will get combo with grid. Now, Question arise how to get, set and reload values of the combo for this I have added 3 buttons in Views.

<input type="button" value="Get Selected Value" onclick="GetSelectedValue()" />
<input type="button" value="Set Selected Value" onclick="SetSelectedValue()" />
<input type="button" value="Reload" onclick="ReloadValue()" />

And also write following JavaScript in views.

  function ReloadValue() 
  {
           $('#drpSelectStudents').combogrid('grid').datagrid('reload');
  }
  function SetSelectedValue()
  {
    $('#drpSelectStudents').combogrid('setValue', '2');
  }
  function GetSelectedValue() 
  {
    var val = $('#drpSelectStudents').combogrid('getValue');
    alert(val);
  }

Now, again run the application and click on selected value button, in your combo value is set to 2 (because in set value function we are defining value as 2:).).To get value click on the get value button it will display alert with value and to reload value of grid click on reload button.

Conclusion:

I’ve been using this plugin just wants to show you that we can provide more user friendly combo. Hopefully, you'll find this as useful as I have found it for my code.

Sunday, October 7, 2012

Under the hood of @Html.Checkbox()

Yesterday, I have used checkbox helper in my mvc project and found some interesting thing when I saw render html of checkbox helper and access value of checkbox from form collection in controller action. I have described both the things below.

1. CheckBox helper renders 2 input element :-

The CheckBox helper is different from the other controls because it will render two input elements. I have tried with following code in a view.

@Html.Checkbox(‘chkAcceptPolicy’)

And check this code in browser source view it will render following html.



I have probably wondering why the helper renders a hidden input in addition to checkbox input. After thinking over that I have found reason for that the HTML Specification indicates that a browser will submit a value for a checkbox only when checkbox is checked. So as per above example that if chkAcceptPolicy checkbox value is not checked then second input guarantees a value will appear.

2. Form Collection returns value of both input element :-

If we are used model binding approach then it will return value true if value of checkbox is checked otherwise return false.

But here, I have tried to access checkbox value from the Form Collection or Request Object.

        [HttpPost]
        public ActionResult Index(FormCollection fB)
        {
            ViewBag.ValueofCheckBox = fB["chkAccpetPolicy"];
            return View();
        }

Here I am found some interesting thing. If you are checked value of checkbox at that time you are getting value of checkbox from the form collection object as “true,false”.

Why it will contains both value because as per HTML Specifications that a browser will submit a value with comma separated when both element have name same.

So here, chkAcceptPolicy checkbox value is checked and hidden element value is false ndue to this formcollection return value a ‘true,false’.

The goal of this article just show you unique thing about @html.checkbox.Hope this will help you.

Sunday, June 24, 2012

Validate Image Type Using Image GUID in Asp.net

Vaildate image content using System.Drawing.Image class rather than image file extension in asp.net.

Generally we have seen that  every web application have functionality like upload images and store that images into server. But before store images into a server there may be required to validate that image because there may be possible that user may upload malicious scripts.

So to resolve this issue , generally we will check extension of that uploaded file and deind that script file to upload on the server. But this validation is not enough to restrict upload malicious script because user will change the extension of that script and upload that file.

To Resolve this problem , we should check content of that images instead of file extension. Because if user changes file extension , content of that file never changes.

Now in this article we will see how to check content of the images and restrict user to upload malicious script using simple example. To check content of the images we will use System.Drawing.Image class.

Now first step is create simple web application in Visual Studio and Add a WebFrom. Now add one file upload control and button. Markup of your default page is look like below:

<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button Text="Save" runat="server" ID="butSave" onclick="butSave_Click"  />

Now we need to write below code in button click to validate images.

try{
 if (FileUpload1.HasFile){
 System.Drawing.Image image =   System.Drawing.Image.FromStream(FileUpload1.FileContent);
 string FormetType = string.Empty;

 if (image.RawFormat.Guid == System.Drawing.Imaging.ImageFormat.Tiff.Guid)
     FormetType = "TIFF";
 else if (image.RawFormat.Guid == System.Drawing.Imaging.ImageFormat.Gif.Guid)
     FormetType = "GIF";
 else if (image.RawFormat.Guid == System.Drawing.Imaging.ImageFormat.Jpeg.Guid)  
     FormetType = "JPG";
 else if (image.RawFormat.Guid == System.Drawing.Imaging.ImageFormat.Bmp.Guid)
     FormetType = "BMP";
 else if (image.RawFormat.Guid == System.Drawing.Imaging.ImageFormat.Png.Guid)
     FormetType = "PNG";
 else if (image.RawFormat.Guid == System.Drawing.Imaging.ImageFormat.Icon.Guid)
     FormetType = "ICO";
 else
     throw new System.ArgumentException("Invalid File Type");
 lblMessage.Text = "File Formet Is:" + FormetType;
  }
}
catch (System.ArgumentException exp){
  lblMessage.Text="Invalid File";
}
catch (Exception ex){
 lblMessage.Text = ex.Message;
}

In above code we will check that user uploaded any file, if uploaded then we will convert that file into image object.After convert into image object we will check that image object RawFormat.GUID to check file content. We will check and compare that GUID with ImageFormet enum.

Using this we can put some restriction that some image file types are only allowed not other than this.If user changes file extension but their RowFormet GUID’s never change it will remain same even after it’s extension changed.for example, if user changed gif file extension to jpg but it’s GUID never changed it will remain same which is in GIF.

In above example,If user upload any file other than images, it will generate ArgumentException while access it’s row formet property so here we can not allow to file other than images.

The goal of this article just show you that we can validate image using it’s content rather than it’s file extension.

Sunday, December 18, 2011

Drag & Drop Shopping Cart Using ASP.NET MVC and JQuery

In most E-commerce web applications, there are Add to Cart features provided using UI like button or link for add product into a cart. But a few days ago, I came across one good JQuery Shopping Cart Plug-in Example. It provides a feature like you can drag your product and drop into your shopping cart.

After seeing that example, I realized that it can be used to add more interactivity into Add to cart features of E-commerce Web Application. Then I decided to use that plug-in with ASP.NET MVC.

To keep this application simple, I have used just one table in database for display product List and am not covering any other feature like Add Products, etc.

Requirements

To implement this, there is a requirement of two JQuery files:

  1. JQuery-1.6.2
  2. JQuery-ui-1.8.11

You can download this file from Jquery.com or in case you are using VS2010 and MVC3 or MVC4 applications, then that jQuery File is already available in the script folder.

The first step is to create a new MVC application in Visual Studio and check whether in script folder, both Jquery files are available or not. If not, then download that file and add files into the Script folder.

Now, create a database and add the below table named Products:

After creating products table, insert records into tables for display products into the list page. For product image, store image name only in table and create one folder named images into the root level of project, then copy all images into that folder. After that, add connection string of database into webconfig file.

Now, for retrieving data from the database, I have creating one model class named Products into the Models Folder. Product model class code will look like below:

public class Products
{
        public int ProductID ;
        public string ProductName;
        public decimal Price;
        public string ProductImage;
}

Now, create one new folder in the application root level named Data Access and one class into that folder named DALProducts. This class is used for the Direct Database Operation. Code of that class will look like below:

 public class DALProducts
    {
        public List GetProductList()
        {
            SqlConnection _con = new SqlConnection(ConfigurationManager.ConnectionStrings
                ["ProductDataBaseConnection"].ConnectionString);
            try
            {
                if (_con.State != System.Data.ConnectionState.Open)
                    _con.Open();
                SqlCommand _cmd = _con.CreateCommand();
                _cmd.CommandText = "Select * From Products";
                SqlDataReader _reader = _cmd.ExecuteReader();
                List _lstPoducts = new List();
                while (_reader.Read())
                {
                    Products _Products = new Products();
                    _Products.ProductID =Convert.ToInt32(_reader["ProductID"]);
                    _Products.ProductImage = _reader["ProductImage"].ToString();
                    _Products.ProductName = _reader["ProductName"].ToString();
                    _Products.Price = Convert.ToDecimal(_reader["Price"]);
                    _lstPoducts.Add(_Products);
                }
                return _lstPoducts;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (_con.State != System.Data.ConnectionState.Closed)
                    _con.Close();
            }
        }
    }

In the above code, GetProductList method returns a list of the products.

Add one controller into Controller folder named ProductController and add the below code into that:

public class ProductController : Controller
 {
       //
       // GET: /Product/
       public ActionResult Index()
       {
           DataAccess.DALProducts _obj = new DataAccess.DALProducts();
           return View(_obj.GetProductList());
       }
 }

Here, in Index action of the controller, call GetproductList method of DALProduct class and pass list of the products into the view.

Add View name index.aspx at View/Product location and add the following markup into that file:

<%@ Page Language="C#" Inherits="
System.Web.Mvc.ViewPage<IEnumerable<EcommerceApplication.Models.Products>>" %>
      <title>Index</title>
    <script type="text/javascript" src="../../Scripts/jquery-1.6.2.min.js"> </script>
    <script type="text/javascript" src="../../Scripts/jquery-ui-1.8.11.min.js"> </script>
    <style type="text/css">
        body
        {
            font-family: Arial, "Free Sans";
            margin: 0;
            padding: 0;
        }
        #main
        {
            background: #0099cc;
            margin-top: 0;
            padding: 2px 0 4px 0;
            text-align: center;
        }
        #main a
        {
            color: #ffffff;
            text-decoration: none;
            font-size: 12px;
            font-weight: bold;
            font-family: Arial;
        }
        #main a:hover
        {
            text-decoration: underline;
        }
        #item_container
        {
            width: 610px;
            margin: 0 auto;
            margin-top: 10px;
            margin-bottom: 10px;
        }
        .item
        {
            background: #fff;
            float: left;
            padding: 5px;
            margin: 5px;
            cursor: move;
            -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.5);
            -moz-box-shadow: 0 1px 2px rgba(0,0,0,.5);
            box-shadow: 0 1px 2px rgba(0,0,0,.5);
            -webkit-border-radius: .5em;
            -moz-border-radius: .5em;
            border-radius: .5em;
            z-index: 5;
        }
        .title, .price
        {
            display: block;
            text-align: center;
            font-size: 14px;
            letter-spacing: -1px;
            font-weight: bold;
            cursor: move;
        }
        .title
        {
            color: #333;
        }
        .price
        {
            color: #0099cc;
            margin-top: 5px;
            -webkit-border-radius: .5em;
            -moz-border-radius: .5em;
            border-radius: .5em;
        }
        .icart, .icart label
        {
            cursor: e-resize;
        }
        .divrm
        {
            text-align: right;
        }
        .remove
        {
            text-decoration: none;
            cursor: pointer;
            font-weight: bold;
            font-size: 20px;
            position: relative;
            top: -7px;
        }
        .remove:hover
        {
            color: #999;
        }
        .clear
        {
            clear: both;
        }
        #cart_container
        {
            margin: 0 auto;
            width: 495px;
        }
        #cart_title span
        {
            border: 8px solid #666;
            border-bottom-width: 0;
            background: #333;
            display: block;
            float: left;
            color: #fff;
            font-size: 11px;
            font-weight: bold;
            padding: 5px 10px;
            -webkit-border-radius: .5em .5em 0 0;
            -moz-border-radius: .5em .5em 0 0;
            border-radius: .5em .5em 0 0;
        }
        #cart_toolbar
        {
            overflow: hidden;
            border: 8px solid #666;
            height: 190px;
            z-index: -2;
            width: 483px;
            -webkit-border-radius: 0 .5em 0 0;
            -moz-border-radius: 0 .5em 0 0;
            border-radius: 0 .5em 0 0;
            background: #ffffff;
        }
        #cart_items
        {
            height: 190px;
            width: 483px;
            position: relative;
            padding: 0 0 0 2px;
            z-index: 0;
            cursor: e-resize;
            border-width: 0 2px;
        }
        .back
        {
            background: #e9e9e9;
        }
        #navigate
        {
            width: 463px;
            margin: 0 auto;
            border: 8px solid #666;
            border-top-width: 0;
            -webkit-border-radius: 0 0 .5em .5em;
            -moz-border-radius: 0 0 .5em .5em;
            border-radius: 0 0 .5em .5em;
            padding: 10px;
            font-size: 14px;
            background: #333;
            font-weight: bold;
        }
        #nav_left
        {
            float: left;
        }
        #nav_left a
        {
            padding: 4px 8px;
            background: #fff;
            -webkit-border-radius: .5em;
            -moz-border-radius: .5em;
            border-radius: .5em;
            text-decoration: none;
            color: #0099cc;
        }
        #nav_left a:hover
        {
            background: #666;
            color: #fff;
        }
        #nav_right
        {
            float: right;
        }
        .sptext
        {
            background: #ffffff;
            padding: 4px 8px;
            margin-left: 8px;
            -webkit-border-radius: .5em;
            -moz-border-radius: .5em;
            border-radius: .5em;
            color: #666;
        }
        .count
        {
            color: #0099cc;
        }
        .drop-active
        {
            background: #ffff99;
        }
        .drop-hover
        {
            background: #ffff66;
        }
    </style>
    <script type="text/javascript">
        var total_items = 0;
        var total_price = 0;
        $(document).ready(function () {

            $(".item").draggable({
                revert: true
            });
            $("#cart_items").draggable({
                axis: "x"
            });

            $("#cart_items").droppable({
                accept: ".item",
                activeClass: "drop-active",
                hoverClass: "drop-hover",
                drop: function (event, ui) {
                    var item = ui.draggable.html();
                    var itemid = ui.draggable.attr("id");
                    var html = '<div class="item icart">';
                    html = html + '<div class="divrm">';
                    html = html + '<a onclick="remove(this)" 
                class="remove ' + itemid + '">×</a>';
                    html = html + '<div/>' + item + '</div>';
                    $("#cart_items").append(html);

                    // update total items
                    total_items++;
                    $("#citem").html(total_items);

                    // update total price
                    var price = parseInt(ui.draggable.find
                (".price").html().replace("$ ", ""));
                    total_price = total_price + price;
                    $("#cprice").html("$ " + total_price);

                    // expand cart items
                    if (total_items > 4) {
                        $("#cart_items").animate({ width: "+=120" }, 'slow');
                    }
                }
            });

            $("#btn_next").click(function () {
                $("#cart_items").animate({ left: "-=100" }, 100);
                return false;
            });
            $("#btn_prev").click(function () {
                $("#cart_items").animate({ left: "+=100" }, 100);
                return false;
            });
            $("#btn_clear").click(function () {
                $("#cart_items").fadeOut("2000", function () {
                    $(this).html("").fadeIn("fast").css({ left: 0 });
                });
                $("#citem").html("0");
                $("#cprice").html("$ 0");
                total_items = 0;
                total_price = 0;
                return false;
            });
        });
        function remove(el) {
            $(el).hide();
            $(el).parent().parent().effect("highlight", { color: "#ff0000" }, 1000);
            $(el).parent().parent().fadeOut('1000');
            setTimeout(function () {
                $(el).parent().parent().remove();
                // collapse cart items
                if (total_items > 3) {
                    $("#cart_items").animate({ width: "-=120" }, 'slow');
                }
            }, 1100);

            // update total item
            total_items--;
            $("#citem").html(total_items);

            // update totl price
            var price = parseInt($(el).parent().parent().
            find(".price").html().replace("$ ", ""));
            total_price = total_price - price;
            $("#cprice").html("$ " + total_price);
        }
       
    <div id="item_container">
     <% foreach (var item in Model)
           { %>
          <div id="i<%:item.ProductID %>" class="item">
              <img src="%3C%:%20Url.Content%28" />"/>
              <label class="title"><%:item.ProductName%></label>
              <label class="price">$ <%:item.Price %></label>
          </div>
         <% } %>
          <div class="clear"> </div>
      </div>
    <div id="cart_container">
          <div id="cart_title">
              <span>Shopping Cart </span>
              <div class="clear"></div>
          </div>
          <div id="cart_toolbar">
              <div class="back" id="cart_items"></div>
          </div>
          <div id="navigate">
              <div id="nav_left">
                  <a id="btn_prev"><</a>
                  <a id="btn_next">></a>
                  <a id="btn_clear">Clear Cart</a>
              </div>
              <div id="nav_right">
                  <span class="sptext">
                      <label>Items </label><label id="citem" class="count">0</label>
                  </span>
                  <span class="sptext">
                      <label>Price </label><label id="cprice" class="count">$ 0</label>
                  </span>
              </div>
              <div class="clear"></div>
          </div>
      </div>
</body>
</html>

In the above markup, to generate products list we iterate over product models. It will display product name, images and price of that products.

Now run the application and type URL into the browser like http://localhost/Product/. You will get a screen similar to screen shot and drag any product from the product list and add into the cart. You will notice that when you add products into cart, it will automatically add their price into the total amount and number of the items. You can navigate into the Cart and also clear the whole cart using clear Cart button. You can remove a single product using click on the close image on the product images. When you remove single product at that time, it will deduct that price from the Total Amount and decrease one product into total number of the products.

I've been using this plug-in to provide more interactivity to the end user for E-Commerce application. Hopefully, you'll find this as useful as I have found it for my code.

Reference :

http://superdit.com/2011/04/02/drag-drop-shopping-cart-using-jquery/

Tuesday, December 13, 2011

Custom Routes for MVC Application

When you request any page into MVC Application, it will go through the Routing Architecture. Your Routing system will decide your URL pattern. The default routing algorithm is like {controller}/ {action}/ {id} patterns. But it can be possible to change that pattern using Custom Routes.

In this article, we will show how to Create Custom Routes, Debugging Routes and Router Constraints.

Using Default Route

You can configure Route into the Global.aspx's Application Start Event. When you are creating an MVC application, it will already define Default route. Default route can be configured using the following code:

routes.MapRoute(
“Default”,  //Route Name
 “{controller}/{action}/{id}” //Url With Parameters
, new { controller = “Home”, action = “Index”, id = ““} // Parameter Defaults
);

Custom Routes

It is possible to develop an MVC application without creating a Custom Route. But sometimes, there is a situation to change the pattern of URL in which it makes sense to create Custom Routes.

Now, we take a simple example of the custom routes. Imagine that you want to create a blog application and you want to route a request look like: /Archive/12-25-2010.

The first step is to create an empty MVC application. And Add Controller File named BlogController.cs and Add Actions named Archive and insert that code will look like below:

public class BlogController : Controller
    {
        //
        // GET: /Blog/

        public string Archive(DateTime? entryDate)
        {
            return "You wants Blog Entry on Date:=" + entryDate.ToString();
        }


        public ActionResult Insert()
        {
            ViewData["Message"] = "Call From the Insert Action When Get Http Occurs";
            return View();
        }
    }

Now go the Global.asax file and add the following code into the Register Routes method.

//Simple Custom Route with out any Constraints
routes.MapRoute(
                "BlogWithoutConstraint",
                "Archive/{entrydate}",
                new { Controller = "Blog", action = "Archive", });

This code used to add Custom routes and it will match the URL like, Archive/12-25-2010.

Route Constraints

When you create a Custom Route, you can also include route constraints. These constraints are used to restrict the requests to match routes. There are three basic types of constraints:

  1. Regular Expression Constraints
  2. HttpMethod Constraints
  3. CatchAll Values

Regular Expression Constraints

You can use regular expression constraints to check the pattern of the Route and prevent invalid requests. Regular expression is used to check any pattern like Currency, Date, time, etc.

In the Above BlogArchive Example, Url likes Archive/12-25-2010 and Archive/mybirthday.

It will allow. Now we have to prevent parameter which is not a date. So it is possible using regular expression constraints. For that, add the following code into Global.aspx file Register Route method.

//Custom Route With Regular Expression Constraints
            routes.MapRoute(
                "Blog",
                "Archive/{entrydate}",
                new { Controller = "Blog", action = "Archive" }, 
        new { entryDate = @"\d{2}-\d{2}-\d{4}" });

The above code matches the entry date must match pattern of two decimals followed by dash followed by two decimals followed by dash followed by four decimals.

HTTP Method Constraints

You can match route with any type of the HTTP operation like POST, GET, etc. you want to prevent user to access particular URL when GET operation occurs but not POST operation occurs. You can also used AcceptVerbs instead of HttpMethod constraints.

For example, BlogArchive example inserts Action only executes when HTTP GET Operation performs. For that, you have to add the following code into Global.asax file Register Route method.

//Custom Route With HttpMethod Constraint
            routes.MapRoute(
                "HttpMethodConstraintRoute",
                "Blog/Insert",
                new { Controller = "Blog", action = "Insert" }, 
        new { method = new HttpMethodConstraint("GET") });

Catch All Routes

Generally, your URL must match with number of segments, but you want to match your URL, regardless of the number of the segments for that, we have to create Catch-All Parameter. Now take a simple example of the Catch All Routes for that add one controller named CatchAllController and add the following code into the controller.

public class CatchAllController : Controller
{
        //
        // GET: /Sort/
       public string Index(string AllValues)
       {
          string[] PassedValue = AllValues.Split('/');
          return "You are Passing Values:" + String.Join(",", PassedValue);
       }
}

Now to catch all parameters, add the following code into the global.asax file’s register route method.

//Custom Route Catch-All  Routes
      routes.MapRoute(
           "CatchAllRoute",
            "CatchAll/{*AllValues}",
            new { Controller = "CatchAll", action = "Index" });

Now it will match the following URL like, CatchAll/index/1/2/3/4/5/6/7 and CatchAll/a/b/c/d/e/f/g/h/.

A catch-all parameter must appear as the last parameter. Think of a catch-all parameter as a parameter array.

Debugging Routes

After creating Custom Routes, you have to check whether your routes work perfectly with your given URL or not. For that, you have to debug your routes. To Debug Routes, you have to download one DLL from the http://code.haacked.com/mvc-1.0/RouteDebug-Binary.zip and add a reference into your MVC Application.

Now debug route you have to write the following line of the code into the Global.asax Application Start Event.

RouteDebug.RouteDebugger.RewriteRoutesForTesting(RouteTable.Routes);

And run your application. You will see the below screen in your browser:

You can see all the custom routes into All Routes Table and it will show that your browser URL matches with which Routes. If it will match any Routes, it will show true into the Match Current Request Routes, otherwise it will show false. You can check with another URL, for that you have to write URL into the Address Bar.

Now write URL like, CatchAll/1/2/3/4/5/6/. It will match with the Catchall CustomRoutes.

In this way, you can check with other Routes too. It is possible that your URL matches with more than one Route, at that time the first match Routes Executes. Conclusion

The goal of this article is to demonstrate the flexibility of the routing system provided by ASP.NET MVC. Hope this helps!

Sunday, December 4, 2011

Creating your own MVC View Engine For MVC Application

The View engines used in ASP.NET MVC Framework are the Razor View Engine and Web Form View Engine. Razor View engine used .cshtml and .vbhtml. While Web Form View Engine used .aspx to design the layout of the user interface.

The ASP.NET MVC Framework was designed to support alternative view engines and there are already several open source alternatives to the web forms view engine like Nhaml (pronounced enamel), spark, Brail, nVelocity. The different View Engines enable to write your view in different ways.

It is possible to use multiple view engines used in one MVC application. For that, it is required to registering multiple engines in the global.aspx file.

Custom View Engines

It is very simple to create your own custom view engine. When you create your own view engine, you have to just think about how you want to write your views.

The easiest approach to create custom view engine is just derive a new view engine from abstract VirtualPathProviderViewEngine Class. This base class can take care of the all low-level mechanics of finding and caching views.

Now take a simple example of MyViewEngine it will return simple view.

The first step is to create an empty MVC application. Then add a class file named MyViewEngine.cs and inherit that class from VirtualPathProviderViewEngine and override createview and createpartialview methods. These methods return an instance of the MYView Class. Your class will look like below:


 public class MyViewEngine : VirtualPathProviderViewEngine
    {
        public MyViewEngine()
        {
            // Define the location of the View file
            this.ViewLocationFormats = new string[] 
        { "~/Views/{1}/{0}.myview", "~/Views/Shared/{0}.myview" };

            this.PartialViewLocationFormats = new string[] 
        { "~/Views/{1}/{0}.myview", "~/Views/Shared/{0}.myview" };
        }

        protected override IView CreatePartialView
    (ControllerContext controllerContext, string partialPath)
        {
            var physicalpath = controllerContext.HttpContext.Server.MapPath(partialPath);
            return new MyView(physicalpath);
        }

        protected override IView CreateView
    (ControllerContext controllerContext, string viewPath, string masterPath)
        {
            var physicalpath = controllerContext.HttpContext.Server.MapPath(viewPath);
            return new MyView(physicalpath);
        }
    }

Note that in the constructor, we set two properties of the base class. These properties indicate where the view engine should search to find a matching view or partial view.The parameter {1} represents the name of the controller and the parameter {0} represents the name of the action.

Now, create another class named MyView which implements IView interface. This class actually renders the view. MYView class code looks like below:

public class MyView : IView
    {
        private string _viewPhysicalPath;

        public MyView(string ViewPhysicalPath)
        {
            _viewPhysicalPath = ViewPhysicalPath;
        }

        #region IView Members

        public void Render(ViewContext viewContext, System.IO.TextWriter writer)
        {
            //Load File
            string rawcontents = File.ReadAllText(_viewPhysicalPath);

            //Perform Replacements
            string parsedcontents = Parse(rawcontents, viewContext.ViewData);

            writer.Write(parsedcontents);
        }

        #endregion

        public string Parse(string contents, ViewDataDictionary viewdata)
        {
            return Regex.Replace(contents, "\\{(.+)\\}", m => GetMatch(m,viewdata));
        }

        public virtual string GetMatch(Match m, ViewDataDictionary viewdata)
        {
            if (m.Success)
            {
                string key = m.Result("$1");
                if (viewdata.ContainsKey(key))
                {
                    return viewdata[key].ToString();
                }
            }
            return string.Empty;
        }
    }

Render method of the class loads the view files and injects view data into the view, and writes that result into a text writer.

Before use, custom view engine is required to register view engine into Global.asax file using the following code:

protected void Application_Start()
 {
       AreaRegistration.RegisterAllAreas();

       RegisterGlobalFilters(GlobalFilters.Filters);
       RegisterRoutes(RouteTable.Routes);

       //Register your View Engine Here.
       ViewEngines.Engines.Add(new MyViewEngine());
}

Now create a controller file into controller folder named myViewController and define index action into the controller. Your controller class will look like below:

public class myViewController : Controller
 {
      //
     // GET: /myView/
     public ActionResult Index()
     {
         ViewData["Message"] = "Hello World!";
         return View();
     }
}

Now add the simple HTML File into View/MyView/ folder and give the name of the file like index.myview. Your view file markup looks like below:

<html>
<head>
             <title>Index MyView </title>
</head>
<body>{message}
</body>
</html> 

Now run the application and type URL /MyView /Index. You will get output of the Hello World! into the browser. The MyView class loads the index.myview file and replaces {message} with hello world! and renders the HTML Page.

After developing Custom View Engine, we can say that MVC team has done an awesome job at providing a very flexible framework for us to tweak and customize it so it fits our applications.