Finding Out which Groups a User is a Member Of When Using Windows Authentication in Asp.Net

March 13, 2008

When using Windows authentication with Asp.net, I often need to know which active directory groups a user is a member of. Now I know that you can do something like:

if (User.IsInRole("Admin"))
{
    //Give Access to Secrets
}

The problem with this is you need to know the name of the group ahead of time. And what if you are on a network where the full name of a group is not always clear. The actual group name may be “MyDomain\Admin”. So I wrote up a quick way to just get a list of all the groups a user is a member of. It isn’t super straight forward (as far as which types you need to cast to) so I thought I would list it out here:

public static List<string> GetGroups(RolePrincipal user)
{
    List<string> groups = new List<string>();

    WindowsIdentity identity = p.Identity as WindowsIdentity;
    foreach (IdentityReference group in identity.Groups)
    {
        NTAccount account = (NTAccount)group.Translate(typeof(NTAccount));

        groups.Add(account.Value);
    }

    return groups;
}

the user of it on a web page would be something like:

List<string> groups = GetGroups(User as RolePrincipal);

Keep in mind that this is assuming you are using Windows Authentication. So the weird part of the code above is:

NTAccount account = (NTAccount)group.Translate(typeof(NTAccount));

if you do not get this step, you will just get a bunch of Active Directory IDs that won’t do you much good.

Also, sorry about the long title. I just can’t think of a clever title today. Maybe I should add something like “Ultimate Edition for Developers” on the end to make it extra clear.

kick it on DotNetKicks.com

Advertisement

Google Charts for Asp.Net now on Codeplex

February 10, 2008

image I have received very positive feedback on my Asp.Net control for Google charts so I decided to place it up on Codeplex to allow people to participate and add code to the project.

I am currently working on a project roadmap so please let me know if you are interested in participating. One feature I have already begun work on is giving the control support for data binding.

Here is some example data binding code I have got working:

protected void Page_Load(object sender, EventArgs e)
{
    chart.DataSource = GetDataSource();
    chart.DataBind();
}

private DataTable GetDataSource()
{
    DataTable table = new DataTable();
    
    table.Columns.Add("Type", typeof(string));
    table.Columns.Add("Jan", typeof(float));
    table.Columns.Add("Feb", typeof(float));
    table.Columns.Add("Mar", typeof(float));

    table.Rows.Add("Men", 68, 78, 88);
    table.Rows.Add("Women", 68, 58, 78);
    table.Rows.Add("Both", 88, 48, 98);
    return table;
}

I am just binding to a simple DataTable which has one column containing the labels for the chart and multiple other columns which contain the data for the chart. The code above produces the following chart:

image

I look forward to seeing this project improve.

kick it on DotNetKicks.com


C# Language Improvements: Know What You Are Getting Into

February 6, 2008

The C# language has changed a lot since its initial release in 2000. C# 2.0 brought us:

imageC# 3.0 brought us:

And that is just the new language features in the last 3 years! This does not include all of the new classes added to the BCL over the same time period.

Know the Cost

I am as excited about these new changes as the next guy. I have used various combinations of these improvements in my projects with great success. But is there a cost to new features?

Recently I read a couple of articles that reminded me that you not only have to understand how a feature is used, you also have to understand the cost of using it. Sometimes that cost is performance, other times it could be something like readability or portability. I’ll take one example from the 2.0 framework and then one from the 3.5 framework to show that you need to understand the implications of using new features.

Yield Return

First, there is Fritz Onion’s recent post on the amount of code generated by the yield return syntax introduced in C# 2.0:

The array allocation function generated a total of 20 lines of IL, but the yield return function, if you included all of the IL instructions for the IEnumerable class generation as well was over 100! That’s a 5x penalty in code generation to save 18 characters of typing

So is the 5x penalty ever worth it? Yes, of course it is. There are things you can do with yield that you couldn’t do previously. In most cases, the use of yield improves readability dramatically. It also makes the task of creating a custom enumerator much easier.

In his article The power of yield return, Joshua Flanagan points to an example where using the yield return improved performance dramatically:

