Due to some e-mails I’ve received this week I am posting a quick tip on how to populate an ASP.NET MVC dropdownlist control using LINQ to SQL. If you haven’t read the Tip#189 about ASP.NET MVC dropdownlist controls, it is a good time to read it.

How to

Create a new ASP.NET MVC Web Application;

Right-click on the Models folder and select Add > New Item;

From the Add New Item dialog, select LINQ to SQL classes. Name it MyModel.dbml and click Add;

Picture 1 - Create a new LINQ to SQL file

Picture 1 - Create a new LINQ to SQL file

Select the connection you want to use on the Server Explorer Window, expand it and select the tables you want to use;

Drag and drop them onto the dbml file surface. For this example I am using a database that has two tables: Product and Category;

Picture 2 - Product and categories tables added to the dbml file

Picture 2 - Product and categories tables added to the dbml file

Right-click the Controllers folder and select Add > Controller. Name it ProductController and hit the Add button;

Picture 3 - New controller class

Picture 3 - New controller class

A new controller class is created it. Open it. We are going to add an action method called Selector that will perform a LINQ query to retrieve a list of products. We are going to save it to the ViewData dictionary and request a view to be rendered;

public class ProductController : Controller
{
    MyModelDataContext _ctx = new MyModelDataContext();

    public ActionResult Selector()
    {
        var products = from prod in _ctx.products
                                select prod;

        ViewData[“ProductList”] = products;

        return View();
    }
}

Right-click the action method we’ve just created and select Add View (or just press ctrl + M, V). On the Add View dialog, name it Selector and keep the first two checkboxes unchecked. Hit the Add button;

Picture 4 - Create the View for our selector

Picture 4 - Create the View for our selector

On the View we are going to use the DropdownList HtmlHelper method to render the dropdownlist control using the list of products added to the ViewData dictionary by our Selector action method. The object used to bind an IEnumerable object to a dropdownlist control is the SelectList. There an explanation about it on Tip #189. We are going also to add a submit button so we can catch the selected item on the controller class. The Html markup will be similar to the following:

<% using (Html.BeginForm()) { %>
    <%= Html.DropDownList(“lstProducts”, new         SelectList((IEnumerable)ViewData[“ProductList”], “ID”, “Name”)) %>
    <input type=”submit” value=”Submit” />
<% } %>

Let’s add an action method that handles the post actions on this view so we can catch the selected product id:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Selector(FormCollection form)
{
    /// Gets the selected product.
    int productID = Convert.ToInt32(form[“lstProducts”]);

    […]
}

Build and run the application. Navigate to http://localhost:<Port Number>/Product/Selector . The dropdownlist control is loaded and displays the product name.

Picture 5 - The product selector in action

Picture 5 - The product selector in action

You may hit the submit button and check the product id on the Selector action method that handles the post action.

It is just a simple example on how to populate the dropdownlist control using LINQ to SQL. Keep in mind that performing queries directly on the controller is not a good practice and tie your application to a specific data source is not maintainable. Check the posts below on how to make you application loosely coupled and how to create a service layer for your application:

On Tip #206 we saw an example on how to create a service layer that may be used by both an ASP.NET MVC web application and a windows client application. The main idea was to show how to code against interfaces and how to consume on an ASP.NET MVC application.

If you have followed my ASP.NET MVC posts you will remember how important the dictionaries are in ASP.NET MVC applications and how UI validation works. If you haven’t read yet, it is a good time to read:

Today we are going to check how to add validation to our service layer and how to communicate back to the service consumer providing a list of messages if something goes wrong. The scenario and examples are the same from the Tip #206.

First of all let’s create our communication mechanism. We are going to provide a dictionary of messages to the consumer application. Again we are going to develop against an interface so you can create a concrete class for each or your applications that handles UI in a way that fits better for each application.

Let’s create an interface called IValidationResult containing methods to either add or remove an entry from a dictionary and a property that returns a Boolean flag indicating whether the operation succeeded or not.

public interface IValidationResult
{
    void Add(string key, string message);
    void Remove(string key);
    bool Succeeded { get; }
    IDictionary Details { get; }
}

Now, let’s change our concrete service class to store an object that implements the IValidationResult interface and change its constructor:

public class ClientStockService : IStockService
{
    private IValidationResult _validationResult;

    public ClientStockService(IValidationResult validationResult)
    {
        this._validationResult = validationResult;
    }

    // Code removed for brevity
}

Now you need to change the StockController class to provide an object that implements the IValidationResult interface. One way to implement it is to create a class that stores the messages in a dictionary that you can use anywhere in your code.

public class ValidationResult : IValidationResult
{
    private IDictionary _validationResult = new HybridDictionary();

    public void Add(string key, string message)
    {
        _validationResult[key] = message;
    }

    public void Remove(string key)
    {
        _validationResult.Remove(key);
    }

    public bool Succeeded
    {
        get
        {
            return _validationResult.Count == 0;
        }
    }

    public IDictionary Details
    {
        get
        {
            return _validationResult;
        }
    }
}

This is an example that may be used in different application types.

Changing the controller class will result in a code similar to the following:

public class StockController : Controller
{
    IValidationResult _validationResult;
    IStockService _stockService;

