Finally, a SelectedItems Option (yaaay)

If you're like me you've often pondered why controls like CheckBoxList don't provide a way to get a collection of selected items.  You've always had the option to iterate the Items collection and evaluate the Selected property, but why should that have to be done over and over again?  I want a quick way to get the selected items from a CheckBoxList, ListBox, DropDownList, and RadioButtonList; all items which inherit from ListControl.

The excellent creation of extension methods makes it simple to get the selected items from a ListControl.

using System.Collections.Generic;

using System.Web.UI.WebControls;

 

namespace ListControlExtensions

{

    public static class ListExtensions

    {

        public static List<ListItem> SelectedItems(this ListControl list)

        {

            List<ListItem> items = new List<ListItem>();

            foreach (ListItem item in list.Items)

            {

                if (item.Selected)

                {

                    items.Add(item);

                }

            }

            return items;

        }

    }

}

 

Have you found an alternative to getting the selected items from a ListControl without looping through the Items collection?

kick it on DotNetKicks.com

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

ASP.NET MVC: Store Routes in the Database

Download the sample MVC project for this post
NOTE:  You should have ASP.NET MVC Preview 3 or later installed to run the provided download.

So far I’m a huge fan of the ASP.NET 3.5 MVC framework which is currently released as Preview 3.  Having worked with primarily Microsoft web frameworks MVC provides a refreshing perspective for what I consider an improved tier separation.

An immediate beef I have with ASP.NET MVC is defining the routes in the Global.asax.cs… I can’t change routes without recompiling and deploying code.  I thought it better to configure routes in a more dynamic environment, specifically the database, which is what this post will provide an example for.
I’ve broken the implementation into three main pieces: 

  1. Database schema for storing routes and route default parameters
  2. LINQ to SQL model for accessing the routes
  3. Class for handling route routines

 

Database Schema – “Mvc”

MvcRoutes Table

Routes table design

routeID
– the primary key for a route.
routeName – simply for identification purposes.  This isn’t used in the app.
routePattern – the URL structure of the route.
routeIsActive – turn your route on or off.
routeOrder – routes are executed on a first match basis.  It may be important to order your routes so a more specific pattern is caught first before a more general pattern catches it… similar logic to exception handling.


MvcRoutes Sample Data

Routes table data
 

MvcRouteParams Table

Route parameters table design

paramID
– the primary key and identifier for the route parameter.
routeID – foreign key to the MvcRoutes.RouteID value.
paramKey – route defaults are stored as a Dictionary.  This is the key for a default.
paramValue – the default value for the paramKey.
paramConstraint – a regular expression value specifying allowed values for the parameter
paramDataType – I’m actually not using this right now but it feels right to analyze the expected data type in a more complete sample… or somethingJ.

 

MvcRouteParams Sample Data

Route parameters table data
 

LINQ to SQL Model

The model is super simple… connect to your MVC routing database and drag the MvcRoutes and MvcRouteParams tables to a new LINQ to SQL class.
Route parameters table design
Now we can do some simple queries.
 

Route Helper Class – Routing.cs

The Routing.cs class provides a handful of methods for working with the RouteTable and interaction with the database.  In my project I included a new controller to handle resetting and displaying the routes which utilizes some of these additional methods.
 
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
 
using MvcAltRouting.Models;
 
namespace MvcAltRouting
{
    internal class Routing
    {
        public static RouteCollection Routes
        {
            get { return RouteTable.Routes; }
        }
 
        /// <summary>
        /// Gets the configured routes.
        /// </summary>
        /// <returns></returns>
        public static List<MvcRoute> GetConfiguredRoutes()
        {
            MvcRoutesDataContext db = new MvcRoutesDataContext();
            List<MvcRoute> dbRoutes = (from b in db.MvcRoutes
                                       where b.routeIsActive == true
                                       orderby b.routeOrder
                                       select b).ToList();
            return dbRoutes;
        }
 
