Enums: Learn to love them

So, I was dredging around in a some old code I inherited looking for that one magical place to make my new change when I came across a piece of code that, well, just made me laugh and then cry.

Here it is:

 1: switch (ddlRollupInterval.SelectedValue) 
 2: { 
 3:     case "Daily": 
 4:         r.RollupInterval = Report.Interval.Daily; 
 5:         break; 
 6:     case "Weekly": 
 7:         r.RollupInterval = Report.Interval.Weekly; 
 8:         break; 
 9:     case "Monthly": 
 10:         r.RollupInterval = Report.Interval.Monthly; 
 11:         break; 
 12:     default: 
 13:         r.RollupInterval = Report.Interval.Yearly; 
 14:         break; 
 15: } 

Looking at the code it is very obvious what it is doing, it is setting an enum value based on the string value of a dropdown.  But did it really take that much code to do it.  Well of course not. 

An enumeration type (also named an enumeration or an enum) provides an efficient way to define a set of named integral constants that may be assigned to a variable. For example, assume that you have to define a variable whose value will represent a report interval. There are only 4 meaningful values which that variable will ever store. To define those values, you can use an enumeration type, which is declared by using the enum keyword.

 1: enum ReportInterval
 2: {
 3:     Daily,
 4:     Weekly,
 5:     Monthly,
 6:     Yearly
 7: }
The above enum was declared and then an instance was used on the Report object.
 
Enums are extremely flexible and can be used in a number of ways.  Lets look at a few ways you can use enums.
 

Get the Names from the Enum

Lets take the ReportInteval enum we created above and look how we would get an Array of strings that represent the names of each valid enum.

 1: var enumNames = Enum.GetNames(typeof (ReportInterval));

This would allow us to populate that ddlRollupInterval dropdown with all the possible values from the enum

 1: ddlRollupInterval.DataSource = Enum.GetNames(typeof (ReportInterval));
 2: ddlRollupInterval.DataBind();

Ok, so now we have a dropdown filled with the names from the enum, how do we clean up that code we found.  You remember that ugly switch statement that started this whole thing. Once a user selects something in the dropdown and clicks save we want to set the enum based on the string that was selected right? Lets look at how to do that next.

Likewise you can also get the values with the following code:

 1: Array enumValues = Enum.GetValues(typeof(ReportInterval));

Get an Enum from a String

This too is much easier than one would think.  Using the Enum.Parse() method provides a quick way to convert from a string to an instance of the desired Enum.

 1: ReportInterval interval = (ReportInterval)Enum.Parse(typeof(ReportInterval), testString);

This works great in our case because we filled the dropdown with only valid values.  But what if you weren’t sure if the value was valid for the enum or not.  You know those pesky users sometimes give us data that doesn’t fit our model.  ;-)  You can use the Enum.IsDefined() which returns an indication letting us know if a constant with the specified value exists in a specified enumeration.

