Application Development

ASP.NET MVC Cascading DropDownLists

Creating DropDownLists using WebForms is easy enough, for those who are venturing into the the world of MVC this may not be as straight forward.

I’ll be using the classic scenario of Cars and their related makes and models.

CarController.cs

public class CarFormViewModel
{
MakeModelRepository makeModelRepository =
    new MakeModelRepository();

private string _carMake = "";

public Car Car { get; private set; }
public SelectList CarMakes { get; private set; }
public SelectList CarModels { get; private set; }
public string CarMake
{
get { return _carMake; }
set { _carMake = value; }
}

// Constructor
public CarFormViewModel(Car car)
{
Car = car;
CarMakes = new SelectList(makeModelRepository.
        GetCarMakes(), "Value", "Text");

if (car.CarMakeModelId > 0)
CarMake = car.CarMakeModel.CarMake;

CarModels = new SelectList(makeModelRepository.
        GetCarModels(CarMake), "Value", "Text", Car.CarMakeModelId);
}
}

Something to be aware of is the use of valueSelected when defining your SelectList, make sure your view items e.g. DropDownList names match your database field names. I found the selected value was not being set correctly when editing a records.

CarForm.aspx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl
<Vehicles.Controllers.CarFormViewModel>" %>

<script type="text/javascript">
$(function() {
$("#CarMake").change(function() {
var carMake = $("#CarMake > option:selected").attr("value");
var urlAction = "<%= Url.Action("FindCarModels", "Car") %>";
$.getJSON(urlAction, { carMake: carMake }, function(data) {
$("#CarMakeModelId").addItems(data);
});
});
});
</script>

<%= Html.ValidationSummary("Edit was unsuccessful. Please correct
the errors and try again.") %>
<%
using (Html.BeginForm())
{%>
<fieldset>
<
legend>Car</legend>
<
p>
<
label for="CarMake">
Make:</label>
<%= Html.DropDownList("CarMake", Model.CarMakes) %>
<%= Html.ValidationMessage("CarMake", "*") %>
</p>
<
p>
<
label for="CarMakeModelId">
Model:</label>
<%= Html.DropDownList("CarMakeModelId", Model.CarModels) %>
<%= Html.ValidationMessage("CarMakeModelId", "*") %>
</p>
<
p>
<
input type="submit" value="Save" />
</
p>
</
fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>

Make sure to change the inherits property to reference your new ViewModel. Note the use of the Url.Action helper, this little snippet helps you creates the correct path to your controller action without the use of those dots e.g. …/<controller>/<action>/

jHelper.js

Borrowed from Steve Michelotti.

$.fn.clearSelect = function() {
return this.each(function() {
if (this.tagName == 'SELECT')
this.options.length = 0;
});
}

$.fn.addItems = function(data) {
return this.clearSelect().each(function() {
if (this.tagName == 'SELECT') {
var dropdownList = this;
$.each(data, function(index, optionData) {
var option = new Option(optionData.Text,
                         optionData.Value);

if ($.browser.msie) {
dropdownList.add(option);
}
else {
dropdownList.add(option, null);
}
});
}
});
}

Little helper that clears and adds items to DropDownLists.

Something I found frustrating is when in debug mode a script reference would work find but when running using IIS the script would not load correctly. What you had to do was use those good old dots to get it loading correctly. My tip is to use the ResovleUrl helper.

<script src="<%= ResolveUrl("~/Scripts/jquery-1.3.1.js") %>" 
type="text/javascript"></script>

<
script src="<%= ResolveUrl("~/Scripts/jHelper.js") %>"
type="text/javascript"></script>

There are some workarounds I’ve seen that don’t break intellisense but look a bit messy. I figure I’ve lived without it for this long.

Here is the source code, if there is anything that is unclear or you have any questions feel free to email me.

Linq to SQL basic list/grid view and form view

Lately I've been getting more and more into using Linq to SQL and think it rocks, Linq takes care of all the hard back end database functions so that you can focus on the interesting business logic of fun design and styling. I've been doing some research on the basics of Linq and found that most tutorials only show the List/GridView. However there was not many tutorials on working with Forms. So I have put together this basic tutorial to get you started. I have to give a lot of credit to aDefWebserver for this tutorial http://www.adefwebserver.com/DotNetNukeHELP/LinqTutorial2/LinqTutorial2_3.htm which although it specific to DotNetNuke a lot of the concepts can be learned here.

I have created a very basic database called "Contacts" with a table called "MyContacts", here is a screenshot of this table.

I prefer to set up a new database user now for this specific application so that when it comes to deploying the application your ready to go.

 

Now I will create a New Web Site in Visual Web Developer 2008 Express Edition called "MyContacts"

 In the Database Explorer right button click on the Data Connections root and select Add Connection

Add a new Linq to SQL Classes item called "My_Contacts_DataClass.dbml" under the App_Code folder

Once the My_Contacts_DataClass opens drag the "MyContacts" table onto the data class from the Database Explorer

 

Add a new web form called "List_MyContacts.aspx" for the list/grid view

Add a LinqDataSource from the Data section in the Toolbox to your new List_Mycontacts page and select Configure Data Source

Select the My_contacts_DataClassDataContext object and click next

Click the "Advanced" button and select which options you want to allow from the list/grid view. In this case I only want to allow Delete

Add a GridView from the Data section in the Toolbox to your new List_Mycontacts page and select the LinqDataSource1 as the Data source. Then check Enable Deleting and Selection so that the user can either delete the record directly from the list or select it to view it in the form view mode.

Select the GridView control and open the properties and click on the lightning bolt to see the events. Double click on the SelectedIndexChanged event and enter the following line of code within this SelectedIndexChanged procedure. This code will open the update page with the selected record in the form view.

    protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)

    {

        Response.Redirect("Update_MyContacts.aspx?ContactId=" + Convert.ToInt32(GridView1.SelectedDataKey.Value) + "");

    }

 

Add a new web form called "Update_MyContacts.aspx" for the form view

Add a LinqDataSource from the Data section in the Toolbox to your new Update_Mycontacts page and select Configure Data Source

Select the My_contacts_DataClassDataContext object and click next

Click the "Advanced" button and select which options you want to allow from the list/grid view. Here I want to allow Insert, Update and Delete

Also click on the Where button and select the Contact_Id is equal to the a parameter passed via the query string so that when a user selects an item on the list/grid view page the update form will know which item the user wants to edit. Add the where clause

 

Add a FormView from the Data section in the Toolbox to your new Update_Mycontacts page and select the LinqDataSource1 as the Data source.

That's it now you can open your browser and browse the application. Here is the first page the list/grid view

When you click on the Select link in the grid view the page redirects to the Update page to display the form view in read only mode

 

Now when the user clicks on the Edit link the form will automatically switch into update mode so they can update the data and save it

Now that all of the data access functionality has been automatically created by Linq all you need to focus on is design and logic.

 

Theme Visual Studio your way

After using TextMate to do some Ruby on Rails development I got used to and enjoyed working on a darker themed editor, I've probably come late to the party but you can achieve the effect in Visual Studio by changing your settings.

Enjoy coding more at the same time saving the planet (only if you choose a dark background), I chose Rob Conery's TextMate theme.

Scott Hanselman has compiled a good collection of themes check it out.