        /// <summary>
        /// Clears current and readds application routes.
        /// </summary>
        public static void ResetAppRoutes()
        {
            Routes.Clear();
            SetAppRoutes();
        }
 
        /// <summary>
        /// Sets the application routes.
        /// </summary>
        public static void SetAppRoutes()
        {
            List<MvcRoute> configuredRoutes = GetConfiguredRoutes();
            SetAppRoutes(configuredRoutes);
        }
 
        /// <summary>
        /// Sets the application routes.
        /// </summary>
        /// <param name="configuredRoutes">Collection of routes to add to the application's routing table.</param>
        public static void SetAppRoutes(List<MvcRoute> configuredRoutes)
        {
            //add the routes to the RouteCollection
            foreach (MvcRoute route in configuredRoutes)
            {
                //create RouteValueDictionary objects to add the default values and contraints to the route
                RouteValueDictionary constraints = new RouteValueDictionary();
                RouteValueDictionary routeVals = new RouteValueDictionary();
 
                foreach (MvcRouteParam param in route.MvcRouteParams)
                {
                    routeVals.Add(param.paramKey, param.paramValue);
                    if (!string.IsNullOrEmpty(param.paramConstraint))
                    {
                        constraints.Add(param.paramKey, param.paramConstraint);
                    }
                }
 
                //create the route using the defaults set above
                RouteTable.Routes.Add(new Route(route.routePattern, new MvcRouteHandler())
                {
                    Defaults = routeVals,
                    Constraints = constraints
                });
            }
        }
    }
}
 

Global.asax.cs

Lastly change the Application_Start method to use the new Routing class to populate the application routes, removing the need for the routes defined within the Global.asax.cs.
using System;
 
namespace MvcAltRouting
{
    public class GlobalApplication : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            Routing.SetAppRoutes();
        }
    }
}


That’s It!

Start up the provided project and navigate to the “Display Routes” link.  You can see the routes have been set from the database values we saw from above!

Have you been working with the ASP.NET MVC framework?  If so have you moved the route configuration out of the Global.asax.cs or are you happy with the default configuration for editing routes?
 
Download the sample MVC project for this post
NOTE:  You should have ASP.NET MVC Preview 3 or later installed to run the provided download.

kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

ASP.NET 3.5 Extensions MVC Preview 2 Released

I really liked tinkering with Preview 1 so I'm REALLY excite to get my paws on Preview 2.  You can check out some MVC Preview 2 videos here and download the MVC Preview 2 here.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

.NET Framework 3.5 Info You Might Not Know

I may be the slow guy in the room...  .NET 3.5 installation includes Service Packs for .NET 2.0 SP1 and .NET 3.0 SP1, both of which replace previous versions.  I checked with our IT team and we've apparently not installed 2.0 SP1 "yet".  There's a concern of compatibility as previous upgrades from 1.0 caused some issues (before my time at this company).  I've not personally experienced problems with these in the past and I've worked with .NET since beta versions of 1.0.  If you'd like to do a quick check to see if .NET 2.0 SP1 is installed check out [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727\1033], "SP" should have a value of "00000001".  I checked a machine without .NET 2.0 SP1 and then checked a machine with .NET 3.5 and this holds true.

Check out these other entries from Heath Stewart for more info:

Microsoft .NET Framework 2.0 Service Pack 1, and How to Detect It (Includes 3.5 info.  Not really about detection, but the next link is.  Bad title for the content.)

Detecting Patches in .NET 2.0 and Visual Studio 2005

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

.NET Framework Source Now Available

As promised Microsoft has released some source for the .NET framework although not all libraries are available just yet.  From what I can tell you can currently only view the source through Visual Studio in debug mode.  Funny how MS's recommendation is to put the opening '{' on a new line yet the source I've seen so far has it on the same line as the method sig:).  You can view some details at the following locations:

Scott Guthrie's announcement

Shawn Burke's detailed instructions

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

A Generic JSON Serialization Extension Method Starring DataContractJsonSerializer

Download the sample code for this post. 

