Ajax.BeginForm: Clear Form After Submit

If you are using ASP.NET MVC, here is a simple tip on how to clear an ajax form after successfully submitting it with a little help from jQuery.

The first step is to get the jQuery Form Plugin, add it to your Scripts folder and then add a script reference to it in your masterpage. jQuery is already included in the projects since the release of the MVC so you don’t need to download and include it.

<script src="../../Scripts/jquery-1.2.6.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.form.js" type="text/javascript"></script>

You can then create a function that will call the clearForm function from the Form Plugin.

<script type="text/javascript">
   function done() {
       $('form').clearForm();
   }
</script>

Now you can use the OnSuccess callback from the Ajax.BeginForm helper to point to the done() function we just created. This function will be called automatically after the form submit completed successfully.

<% using (Ajax.BeginForm("SaveComment", new AjaxOptions { 
         UpdateTargetId = "feedback", 
         InsertionMode = InsertionMode.Replace, 
         OnSuccess = "done"}))
{ %>

Here is the complete code:

<script type="text/javascript">
            function done() {
                $('form').clearForm();
            }
    </script>
    <h2 id="feedback"></h2>
    <fieldset>
        <% using (Ajax.BeginForm("SaveComment", new AjaxOptions { 
               UpdateTargetId = "feedback", 
               InsertionMode = InsertionMode.Replace, 
               OnSuccess = "done"}))
           { %>
            <dl>
                <dd><%= Html.TextBox("Comment.Author")%></dd>
                <dd><input type="submit" title="Submit" /></dd>
            </dl>
        <% } %>
    </fieldset>

 

Sharing Static Field Only Within a Thread

When you use a static field it’s data is shared among any classes using it. That’s something that everyone should know. When programming web applications, every request from the browser will span a new Thread. If you have a static field in a class that is used in a page’s code behind all it’s value will be shared by all requests.

This is great but sometimes you want to share the static field between a bunch of classes that do some business logic when the browser sends a request and you want the static field to share data among all these business logic classes. But when you think that there will be several requests to your site simultaneously (hopefully) you notice that the static field is not only being shared between all business classes in the request but between all business classes in all the requests. You might or might not want this behavior.

In order for a field to have a different value for each thread running, the simplest way is to decorate the static field with a ThreadStaticAttribute attribute.

[ThreadStaticAttribute]
public static int ThreadInfo;

If you never used this attribute here is piece of code that will prove that this really works:

class Program
    {
        static void Main(string[] args)
        {
            ParentClass.MySharedInfo = 5;

            for (int i = 1; i < 3; i++)
            {
                ParameterizedThreadStart pts = new ParameterizedThreadStart(RunTest);
                Thread t = new Thread(pts);

                t.Start(i * 10); 
        }

        }

        public static void RunTest(object val)
        {
            ParentClass.MySharedInfo = (int)val;

            ParentClass cp = new ParentClass();
            cp.Write();
            cp.ChildClass.Write();

            Thread.Sleep(1000);
            cp = new ParentClass();
            cp.Write();
            cp.ChildClass.Write();
        }
    }

    class ParentClass
    {
        [ThreadStaticAttribute]
        public static int MySharedInfo;

        public ChildClass ChildClass { get; set; }

        public ParentClass()
        {
            ChildClass = new ChildClass();    
        }

        public void Write()
        {
            Console.WriteLine("ParentClass ThreadId:{0} / MySharedInfo:{1}",
                Thread.CurrentThread.ManagedThreadId, MySharedInfo);
        }
    }

    class ChildClass
    {
        public void Write()
        {
            Console.WriteLine("ChildClass ThreadId:{0} / MySharedInfo:{1}", 
                Thread.CurrentThread.ManagedThreadId, ParentClass.MySharedInfo);
        }
    }

The code above defines two classes: ParentClass and ChildClass. ParentClass has a static field decorated with the ThreadStaticAttribute attribute and an instance of a ChildClass. The Main method set’s the static filed to 5. Then a loop will start two Threads and create a new ParentClass in each of them. The static field value is set to different values. The class will print the static field value from the ParentClass and from the ChildClass two times. Between the first and the second time the value is printed there is a Thread.Sleep of 1 second. This pause shows that each thread maintains it’s own value.

c#

jQuery Intellisense in VS 2008

Microsoft has shipped a patch to Visual Studio 2008 and Visual Web Developer 2008 Express that enables intellisense support for jQuery and will allow developers to add configuration information to other libraries such as Prototype so that they too can have the intellisense support. Read more about it in ScottGu’s Blog

ToDataTable Method for Linq Queries Results

When you query a DataTable using Linq the normal result will be an IEnumerable, which is not a DataTable (obviously). If you need a DataTable as a result you already have an extension method called CopyToDataTable which will turn your IEnumerable into a new DataTable. Although if you want to join two DataTables and the merge the DataRows into a new Anonymous Type the CopyToDataTable will not help you. Let’s see how to create a helper method that will transform an IEnumerable of anonymous types into a new DataTable.

First let’s create two DataTables: Person and Job. Here’s the code:

DataTable dtPerson;
DataTable dtJob;

dtPerson= new DataTable("Person");
DataColumn dc;

dc = new DataColumn("Id", typeof(int));
dtPerson.Columns.Add(dc);

dc = new DataColumn("Name", typeof(string));
dtPerson.Columns.Add(dc);

dc = new DataColumn("Age", typeof(int));
dtPerson.Columns.Add(dc);

//JOB DataTable
dtJob = new DataTable("Job");

dc = new DataColumn("PersonId", typeof(int));
dtJob.Columns.Add(dc);

dc = new DataColumn("Position", typeof(string));
dtJob.Columns.Add(dc);

Here is the code to populate the DataTables:

DataRow dr = dtPerson.NewRow();
dr[0] = 1;
dr[1] = "Gabriel";
dr[2] = 31;
dtPerson.Rows.Add(dr);

dr = dtPerson.NewRow();
dr[0] = 2;
dr[1] = "Elisa";
dr[2] = 27;
dtPerson.Rows.Add(dr);

dr = dtJob.NewRow();
dr[0] = 1;
dr[1] = "Programmer";
dtJob.Rows.Add(dr);

dr = dtJob.NewRow();
dr[0] = 2;
dr[1] = "Manager";
dtJob.Rows.Add(dr);

Now let’s write a Linq query to join these two DataTables:

var query = from p in dtPerson.AsEnumerable()
             join j in dtJob.AsEnumerable() on p.Field<int>("Id") equals j.Field<int>("PersonId")
             select new
             {
                 Id = p.Field<int>("Id"),
                 Name = p.Field<string>("Name"),
                 Job = j.Field<string>("Position")
             };

Notice that the result of the query is an IEnumerable of an anonymous type with three properties (Id, Name and Position) which is a merge of our two DataTables data. Now for the helper method that will convert this result to a new DataTable. The base of this idea is in my previous article on using reflection on anonymous types. I’ll use this principle to inspect the properties of the anonymous type and create new DataColumns for the new DataTable. After that all it’s needed is iterating over the results creating new DataRows. Here’s the method:

public static DataTable ToDataTable(this IEnumerable objectList)
{
    //if the result is null or if the number of
    //objects is less then 1, return null
    if (objectList == null || 
        objectList.OfType<object>().Count() < 1)
    {
        return null;
    }
    //create a new list based on the IEnumerable
    List<object> list = new List<object>(objectList.OfType<object>());

    //take the first object in the list
    object o = list[0];
    //get the type of the object
    Type t = o.GetType();
    //read all the info of the properties
    PropertyInfo[] properties = t.GetProperties();

    DataTable dt = new DataTable();
    //for each property create a new column
    //in the DataTable
    foreach (var pi in properties)
    {
        //the new column has the name of the property
        //and it's type
        DataColumn dc = new DataColumn(pi.Name, pi.PropertyType);
        //add the column to the DataTable
        dt.Columns.Add(dc);
    }

    //add the rows to the DataTable
    foreach (var item in list)
    {
        DataRow dr = dt.NewRow();
        //each property represents a column 
        //that has to be set
        foreach (var pi in properties)
        {
            dr[pi.Name] = pi.GetValue(item, null);
        }
        dt.Rows.Add(dr);
    }
    return dt;
}

That’s it. The returning DataTable will have three columns (int Id, string Name, string Position). If you want you can download the code for the class here. In this code for download I transformed the ToDataTable method into an extension method.

Reflection on Anonymous Types

Using reflection on anonymous types is just like reflection on any other type.

Consider this simple anonymous object being instantiated:

var anonyObject = new
{
    Name = "Gabriel",
    Age = 31
};

If you want to know all the properties, it’s values and types you can query the object with the reflection classes like this:

//get the type of the anonymous object
Type anonyType = anonyObject.GetType();
//get all the properties info
PropertyInfo[] props = anonyType.GetProperties();
//display each of the properties info
foreach (var prop in props)
{
    Console.WriteLine("Name:{0}, Value:{1}, Type:{2}",prop.Name, 
        prop.GetValue(anonyObject, null), prop.PropertyType);
}

I just wanted to share this code because I’m going to use it in my next article in which I will talk about creating a helper method to transform the result from a Linq query that returns anonymous types to a DataTable.

ASP.NET MVC: ListBox

The Html.ListBox helper is a good choice if you need to represent many-to-many relationships in a form.

Lets say you have a many-to-many between the Posts table and the Categories table. When you are creating a new post you need to select all the categories that it belongs to. When you are editing a post you need to show the categories it already belongs to in order to make a new selection (or not).

 The ListBox would allow you to make all the selections necessary, so the Action and the View for the New Post would need something like this:

Action:

[AcceptVerbs("GET")]
public ActionResult New()
{
        ViewData["Categories"] = _postService.GetCategories();
        return View();
}

View:

<%= Html.ListBox("CategoryList", new MultiSelectList((IList<Category>)ViewData["Categories"], "ID", "Name"))%>

And the View and Action for the Edit would be like this:

Action:

[AcceptVerbs("GET")]
public ActionResult Edit(int? id)
{
        int postId = id ?? 0;
        //get the post that is being edited
        Post post = _postService.GetPost(postId);
        //get all the categories
        ViewData["Categories"] = _postService.GetCategories();
        //get the id's of the categories to which the post belongs
        ViewData["CategoryIDs"] = post.Categories.Select(c => c.ID);
        return View(post);
}

View:

<%= Html.ListBox("CategoryList", new MultiSelectList((IList<Category>)ViewData["Categories"], "ID", "Name", (IEnumerable<int>)ViewData["CategoryIDs"]))%>

Note that this time I had to pass an extra parameter to the ListBox method which is a list of the categories ID’s that are already associated with the Post. This list will be used to make the initial selection in the ListBox rendered in your HTML.

One last thing you need to know is how to get the ID’s of the selected categories back in your action. This is pretty simple as well. The Form will have a CategoryList item that will have a comma separated string with all the selected lines, all you need to do is split this in a array of strings and them save them to the database as you see fit.

string[] selected = Request.Form["CategoryList"].Split(',');

I hope this tip is useful to others that are testing the MVC Framework.

ASP.NET MVC: DropDownList

Here is an example of how to use the Html.DropDownList helper method available in the MVC framework to generate a combo in you page.

Let’s use the Northwind example and say that you want to create a product and in the product for you need to select a category to which this product belongs in a dropdownlist.

The first step is in the select the list of categories in the appropriate controller action. In my case I’m going to use the new Action.

public ActionResult New()
{
    ViewData["CatList"] = new SelectList(_db.Categories.ToList(), "CategoryID", "CategoryName");
    return View();
}

Notice that I used the SelectList class. In this case I used the constructor that takes 3 parameters:

  1. The list of categories I got from my Linq DataContext
  2. The name of the property of the Category class that has the ID value that is going to be stored in the select list and which will be the value that actually is passed to the Product class
  3. The name of the property of the Category class that has the value I want to display to the user

The SelectList class will be used by the DropDownList helper to generate the html code. Here is part of the View code:

...
<tr>
       <td>Category:</td>
       <td><%= Html.DropDownList("CategoryID",(SelectList)ViewData["CatList"]) %></td>
</tr>
...