    public StockController()
    {
        _validationResult = new ValidationResult();
        this._stockService = new ClientStockService(_validationResult);
    }

    // Code removed for brevity
}

It’s usually a good idea to keep concerns separated between layers. Maintenance and scalability are just two of many benefits of doing that.

When developing an ASP.NET MVC web application this is not different. You not only keep the concerns separated via the model, view and controller classes but is important to keep in mind that if you need to reuse some of the operations exposed via the model classes in another application, you cannot tie your code to any application or application type specific feature.

Actually the model is the only part of the MVC design pattern that is free of application type. You cannot develop either a controller or a view without referencing an ASP.NET MVC assembly. So, when you are designing your model classes you can (and you should) keep it completely decoupled from your controller classes.

Scenario

You work as a developer for a financial company that provides stock operations to its clients. The company operates by phone where the clients can talk to an analyst and either buy or sell stocks. The analysts use a .NET windows client application for all related tasks.

The company wants to develop an application where the clients can log on and check their investments and request transactions directly from it. An ASP.NET MVC web application was chosen as the application type and you are responsible for designing it.

Basically all operations, business logic and data access related to the investment transactions are available on the windows client application in a separated assembly from the UI. How can you reuse the code from your ASP.NET MVC application?

How to

We are going to create a service layer that will expose all the necessary operations to both the windows client and the ASP.NET MVC web application.

Our first task is to create an interface where all operations we need to use are defined. If you have a class with the methods you need you can use the Extract Interface feature from Visual Studio 2008 by right-clicking the class and selecting Refactor > Extract Interface. The process is pretty straightforward. Give a name to the new interface, the physical file name and select the methods you want to include in your interface. When it’s done, just click the OK button.

I am not a stock specialist so I am going to add simple methods to our interface just to illustrate:

public interface IStockService
{
    bool BuyStock(int clientID, int quantity, string stockCode, decimal unitPrice);
    bool SellStock(int clientID, int quantity, string stockCode, decimal unitPrice);
    List<Stock> GetAll();
    List<Stock> GetAllByClient(int clientID);
    Stock GetDefinition(string stockCode);
    Stock GetDefinition(string userName, string stockCode);
}

If you have made the refactor of your current application to extract an interface you will notice that the interface keyword has been added to the class definition. You have the first concrete implementation of your interface. Just to illustrate, a simple code:

public class ClientStockService : IStockService
{
    public bool BuyStock(string userName, int quantity, string stockCode)
    {
        /// Code removed for brevity
    }

    public bool SellStock(string userName, int quantity, string stockCode)
    {
        /// Code removed for brevity
    }

    public List<Stock> GetAll()
    {
        /// Code removed for brevity
    }

    public List<Stock> GetAllByClient(string userName)
    {
        /// Code removed for brevity
    }

    public Stock GetDefinition(string stockCode)
    {
        /// Code removed for brevity
    }

    public Stock GetDefinition(string userName, string stockCode)
    {
        /// Code removed for brevity
    }
}

Create a new ASP.NET MVC web application;

Add a reference to the assembly where both the concrete class and the interface are defined;

Right-click the Controllers folder and select Add > Controller;

From the dialog, name it StockController, make sure that the checkbox is not checked and click Add;

Picture 1 - Add Controller Dialog

Picture 1 - Add Controller Dialog

Open the StockController class. We are going to create the methods necessary to buy and sell stocks, get a list of stocks and a list of all stocks that the client has. The code is available below:

public class StockController : Controller
{
    IStockService _stockService;

    public StockController()
        : this(new ClientStockService())
    { }

    public StockController(IStockService service)
    {
        this._stockService = service;
    }

    public ActionResult Index()
    {
        return View(_stockService.GetAll());
    }

    [Authorize]
    public ActionResult MyOptions()
    {
        return View(_stockService.GetAllByClient(this.User.Identity.Name));
    }

    [Authorize]
    public ActionResult Buy(string stockCode)
    {
        return View(_stockService.GetDefinition(stockCode));
    }

    [AcceptVerbs(HttpVerbs.Post), Authorize]
    public ActionResult Buy(int quantity, string stockCode)
    {
        if (!_stockService.BuyStock(this.User.Identity.Name, quantity, stockCode))
            return View(“Error”);

        return RedirectToAction(“Index”);
    }

    [Authorize]
    public ActionResult Sell(string stockCode)
    {
        return View(_stockService.GetDefinition(this.User.Identity.Name, stockCode));
    }

    [AcceptVerbs(HttpVerbs.Post), Authorize]
    public ActionResult Sell(int quantity, string stockCode)
    {
        if (!_stockService.SellStock(this.User.Identity.Name, quantity, stockCode))
            return View(“Error”);

        return RedirectToAction(“Index”);
    }
}

You may have noticed that we are coding against an interface instead of the concrete class. As the same way than the data access we saw on Tip #205 we keep the layers separated. If you develop a new concrete service layer class, you just need to change the instantiation type on the controller class. Thanks to polymorphism!!!!

Tomorrow we are going to improve the code we have seen today to add the validation on the service layer and make it interact with the controller class dictionary.

Stay tuned!

« Newer Posts - Older Posts »

Categories