In October of 2007 The Gu wrote a ToJSON extension method using the JavaScriptSerializer class.  Since that time the JavaScriptSerializer class has been marked obsolete in favor of DataContractJsonSerializer.  In this post we’ll write an updated ToJSON method to satisfy every JSON extension method fantasy you have.  Quick agenda… the goal is to take a .Net object and convert it in to JSON text which would likely be consumed be a remote client.  Let’s start with the object to convert… an Address class.

using System.Runtime.Serialization;
 
...
 
[DataContract(Name = "Address", Namespace = "")]
public class PersonAddress
{
    [DataMember(Name = "City", Order = 1)]
    public string City { get; set; }
    [DataMember(Name = "Country", Order = 2)]
    public string Country { get; set; }
    [DataMember(Name = "PostalCode", Order = 3)]
    public string PostalCode { get; set; }
    [DataMember(Name = "State", Order = 4)]
    public string State { get; set; }
    [DataMember(Name = "Street", Order = 5)]
    public string Street { get; set; }
}


DataContract
and DataMember attributes provide information to the serialization process of how to structure the data.  It is possible to use the more familiar System.Serializable attribute however the output isn’t nearly as friendly.  More on that later.

The constructor for DataContractJsonSerializer we’re using requires knowledge of the Type of object being serialized to JSON.  For the purposes of this method we’re likely to not know which Type is to be serialized.  Quite often it will be a custom type.  We need our extension method to be more generic… I love .Net…  Here’s the method suitable for such a task:

using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;

...

public static string ToJSON<T>(this T obj)
{
    MemoryStream stream = new MemoryStream();
 
    try
    {
        //serialize data to a stream, then to a JSON string
        DataContractJsonSerializer jsSerializer = new DataContractJsonSerializer(typeof(T));
        jsSerializer.WriteObject(stream, obj);
 
        return Encoding.UTF8.GetString(stream.ToArray());
    }
    finally
    {
        stream.Close();
        stream.Dispose();
    }
}

 

Be sure to reference System.Runtime.Serialization and System.ServiceModel.Web.

Let’s dissect a bit.  DataContractJsonSerializer needs to know the object type.  In our case it’s generic, so we’ll let typeof(T) figure it out for us.  The serializer WriteObject method wants a stream to write the serialization output to for which we’re using a MemoryStream; an easy object for retrieving text from.  And that’s what we do… convert the stream’s byte array into a string; our JSON string.

Let’s run this pup using the following code:

PersonAddress address = new PersonAddress();
address.City = "Newport Beach";
address.Country = "US";
address.PostalCode = "92626";
address.State = "CA";
address.Street = "123 Candyland Way";
 
string json = address.ToJSON();
 
Response.Write(json);


And the results:

{"City":"Newport Beach","Country":"US","PostalCode":"92626","State":"CA","Street":"123 Candyland Way"}

Earlier I mentioned if you used the [Serializable] attribute instead of the [DataContract] attribute your solution would compile and function however your results would come out a bit different.  Here’s the output when using Serializable:

<{"<City>k__BackingField":"Newport Beach","<Country>k__BackingField":"US","<PostalCode>k__BackingField":"92626","<State>k__BackingField":"CA","<Street>k__BackingField":"123 Candyland Way"}>

As you can see this is far less friendly to work with from a JSON consumer perspective… Make it easier on yourself and stick with DataContract in this case.

I hope this helps in your JSON endeavors.  Let me know if you have any questions of problems!

Download the sample code for this post.

kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

ASP.NET 3.5 Extensions CTP Preview Released

It's late, I'm finally catching Cinderella Man, and I'm heading for vacation this week... of course none of that is interesting to you, but the CTP release of the ASP.NET 3.5 Extensions CTP Preview probably is.  The MVC framework seems to have garnered the most blog entries as of late.  I'll be sure to check it out when I return, unless the wife falls asleep early in the hotel and I can sneak the laptop out that is!
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

ASP.NET 3.5 Extensions Public Preview Announced