With the improved implementation that took advantage of the yield keyword, the program was able to finish its job in less than half the time! It also used much less memory, as it never had to store all 9 strings in a collection. Now imagine the potential impact if GetCombinations returned a collection with thousands of entries!

The point here is that you have to know the costs and how they fit in with the requirements of the project you are working on. If you are building something that must support thousands of concurrent users and must be very performant, you will most likely choose to use the yield return despite the extra code generated by the compiler.

LINQ is Dead, Long Live LINQ

Most of the time when I show somebody the new language enhancements in C# 3.0, the thing that interests them the most (and rightly so) is LINQ. It is just so different to see query syntax built right into the language. The next question they usually ask is how the performance of something written using LINQ would compare the same procedure written using just C# 2.0 control structures.

Steve Hebert recently wrote a post about LINQ performance where he concludes:

Despite my best efforts I just couldn’t make my hand-written code perform as poorly as Linq

What? Seriously? Wow. Then I guess we should stay away from LINQ then right? Well, if you look closer at his post, you will notice that he has optimized his non LINQ version of the code a little bit for the underlying data structure where LINQ has to be able to operate regardless of the underlying data structure. I am not so much interested in the particulars so much as I am the idea that you should understand these things before you start replacing all of your for loops with LINQ queries.

Shifting Sands

One more recent post that fits in here. Rob Conery wrote about his recent experience where his 5 year old code has come back to haunt him:

I spose the moral of the story is to always view the concept of maintenance with an eye towards shifting toolsets and platforms. In 4 years you will need to support the ASP.NET 2.0 site you’re on now, using Visual Studio 2012 and it’s Silverlight-generated Scaffolds :).

This is a great reminder of how tough it can be to deal with changes in technology. I mean, come on, he couldn’t find a machine to compile his 5 year old code?!? I know we can all relate. With the technology learning curve growing at a semi exponential way, just imagine where that same code will be in another 5 years.

Back to Machine Code

Obviously I am not advocating that we just give up on new features because they might not be as fast or resource efficient as our hand coded machine code. In fact, I think we need to embrace abstractions wherever possible. They make our jobs as software developers much easier. Just be smart about it. Have some idea what is going on behind the covers. It is important to realize that yield return eventually becomes a bunch of compiler generated code and that LINQ queries are general case and they may not always be as great as manually doing the coding yourself.

Maybe the documentation on these new language features could do a better job at explaining what sorts of considerations we need to take into account when using them in our applications.

kick it on DotNetKicks.com


C# Enum Craziness: Sometimes What You Expect Isn’t The Case

January 28, 2008

I learned something new today about enums that I find really weird. Lets start with the following test enum:

public enum Action
{
    Run = 2,
    Walk = 4,
    Crawl = 8
}

and then some code to do something with that enum:

static void Main(string[] args)
{
    Console.WriteLine((Action)2);
    Console.WriteLine((Action)4);
    Console.WriteLine((Action)8);
    Console.WriteLine((Action)10);
}

What do you think will happen here? Will it even compile?

When I saw this code snippet I said to myself, “the first three lines look ok but the last line won’t work because 10 isn’t a valid value for this enum. Well, I was wrong. This program actually outputs:

Run
Walk
Crawl
10

Huh?!? How could this be? 10 isn’t a valid value according to my enum definition!

This Should Never Happen…Right?

Ok, lets try something different. How about a method?

public static void Execute(Action action)
{
    switch (action)
    {
        case Action.Run:
            Console.WriteLine("Running");
            break;
        case Action.Walk:
            Console.WriteLine("Walking");
            break;
        case Action.Crawl:
            Console.WriteLine("Crawling");
            break;
        default:
            Console.WriteLine("This will never happen! {0}", action);
            break;
    }
}

Surely you can’t pass anything into this method other than one of the 3 values defined in my enum. So lets run some code:

static void Main(string[] args)
{
    Execute(Action.Run);
    Execute(Action.Walk);
    Execute((Action)55);
}

What do you think this does? Well, it outputs:

Running
Walking
This will never happen! 55

Just about this time you must be thinking: “This has to be a bug!”. Well, it is not. It is by design. here is the excerpt from the C# design spec:

14.5 Enum values and operations