If our user was able to add a value, say ‘Quarterly’ to our dropdown by some other part of the application and then selected it we would want to test the string we were provided to make sure we don’t throw an unwanted exception.

 1: var ourUserInputString = "Quarterly"
 2:  
 3: if (Enum.IsDefined(typeof (ReportInterval), outUserInputString)
 4: {
 5:     // It is ok go ahead and pase the enum
 6: }
 7: else
 8: {
 9:     // Alert the user an invalid string was selected.
 10: }

Get an Enum from an Integer

Getting an enum instance form an integer is even easier just cast the integer to the desired Enum.

 1: ReportInterval interval = (ReportInterval) testInt;

Of course we would never let our users add values to the dropdown because we want to constrain the valid values to be one that is on the enum, but I wanted to show you that it can be done.

Limit Method Call Arguments

Another usage for an enum is to limit the values a developer can pass to a method on your object.  Using our ReportInterval enum as an argument to a LoadReport method on our Report call gives us the safety net to know we are only going to get a valid value.  Where as if we just used a string we could get a value that doesn’t make sense.

 1: var status = RunReport(ReportInterval.Daily);

Another great part of this is a that Visual Studio will start complaining that the value is in valid unless it is from the enum, further more the compiler will  an argument '1': cannot convert from 'string' to 'EnumTest.ReportInterval'  exception.  I don’t know about your but I like that.

Summary

So what was the final result of fixing the code smell you say?  I replaced that huge 15 line switch statement with the two lines of code, one to verify that the value was correct, remember this is a very, very legacy application and I can not trust that the values were actually loaded to the dropdown from the enum, and one to set the ReportInterval if it checked out good.

I hope that this has shown you just a few ways that the simple Enum can enhance you programming life.

References:

C# Programming Guide: Enumeration Types

How Do Your Convert a String Into an Enum? – Tim Sneath

Generate your own RSS feed with WCF: Syndication

On a recent project I needed to expose some data via an RSS feed.  I came across Derik Whittaker’s blog post Generate your own RSS feed with Argotic.

Argotic Syndication Framework is a Microsoft .NET class library framework that enables developers to easily consume and/or generate syndicated content from within their own applications.  The Argotic Syndication Framework is very powerful and easy to use.

I didn’t go with the Argotic Syndication Framework for the project because I didn’t want to have yet another assembly in my project, maybe a lame reason but I found the solution I needed already existed in the .NET Framework with WCF: Syndication.  WCF: Syndication is a set of classes available in the .NET Framework that enables the creation and consumption of RSS feed in RSS and ATOM.

I thought it would be a good exercise for me to take Derik’s original article and show how you would accomplish the same thing using WCF: Syndication, so here goes.

In this post we will review the following steps needed to add a feed to your site. image

  1. Creating the xml (rss feed) document for publication
  2. Creating an access point for the feed
  3. Adding the feed to your site 

Creating the xml (rss feed) document for publication

Using the Syndication objects available in the .NET Framework is pretty easy.  The first thing we need to do is add a reference to the assembly that holds the classes we need to add a reference to the System.ServiceModel.Web.dll.

Once we have the reference to the assembly all we have to do is add a using statement and away we go.

 1: public SyndicationFeed GenerateRssFeed()
 2: {
 3:     var items = RssRepository.GetRssItems();
 4:     var syndicationItems = new List<SyndicationItem>();
 5:  
 6:     var feed = new SyndicationFeed("Main RSS Feed for site", "Title", null);
 7:  
 8:     foreach (var rssItem in items)
 9:     {
 10:         var newItem = new SyndicationItem
 11:                           {
 12:                               Title = new TextSyndicationContent(rssItem.Title),
 13:                               Content = new TextSyndicationContent(rssItem.Content),
 14:                               Id = Guid.NewGuid().ToString()
 15:                           };
 16:         
 17:         newItem.Links.Add(new SyndicationLink(rssItem.Link));
 18:         newItem.Authors.Add(new SyndicationPerson("author@example.com", "Author Name", "http://example.com"));
 19:         
 20:         // Add the new syndication item to the generic list
 21:         syndicationItems.Add(newItem);
 22:     }
 23:  
 24:     // add the SyndicationItems to the Syndication Items
 25:     feed.Items = syndicationItems;
 26:  
 27:     // Return the Syndication feed
 28:     return feed;
 29: }

 

Creating an access point for the feed

Following along with the original post we now need to create an access point for users to be able to consume the feed.  Instead of using a static .xml document to expose the content lets look at how we can dynamically generate the feed.  The simplest way is to create an .aspx page and change the content type to “text/xml” and place the following code in the Page_Load event.

Another good idea is to add the OutputCache to the page.

 1: // Put this code here in your html part of the page. 
 2: // This will cache the output for a given number of seconds 
 3: <%@ OutputCache Duration="600" VaryByParam="none" %> 

 

Adding the feed to your site

In order to let the world know you have a feed, you need to expose it in your html documents.  One way to accomplish this is to add it to you master page, this will make it available on every page of the site.

After you have added the reference to your html page you should see the RSS feed icon on your URL bar in your browser.

 1: <link title="[Your title here]" 
 2:         href="http://www.yourdomain.com/[rssfilehere]" 
 3:         type="application/rss+xml"
 4:         rel="alternate">

 

Conclusion

First I would like to thank  Derik for his easy to follow post on using the Argotic Syndication Framework and I hope that you can also see how easy it is to also create Syndication feed using the new classes made available in WCF.

Download the full source SyndicationVsArgotic.zip (27.26 kb).

Calendar

<<  March 2024  >>
MonTueWedThuFriSatSun
26272829123
45678910
11121314151617
18192021222324
25262728293031
1234567

View posts in large calendar

Widget Category list not found.

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X

Tag cloud

    Widget Month List not found.

    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X

    Widget AuthorList not found.

    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X

    Widget TextBox not found.

    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))X