Scott Guthrie has announced ASP.NET 3.5 Extensions public preview will be released next week sometime.  This is really a big hitter people have been clammoring about...  MVC, Entity Framework, Astoria, and more!

After stumbling upon it on a MS labs site I've been following Astoria for a few months now.  An Astoria overview describes its purpose better than I can:

"The goal of Astoria is to facilitate the creation of flexible data services that are naturally integrated with the web. As such, Astoria uses URIs to point to pieces of data and simple, well-known formats to represent that data, such as JSON and plain XML. This results in the data service being surfaced to the web as a REST-style resource collection that is addressable with URIs and that agents can interact with using the usual HTTP verbs such as GET, POST or DELETE."

... using a REST-style request to get XML or JSON formatted data in a .NET Framework sanctioned way is just what the doctor ordered.  Here's a sample request and output:

Request: http://myserver/data.svc/Customers[ALFKI]

XML:
DataService xml:base="http://myserver/data.svc">
 <Customers>
  <Customer uri="Customers[ALFKI]">
   <CustomerID>ALFKI</CustomerID>
   <CompanyName>Alfreds Futterkiste</CompanyName>
   <ContactName>Maria Anders</ContactName>
   <ContactTitle>Sales Representative</ContactTitle>
   <Address>Obere Str. 57</Address>
   <City>Berlin</City>
   <Region />
   <PostalCode>12209</PostalCode>
   <Country>Germany</Country>
   <Phone>030-0074321</Phone>
   <Fax>030-0076545</Fax>
   <Orders href="Customers[ALFKI]/Orders" />
  </Customer>
 </Customers>
</DataService>

JSON:
[
    {
        __metadata: {
            Type: "Customer",
            Base: "http://myserver/data.svc",
            Uri: "Customers[ALFKI]"
        },
        CustomerID: "ALFKI",
        CompanyName: "Alfreds Futterkiste",
        ContactName: "Maria Anders",
        ContactTitle: "Sales Representative",
        Address: "Obere Str. 57",
        City: "Berlin",
        Region: null,
        PostalCode: "12209",
        Country: "Germany",
        Phone: "030-0074321",
        Fax: "030-0076545",
        Orders: {
            __metadata: {
                Uri: "Customers[ALFKI]/Orders"
            }
        }
    }
]

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Visual Studio 2008 Beta 2 to RTM Experience

I wanted to share my experience of going from Visual Studio 2008 Beta 2 to the RTM.  Scott Guthrie recommends uninstalling Visual Studio 2008 Beta 2, .Net Framework Beta 2, and Visual Studio Web Authoring Component.  When I uninstalled VS it seems to have taken the framework with it.  Typically I wouldn't expect this coupling to occur however in the case of beta and no release license I don't completely excuse that possibility.

I've also uninstalled a few others just to wipe the slate as clean as possible (it's a beta, who knows).  Other uninstalls include "MSDN Library for Visual Studio 2008 Beta 2 - ENU", "Microsoft SQL Server Compact 3.5" (and friends), and the "Microsoft .Net Compact Framework 3.5" or at least I think that's what it was called:).

In my opinion the uninstall processes are the most unpolished piece of the whole Beta 2 experience which was fantastic.  A number of times the uninstaller would halt due to some program being used.  Many times a simple "Retry" would resolve that one.

The install itself went smooth, but again took quite some time... now to find Team Explorer for 2008! 

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Visual Studio 2008 RTM Now Available

Microsoft has released Visual Studio 2008 to MSDN subscribers.  Oddly however, it wasn't listed in my applications tree view.  I got to the goods through this page: http://msdn2.microsoft.com/en-us/subscriptions/bb608344.aspx

This is also the first time I've seen Microsoft use Akamai to deliver a file.  It's not your standard Microsoft BITS download add-in... maybe FireFox is giving it the bird.

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

About Me

I'm Ian Suttle and I work for IGN Entertainment, a division of Fox Interactive Media.

Recent posts