Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Using AJAX in Microsoft MVC applications (with Entity Framework)

3.84/5 (11 votes)
11 Jun 2008CPOL4 min read 2   1.6K  
The article shows how to use AJAX in your applications based on the Microsoft MVC Framework.

MvcAjax

Introduction

In this article, I will explain how to use AJAX in MVC applications. I will get data from the database using an Entity Framework. For partial web page updating, I use the fascinating JS framework prototype.

What Do you Need to Start

  1. Visual Studio 2008 (beta)
  2. MVC Framework
  3. ADO.NET Entity Framework
  4. VS 2008 and Microsoft .NET 3.5 SP1
  5. Framework Prototype

Task

I have two drop downs on my page: a list of countries and a list of cities. When I select a country in the first dropdown, the list of cities in the second one should be updated, of course, without reloading the whole page.

Plan

Although the task is trivial, I think it would be better to have some plan of developing.

  1. Database — tables for countries and cities
  2. Entity Framework — interface for accessing the data
  3. Model — getting the lists of countries and cities
  4. Controller — action methods for viewing the main page and transferring objects to views
  5. Views
  6. AJAX (prototype) — JavaScript code for loading data into the dropdowns

Solution

  1. Database — I have created two tables, Country and City. City is connected with Country through CountryCode:

    Tables.gif

  2. Entity Framework — We should generate code for accessing database objects like Country and City. To do that, right click on the Models folder, then click Add ..., and select ADO.NET Entity Data Model. Then, we select the tables from the list: Country, City. After we have clicked the Finish button, the studio generates the model and the classes. To update this model (after creating), you should go to the Model Browser (double click on the .edmx file), click on the root object, and select Update Model from the database.
  3. Model — Let's create two classes — for countries and cities. The first class, StaticData, has a private method for getting the list of cities, and a public property:
    C#
    public class StaticData
    {
        public List<Country> CountryList
        {
            get
            {
                return GetAllCountries();
            }
        }
        private static List<Country> GetAllCountries()
        {
            List<Country> countries = null;
            using (DataCoreConnection context = new DataCoreConnection())
            {
                countries = (from c in context.Country
                             select c).ToList();
            }
            return countries;
        }
    }

    The second class for cities is almost the same, but the constructor takes a parameter, the code for the country that the cities should be selected for:

    C#
    public class Cities
    {
        private string countryCode;
        public Cities(string CountryCode)
        {
            countryCode = CountryCode;
        }
        public List<City> CitiesForCountry
        {
            get
            {
                return GetCitiesForCountry(countryCode);
            }
        }
        private List<City> GetCitiesForCountry(string CountryCode)
        {
            List<City> list = null;
            using (DataCoreConnection context = new DataCoreConnection())
            {
                list = (from c in context.City
                        where c.Country.Code == CountryCode
                        select c).ToList();
            }
            return list;
        }
    }
  4. Controller — We use the existing HomeController because our dropdowns are on the home page. We add only one action method for showing the view that gives the contents for the cities dropdown:
    C#
    public void UpdateCities(string code)
    {
        Cities cities = new Cities(code);
        RenderView("SelectCity", cities);
    }

    Here, we get a list of cities (the object Cities) and pass it to the SelectCity view. Don't forget to add a routing rule into Global.asax:

    C#
    routes.Add(new Route("Home/UpdateCities/{code}", 
    new RouteValueDictionary(new { controller = "Home", action = "UpdateCities" }),
        new MvcRouteHandler()));
  5. Views — We use two views, one for the main page with static data, and one for the contents of the dropdowns with cities. Start from the existing view — Index.aspx. As we should pass the StaticData object to it, our view has to be inherited from not just ViewPage but also from ViewPage<StaticData>:
    C#
    public partial class Index : ViewPage<StaticData>
    {
    }

    Let's show the list of countries on the page itself:

    HTML
    <select id="selCountry" onchange="UpdateCitiesList();">
        <option value="0" selected="selected"><Select a country></option>
    
        <% foreach (var country in ViewData.CountryList)
           { %>
            <option value='<%= country.Code %>'>
            <%= country.Name %>
            </option>
        <% } %>
    
        </select>

    This code is very simple, so it seems to me there is no need to explain it. I just noticed that the ViewData object has the StaticData type, so we can call its members without any casting. The handler UpdateCitiesList() that gets the list of cities will be discussed a little later. Now, let's create one more view for showing the cities:

    C#
    public partial class SelectCity : ViewPage<Cities>
    
    {
    }

    And, add the code generating the contents of the dropdown:

    ASP.NET
    <option value="0"><Select a city></option>
    <% foreach (var city in ViewData.CitiesForCountry)
       { %>
    
    <option value='<%=city.Id %>'><%= city.Name %></option>
    
    <%} %>

    Firstly, we should add a link to the prototype file (I did so on the master page):

    HTML
    <script type="text/javascript" 
      src="<%= Page.ResolveClientUrl("~/Views/Scripts/prototype_p.js") %>"></script>

    Now, we add some code that will get data from the database without reloading the whole page:

    JavaScript
    <script type="text/javascript" language="javascript">
        function UpdateCitiesList()
        {
            if ($('selCountry').value == "0")
                return;
                var url = '/Home/UpdateCities/' + $('selCountry').value;
            new Ajax.Updater('selCities', url,
            {
                method: 'get'
            }
                    );
        }
    </script>

    This code is also very simple. First, we define what element of the dropdown is selected. If it is the "0" element (that only contains the text "Select ..."), we go out from the function. Else we create a URL to call the controller Home and the UpdateCities action method (with the code of the selected country) and call the prototype library object Ajax.Updater. This object allows us to get data in an asynchronous manner, i.e., without reloading the whole page.

    As soon as we select some country, the cities dropdown is updated.

Load and open the solution attached to this article. You may see an empty page, Default.aspx (bug in SP1), or maybe not. Anyway, you need to use this address: localhost:NNN/Home/ to see the result.

Latest Updates

Microsoft launched the 3 version of MVC Prerelease, so you can load it here. Don't forget to load the Readme file (at the bottom of loading page) where you will find the full list of changes. I was trying to make over my project how the Readme advised, and I got the absolutely-compiled-but-absolutely-non-working code (the routing doesn't work so far). So I have created a new project (where the routing works for some reason) and transfered all files there. So you can find a new version of project (for ASP.NET Prerelease 3) at the top of article.

You can find a version of this article in Russian in my blog.

Comments and suggestions are welcome!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)