Each enum type defines a distinct type; an explicit enumeration conversion (Section 6.2.2) is required to convert between an enum type and an integral type, or between two enum types. The set of values that an enum type can take on is not limited by its enum members. In particular, any value of the underlying type of an enum can be cast to the enum type, and is a distinct valid value of that enum type.

Wow, that is not at all what I expected when it comes to limiting the possible values of enums. So what are enums good for then? Are they just for code readability? Between this little revelation and my previous hack to associate string values to enums, I am loosing faith in enums.

Can You Handle it?

So what is the best way to check for this in your methods? Should you throw an exception if you receive an enum value you were not expecting? Should you just ignore it? Well, lets see what the .Net base class libraries do.

First, lets start with the System.IO.File class. What happens if I run the following code?

File.Open(@"C:\temp\test.txt", (FileMode)500);

Well, it throws a System.ArgumentOutOfRangeException with the message “Enum value was out of legal range.”. Ok, makes sense – I did pass in something out of range.

Lets try reflection. What does the following code snippet output?

PropertyInfo[] info = typeof(StringBuilder)
.GetProperties((BindingFlags)303); Console.WriteLine(info.Length);

Well, it just outputs ‘0’ which means in this case it is just being ignored and an empty array is returned.

What about System.String? Lets try this code snippet:

"TestString".Equals("TESTSTRING", (StringComparison)245);

Well, it turns out this throws an exception but instead of being a System.ArgumentOutOfRangeException like System.IO did, it throws a System.ArgumentException with the message “The string comparison type passed in is currently not supported.” Ok, so this is kind of the same but still a little inconsistent if you ask me.

Is Anything Safe These Days?

So what is a developer to do? Obviously you need to be aware of this when you are receiving enum types from publicly facing code. It seems there is no clear guidance on this that I can find. The C# design spec explains the behavior but doesn’t really give any guidance on why or how this should be handled. So the only other place to turn for guidance is one of my favorite .Net books Framework Design Guidelines by Brad Abrams and Krzysztof Cwalina. On their section on enums, I can’t find any guidance on how to handle out of range enum values. I do, however, find guidance that we should be using enums:

DO use an enum to strongly type parameters, properties, and return values that represent sets of values

They also suggest that enums should be favored over static constants:

DO favor using an enum over static constants

And Jeffrey Richter (and while I am pointing out my favorite .Net books, I have to add Mr. Richter’s book CLR via C# which contains priceless information on the CLR that you can’t find anywhere else) adds the following commentary:

An enum is a structure with a set of static constants. The reason to follow this guideline is because you will get some additional compiler and reflection support if you define an enum versus manually defining a structure with static constants.

So I guess we do continue to use enums and just know that we can’t always trust their values to be valid. Do you think the C# design spec should be amended to include a recommended behavior for out of range enum values? Perhaps Brad and Krzysztof can include something in their second edition of Framework Design Guidelines.

kick it on DotNetKicks.com


Associating Strings with enums in C#

January 17, 2008

I have seen other great articles out lining the benefits of some pretty clever and useful helper classes for enums. Many of these methods almost exactly mirror methods I had written in my own EnumHelper class. (Isn’t it crazy when you imagine how much code duplication there must be like this out there!)

One thing that I don’t see emphasized much is trying to associated string values with enums. For example, what if you want to have a Drop Down list that you can choose from a list of values (which are backed by an enum)? Lets start with a test enum:

public enum States
{
    California,
    NewMexico,
    NewYork,
    SouthCarolina,
    Tennessee,
    Washington
}

So if you made a drop down list out of this enum, using the ToString() method, you would get a drop down that looks like this:

image

While most people will understand this, it should really be displayed like this:

image

“But enums can’t have spaces in C#!” you say. Well, I like to use the System.ComponentModel.DescriptionAttribute to add a more friendly description to the enum values. The example enum can be rewritten like this:

public enum States
{
    California,
    [Description("New Mexico")]
    NewMexico,
    [Description("New York")]
    NewYork,
    [Description("South Carolina")]
    SouthCarolina,
    Tennessee,
    Washington
}

Notice that I do not put descriptions on items where the ToString() version of that item displays just fine.

How Do We Get To the Description?

Good question! Well, using reflection of course! Here is what the code looks like:

public static string GetEnumDescription(Enum value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DescriptionAttribute[] attributes =
        (DescriptionAttribute[])fi.GetCustomAttributes(
        typeof(DescriptionAttribute),
        false);

    if (attributes != null &&
        attributes.Length > 0)
        return attributes[0].Description;
    else
        return value.ToString();
}

This method first looks for the presence of a DescriptionAttribute and if it doesn’t find one, it just returns the ToString() of the value passed in. So

GetEnumDescription(States.NewMexico);

returns the string “New Mexico”.

A Free Bonus: How to Enumerate Enums

Ok, so now we know how to get the string value of an enum. But as a free bonus, I also have a helper method that allows you to enumerate all the values of a given enum. This will allow you to easily create a drop down list based on an enum. Here is the code for that method:

public static IEnumerable<T> EnumToList<T>()
{
    Type enumType = typeof(T);

    // Can't use generic type constraints on value types,
    // so have to do check like this
    if (enumType.BaseType != typeof(Enum))
        throw new ArgumentException("T must be of type System.Enum");

    Array enumValArray = Enum.GetValues(enumType);
    List<T> enumValList = new List<T>(enumValArray.Length);

    foreach (int val in enumValArray)
    {
        enumValList.Add((T)Enum.Parse(enumType, val.ToString()));
    }

    return enumValList;
}

As you can see, the code for either of these methods isn’t too complicated. But used in conjunction, they can be really useful. Here is an example of how we would create the drop down list pictured above based on our enum:

DropDownList stateDropDown = new DropDownList();
foreach (States state in EnumToList<States>())
{
    stateDropDown.Items.Add(GetEnumDescription(state));
}

Pretty simple huh? I hope you find this as useful as I do.

One More Example

There is one more scenario that I often find myself needing to associate string values with enums – when dealing with legacy constant string based system. Lets say you have a library that has the following method:

public void ExecuteAction(int value, string actionType)
{
    if (actionType == "DELETE")
        Delete();
    else if (actionType == "UPDATE")
        Update();
}

(I tried to make this look as legacy as I could for a contrived example). What happens if somebody passes in “MyEvilAction” as a value for actionType? Well, whenever I see hard coded strings, that is a code smell that could possibly point to the use of enums instead. But sometimes you don’t have control over legacy code and you have to deal with it. So you could make an enum which looks like this:

public enum ActionType
{
    [Description("DELETE")]
    Delete,
    [Description("UPDATE")]
    Update
}

(I know, I know, this is a very contrived example) Then you could call the ExecuteAction Method like this:

ExecuteAction(5, GetEnumDescription(ActionType.Delete));

This at least makes the code more readable and may also make it more consistent and secure.

kick it on DotNetKicks.com


Useful Code Snippet: Web Property

January 15, 2008

Write WebControls much? Well, I do and I have a code snippet that I pretty much can’t live without. It is used for creating ViewState backed properties. Here is the basic pattern I use when creating properties for my web controls:

public string Name
{
    get
    {
        object o = ViewState["Name"];
        return o == null ? String.Empty : (string)o;
    }
    set { ViewState["Name"] = value; }
}

Basically, you just want a property (in this case a string named “Name”) and you want to store it in ViewState. And when the value is being retrieved, if it is not in ViewState, you want to retrieve some default value. This is a pattern that I repeat over and over in my controls. So I made a code snippet to make it easier.

I use the shortcut ‘webprop’

image

and it expands like this:

image

To install, you just need to place the .snippet file (link to download below) in your ‘My Snippets’ folder which in windows vista is located at:

C:\Users\<UserName>\Documents\Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets

or if you use Visual Studio 2008:

C:\Users\<UserName>\Documents\Visual Studio 2008\Code Snippets\Visual C#\My Code Snippets

I hope this is helpful. It saves me a bunch of time.

You can download the .snipped file here

kick it on DotNetKicks.com


Asp.Net Control For Google Charts

December 9, 2007

Google has launched a new service which allows you to very simply build charts for any web application. Their design decision to make an interface to their service which is all based on the format of the query string is very interesting to me. Basically, you send them a Url and they return a PNG image of a chart. The little query string language they use for the charts is not the cleanest thing in the world but it is simple which is nice.

Here is the official description:

The Google Chart API is an extremely simple tool that lets you easily create a chart from some data and embed it in a webpage. You embed the data and formatting parameters in an HTTP request, and Google returns a PNG image of the chart. Many types of chart are supported, and by making the request into an image tag you can simply include the chart in a webpage.

A Weekend Coding Project

I really enjoy building custom Asp.Net web controls so I decided to try my hand at creating a control to wrap the Google chart functionality. Now, this is really just a first pass so it is definitely not bug free or feature complete. I just figure I can put it out there and get some feedback to see if I should continue in the same direction or to see if I am way off. Also, I can use this as an opportunity to share a little about how I approach web control design.

Note: I realize that I am not the first or only one to get the idea to create a Google chart Asp.Net control, but since my approach is so different, I figured I would go ahead and submit my own.

So Many Classes

Maybe I am a little too obsessive or just set in my ways, but it always seems like when I set out to tackle a problem like this, there is a set of helper/utility classes that I prefer to use. Over time this creates a sticky situation because I have so many copies of the same or similar classes laying around it becomes a maintenance nightmare. I have considered just creating my own utility assembly but then people would have to deploy that with any solution that they use my code in. I prefer to release my code as a self contained assembly whenever possible so I guess I will just put up with it for now.

Here is a quick list of the classes I used on this project:

image

I use ColorHelper to translate System.Drawing.Color objects to and from their hexadecimal string counterparts. EnumHelper contains methods for getting Description attributes associated to enums as well as some parsing methods similar to these. I have written about DelimitedList and the state managed classes before. I make heavy use of QueryStringHelper to build the query string which represents the chart data.

Heavy on the Declarative Syntax

I have approached this problem by trying to represent the entire chart declaratively right in the aspx code. Here is an example of a line chart:

<web:Chart ID="chart" runat="server" Width="300px" Height="150px"
    Title="Transportation" Type="Line" EnableLegend="true">
    <DataSets>
        <web:DataSet Color="ForestGreen" Label="Cars">
            <web:DataPoint Value="5" />
            <web:DataPoint Value="9" />
            <web:DataPoint Value="21" />
            <web:DataPoint Value="30" Marker="Arrow" />
            <web:DataPoint Value="25" />
            <web:DataPoint Value="36" />
        </web:DataSet>
        <web:DataSet Color="Red" Label="Trucks">
            <web:DataPoint Value="7" />
            <web:DataPoint Value="3" />
            <web:DataPoint Value="13" />
            <web:DataPoint Value="13" />
            <web:DataPoint Value="16" />
            <web:DataPoint Value="25" />
        </web:DataSet>
        <web:DataSet Color="Orange" Label="Motorcycles">
            <web:DataPoint Value="18" />
            <web:DataPoint Value="25" />
            <web:DataPoint Value="18" />
            <web:DataPoint Value="13" />
            <web:DataPoint Value="25" />
            <web:DataPoint Value="23" />
        </web:DataSet>
    </DataSets>
</web:Chart>

As you can see, a chart with any sizable amount of data can become very cumbersome. The output of this chart looks like this:

Transportation

The url used to generate this chart looks like this:

http://chart.apis.google.com/chart?chd=t:5,9,21,30,25,36|7,3,13,13,16,25|18,25,18,13,25,23
&cht=lc&chs=300×150&chco=228b22,ff0000,ffa500
&chm=a,000000,0,3,10&chtt=Transportation&chdl=Cars|Trucks|Motorcycles

You can change the type of chart being generated through the Type property. Here is an example of a bar chart:

A Venn Diagram:

Pie Chart:

Feedback Please

What I really need right now is some feedback. Do you find this helpful at all? Is my design way off? What would be the ideal way to build charts using the Google Api?

Please – download the library, try it out. Download the source and check it out. Post comments letting me know what you think.

Also, let me know if you would like me to write more about the details of the code or the usage of the control.

Source: Google Chart Source Assembly: Google Chart Assembly

kick it on DotNetKicks.com


Codesmith 4.0 Feedback and Feature Requests

June 5, 2007

Codesmith is a product that I have considered purchasing multiple times in the past. It seems to be the code generations suite that has the best community built around it and I think that is a very import aspect of any software I purchase. Every time I download the trial of Codesmith, my trial expires before I find a compelling reason to purchase the product.

Well, the other day I received a free licence for Codesmith 4.0 professional so I decided to use it on a project I am working on. After spending a couple of days with the product there are many features which I feel are missing or need some improvement. Some of them seem so glaring that I plan on following up with support to make sure I understand the functionality and the documentation correctly. It is also possible that the scenarios that Codesmith is meant to target are just not what I am trying to use it for. It seems that Codesmith is very well suited for walking through database structures and generating stored procedures or some sort of custom data layer, but that is not really what I want to use it for.

Background

First I want to explain what I am attempting to use code generation for. Basically, I am generating an asp.net website based on configuration in a database. I already have a separate app that is used to input the configuration parameters and now I am trying to use Codesmith templates to generate the website. So here is the basic structure of my project:

I have created a base class for all the templates which includes some properties and functionality that will be common to all the code templates in this project. I created this class in Visual Studio and so it is in a re-usable dll. I also have other classes in this assembly which are used to hold common configuration parameters and such.

I plan on making three template files (.cst) for each aspx page I am generating. One for the code behind(.cs), one for the markup (.aspx), and one “master” template that will call the other two templates.

In the end, I will be writing my own client which will use the Codesmith API to run the templates and generate the website.

Visual Studio Integration

With visual studio integration being a feature, I assumed that this would allow you to view, edit, and run your code templates inside of Visual Studio. I was expecting an experience where I can open Visual Studio, choose “New Codesmith Project” or “Add Codesmith template” to an existing project and then begin editing both the .cst file as well as the .cs code behind file. Well, the only visual studio template that is provided is a “Add Codesmith project” which simply adds a Codesmith project (.csp) to your project. This features helps you manage code generation as part of your build process. And when it comes to editing and running your code templates, they still open up in Codesmith Studio which is external to Visual Studio. This wouldn’t be so bad except the development experience in Codesmith Studio is nowhere near as nice as Visual Studio. The intellisense only seems to work part of the time, the code formatting is not very configurable, and it just feels a lot more like editing in notepad than it does a development IDE.

Reading through the feature request at the Codesmith forums lead me to believe that I am not alone in my frustrations with the Visual Studio integration. I have seen other products do a much better job of leveraging the fact that I am comfortable and much more productive in Visual Studio. Codesmith Studio should only be for developers who do not have Visual Studio.

Assembly References

As I mentioned earlier, I want to use a common assembly to hold some base and utility classes for my templates. There is one problem though, if you want to use any external assemblies, they must be in one of three places:

  • The GAC
  • The Visual Studio PublicAssemblies Folder
  • The Codesmith Addins folder

So this basically means that I have to finish developing my external assemblies BEFORE I begin developing my code templates or I can just copy my assembly manually over to one of the folders above every time I make a new build of it. Well, that may not be so bad except for the fact that the Codesmith Studio holds on to the assembly once you use it in a template so I can’t replace it in the file system until I completely close Codesmith Studio. This is annoying to say the least.

I do not know how the Codesmith engine works under the hood, but I assume it is doing some sort of build which results in a .Net assembly or something very similar. I think it would be ideal if you could just have a Codesmith visual studio project type which would result in an assembly which could be referenced in other visual studio projects. This would really open up tons of new scenarios for sharing templates across applications as well as with the community. Having the templates in a assembly package would also make using the Codesmith API much easier. Instead of having to point the CodeTemplateCompiler to a .cst file, I would like to be able pass it an instance of a CodeTemplate class which it can then operate on.

Code Behind

I realize intellisense is probably a very hard feature to implement but whenever I use a product has it implemented but it only works sometimes, this almost makes me wish it weren’t there at all. If you can’t count on a feature, then it is more of an annoyance than a help. The code behind model seems like it is something that was just tacked on to Codesmith and is not really supported all that well. For starters, I can’t figure out how to add a .cs code behind file to the Codesmith Explorer window. If I right click, there is not “new C# file” option and if I try to rename another file to a .cs extension it complains that it is not a valid extension. The only way I have been able to add my own code behind files into the Codesmith explorer is to create a blank cs file and move it into the same folder as my template using windows explorer. Then it shows up in the Codesmith explorer. Maybe my experience as an Asp.Net developer pushes me towards the code behind model because it seems that Codesmith templates are more geared towards the inline classic asp type model of coding.

Conclusion

I hope all of this ranting makes you think I hate Codesmith. On the contrary, I think it is a pretty cool product that has a very wide variety of applications. I guess I am just spoiled by Visual Studio. I am a big believer that when you create tools for a development platform like .Net or Visual Studio, you should make things work just like they were always part of the platform. For example, if you are writing APIs, they should conform as closely as possible to the BCL standards as far as naming etc. Codesmith essentially introduces a new file type into my development arsenal: the .cst template file. Having to use these files outside of Visual studio when I am trying to integrate them with a project that is being developed inside of the Visual Studio IDE just feels wrong. I would love to hear from the Codesmith team as to what their plans are beyond version 4.0


Child Collections in Asp.Net Custom Controls

May 23, 2007

I have been developing custom web controls for many years now and I am just now getting comfortable with many of the advanced features afforded by the rich System.Web.UI.WebControls namespace. One feature I have implemented many different times over the years is having a web control which contains a list of sub items. For example, the Asp.Net GridView’s collection of Columns or the DropDownList’s collection of ListItems.

<asp:GridView ID="grid" runat="server"> 
    <Columns> 
        <asp:BoundField /> 
        <asp:ButtonField /> 
    </Columns> 
</asp:GridView>

There is so many things going on it a control like this that just seem like magic. How are the child items persisted in ViewState? How does the control know how to parse the child items? What if the whole world were a power ranger?

StateManagedItem

I have created a couple of classes that really simplify the process of creating lists of child items. The first of which is the class StateManagedItem. This class is the base class for all the objects which you wish to use as "Child Items" (like grid view columns or list items).

In order to manage state in Asp.Net, you have to implement the IStateManager interface. This interface allows objects to participate in the process of saving and retrieving things from ViewState. In order to generalize the whole process, I needed on other method to set an item as "Dirty" so I created the following interface:

public interface IStateManagedItem : IStateManager 
{ 
    void SetDirty(); 
}


So now we have the base interface for all state managed items. So here is the what the base class definition looks like:

public abstract class StateManagedItem : IStateManagedItem

This class provides it’s own ViewState for items to save their state in which essentially allows "Child Items" to save their state just like custom web controls do. To illustrate this concept, lets create an example class called Appointment which will hold information about a calendar appointment.

public class Appointment : StateManagedItem

The definition for this class is very simple. Here is how the properties are implemented:

public DateTime? Start 
{ 
    get 
    { 
        object o = ViewState["Start"]; 
        return o == null ? null : (DateTime?)o; 
    } 
    set { ViewState["Start"] = value; } 
}

If you are familiar with using ViewState to store web control properties, this syntax should look fairly familiar. That that is all there is to our child item.

StateManagedCollection

The next helper class is a base class for the collection of items. In our example, we need a collection of Appointments. For this purpose, I have created a StateManagedCollection<T> class which can be used to hold the child items.

public abstract class StateManagedCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IStateManager, 
    IList, ICollection 
    where T : class, IStateManagedItem, new()

If you are not familiar with generics and generic constraints, this is basically a list class which requires the child items to be a class (not a struct), derive from IStateManagedItem, and to have a default constructor.

So to create our list of Appointments, all we need to do is the following:

public class AppointmentCollection : StateManagedCollection<Appointment> 
{ 
}

That is it as far as the AppointmentCollection class goes. It doesn’t require any more code.

Sample Control

So lets finish the example by creating a custom control which displays a list of Appointments. First we will derive from Composite Control:

[ParseChildren(true), PersistChildren(false)] 
public class AppointmentControl : CompositeControl

Note the ParseChildren and PersistChildren attributes, these are required to tell Asp.Net how to parse the markup inbetween the start and end tags of your control. This is part of the "Magic" I mentioned earlier.

Next, make a member of the class which is an AppointmentCollection:

private AppointmentCollection appointments = null;


And a public property to access that collection:

[ 
    Mergable(false), 
    PersistenceMode(PersistenceMode.InnerProperty), 
] 
public AppointmentCollection Appointments 
{ 
    get 
    { 
        if (appointments == null) 
        { 
            appointments = new AppointmentCollection(); 
            if (base.IsTrackingViewState) 
            { 
                appointments.TrackViewState(); 
            } 
        } 
        return appointments; 
    } 
}

This property also must have a couple of attributes – Mergable and PersistenceMode. These basically tell Asp.Net and Visual Studio how to handle and persist this property.

To use this control, first place the proper includ directive on your page:

<%@ Register TagPrefix="web" Namespace="Web.Example.Appointment" %>

Now we can declare our control markup as:

<web:AppointmentControl id="appointmentList" runat="server"> 
    <Appointments> 
        <web:Appointment Start="1/6/2007 8:00 AM" End="1/6/2007 11:30 AM" Description="Breakfast" /> 
        <web:Appointment Start="5/12/2007 9:30 AM" End="5/12/2007 9:45 AM" Description="Meeting" /> 
        <web:Appointment Start="5/12/2007 10:00 AM" End="5/12/2007 10:30 AM" Description="Break" /> 
    </Appointments> 
</web:AppointmentControl>

I won’t go into the render code (you can download the source code to see all the gory details) but here is how the control renders:

You have 3 appointment(s)

  • Breakfast – (01/06/2007 08:00:00 – 01/06/2007 11:30:00)
  • Meeting – (05/12/2007 09:30:00 – 05/12/2007 09:45:00)
  • Break – (05/12/2007 10:00:00 – 05/12/2007 10:30:00)

You can download the full source code here. Hope this helps dispell some of the "Magic" of Asp.Net controls.

kick it on DotNetKicks.com


DelimitedList<T> – a useful utility class

May 22, 2007

There are several classes which I have written over the years which have become almost like my own personal BCL when developing .Net projects. I think most people have these classes laying around in some form or fashion. In fact, I have joined a formalized effort led by Steve Wright to make an open source version of this “Toolbox” called nToolbox. While that project is getting off the ground, I figured I might share some of the classes which have been very useful to me personally. If this topic interests you, you can read my previous post where I shared some code which I use to find Controls on an Asp.Net page.

Background

Here is the situation I kept finding myself in – I will use the case of a comma delimited list of items since it is the most common scenario:

I want to loop through a list of strings and build a comma delimited list. The code begins something like this:

string[] items = new string[] 
{ 
    "Apples", 
    "Oranges", 
    "Pears", 
    "Bannanas" 
};    

StringBuilder list = new StringBuilder();       

foreach (string item in items) 
{ 
    list.AppendFormat("{0},", item); 
}       

Console.WriteLine(list.ToString());

The problem with this is it will produce the following string:

Apples,Oranges,Pears,Bannanas,

Notice that there is a trailing comma on the end. So then I end up having to explicitly remove that last comma by either not adding it on the last iteration through the loop or by removing it after the loop has completed.

DelimitedList

So I wrote a class which will help me produce such lists but without the pain of remembering if there is a comma at the end or not. Although the DelimitedList class defaults to just having a single comma as its delimited, it can actually have any string as a delimited. I have used it in the past to delimited things by pipes ‘|’ and even line breaks which can be useful when you want one item per line.

Rewriting the same code above with the delimited list would look like this:

DelimitedList<string> list = new DelimitedList<string>();       

foreach (string item in items) 
{ 
    list.Add(item); 
}     

Console.WriteLine(list.ToString());
Now this will produce the expected string:
Apples,Oranges,Pears,Bannanas

The DelimitedList can also work on any type of object (thus the use of Generics) so you can use it with types other than strings: (just for varieties sake, I will use a delimiter other than a comma)

DelimitedList<int> list = new DelimitedList<int>("+");       

for (int i = 0; i < 10; i++) 
{ 
    list.Add(i); 
}       

Console.WriteLine(list);

This will produce the following string:

0+1+2+3+4+5+6+7+8+9

You can download the complete code for the DelimitedList class here