Twitter Feed Popout byInfofru

OverrideThis.com

Adventures in .NET Software Craftsmanship!

ASP.NET MVC 1.0 Released!!!

I am very excited to announce that Microsoft has officially released the RTM version of the ASP.NET MVC Framework during the Mix'09 developer's conference.  Make sure to download as soon as possible, and welcome to the ASP.NET MVC Framework generation.

Thanks for Reading,

Roberto Hernandez

Additional Links
(Download) http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b&displaylang=en
(Official Website) http://www.asp.net/mvc

Security Trimming an ASP.NET SiteMapCollection

Yes, I know what everybody is thinking right now, Don't SiteMaps already provide functionality for Security Trimming?   Well they do and they don't.  This functionality is available only if you are using an implementation of the ASP.NET MembershipProvider and RoleProvider.  In the applications that I have to work with in a day to day basis that is rarely the case, I always have to develop a custom security provider using forms or windows authentication that support some far fetched business requirements.   I still however love to use SiteMaps and have rarely seen the need to customize the base SiteMap provider for any other reason.    So, in order to have security trimming and still use and bind the information from my SiteMap I wrote the following block of code that just begged to be re-factored.

Exhibit A - Code that needs (begs) for refactoring.

// do security trimming.
List<SiteMapNode> nodes = new List<SiteMapNode>();
foreach (SiteMapNode node in SiteMap.RootNode.ChildNodes) {
    if (node.Roles.Count == 0) {
        // just add.
        nodes.Add(node);
        continue;
    } else {
        // validate security.
        foreach (var role in node.Roles) {
             if (this.Page.User.IsInRole(role.ToString())) {
                 nodes.Add(node);
                 break;
             }
        }
   }
}

// return list.
this.ListViewTopMenu.DataSource = SiteMap.RootNode.ChildNodes;
this.ListViewTopMenu.DataBind();


I decided that, because I was going to need to reuse this functionality in several places and I wanted to avoid creating a class that would perform this task specifically,  that I should add a new method to the SiteMapCollection class using a C# 3.0 Extension Method. 

Step 1 - Extension Method

public static class SiteMapNodeCollectionExtension {
	
	public static IList FilterByRoles(
		this SiteMapNodeCollection nodeColl, 
		IPrincipal user) {
		
		// collection used to store array values to return to browser
		List nodes = new List();

		// iterate through the node collection to return the valid nodes.
		foreach (SiteMapNode node in nodeColl) {
			if (node.Roles.Count == 0) {
				// just add.
				nodes.Add(node);
				continue;

			} else {
				// validate security.
				foreach (var role in node.Roles) {
					if (user.IsInRole(role.ToString())) {
						// add to collection.
						nodes.Add(node);
						break;
					}
				}
			}
		}
		return nodes;
	}
	
}

 

This blog is not intended to be a tutorial, but I would like to point out the facts that C# Extension methods have to be defined in a static class as a static method and the first parameter must be the class to be extended (Notice the use of the 'this' keyword on the fist parameter).

Step 2 - Refactoring of the client code.

// bind list.
this.ListViewTopMenu.DataSource = SiteMap.RootNode.ChildNodes.FilterByRoles(this.Page.User);
this.ListViewTopMenu.DataBind();

Thank you for reading,

Roberto Hernandez

Caching Abstraction Solution - .NET 3.5

Today, as I was writing the frontend to an ASP.NET web application I noticed a trend in my code.  I had the following block of code in one form or another in several places.

protected string MemberFullName() {

    // build the cache key.
    string cacheKey = string.Format("Member@FullName@{0}"
        , this.Page.User.Identity.Name);

    // build cache entry.
    if (this.Cache[cacheKey] == null) {

        // get membership service.
        var membershipService = DependencyFactory.MembershipService();

        // get member.
        var member = membershipService
            .MemberGetByUsername(this.Page.User.Identity.Name);

        // get full name.
        string fullName = string.Format("{0}, {1}", 
            member.Lastname, 
            member.Firstname);

        // add to cache.
        this.Cache.Insert(cacheKey, 
            fullName, 
            null, 
            DateTime.Now.AddMinutes(5), 
            TimeSpan.Zero);
    }

    // return value.
    return (string)this.Cache[cacheKey];
}

 
Immediately I decided to address the issues that could arise from letting this behavior continue. First of all, I wanted to decouple the direct dependency to the ASP.NET Caching implementation, that way if in the future I decided to cache using another provider I would be able to make the switch without huge problems. I also wanted to use some of the cool features that have been available since the release of the .NET 3.0 Framework like Lambdas, and some oldies but goodies, like Generics and Anonymous Methods.

Step 1 - I coded a basic enum to use as the type of information to be cached.

public enum CacheKey {
    MembershipRolesByUsername,
    MembershipFullNameByUsername,
}


Step 2 -  I built the following interface that will provide the abstraction.

public interface ICacheProvider<T> {
    T GetItemFromCache(CacheKey type, string key, int minutes, Func<T> builderFunction);
}


Generics is used to add flexibility to the Cache provider while retaining the elegance and compile time advantages of strongly typed code. It has a couple of parameters but the one that should really catch your eye is the builderFunction (Func<T>) which allows us to pass in the function used to create the item to cache by using a Lambda expression or an Anonymous Method.

Step 3 - Implement the cache provider.

public class CacheProvider<T> : ICacheProvider<T> {

    #region ICacheProvider Members

    public T GetItemFromCache(CacheKey type, 
                 string key, 
                 int minutes, 
                 Func<T> builderFunction) {

        // build the cache key.
        string cacheKey = string.Format(string.Concat(type.ToString(), "{0}"), key);

        // get current cache.
        var context = HttpContext.Current;

        // build cache entry.
        if (context.Cache[cacheKey] == null)
            context.Cache.Insert(cacheKey, 
                 builderFunction.Invoke(), 
                 null, 
                 DateTime.Now.AddMinutes(minutes), 
                 TimeSpan.Zero);

        // return value.
        return (T)context.Cache[cacheKey];
    }

    #endregion
}


Nothing real fancy to explain here, the only thing I would point out is that the function to build the item doesn't get called if the item is already in the cache which is the whole point of caching.

Step 4 - Use the Cache provider
Option A - With an anonymous method.

// anonymous function.
Func<string> memberFullNameFunction = delegate() {
     var member = DependencyFactory.MembershipService()
          .MemberGetByUsername(this.Page.User.Identity.Name);
     return string.Format("{0},{1}", member.Lastname, member.Firstname);
};

// return value.
return new CacheProvider<string>()
     .GetItemFromCache(CacheKey.MembershipFullNameByUsername
          , this.Page.User.Identity.Name
          , 5
          , memberFullNameFunction);


Option B - With a Lambda Expression

// return value.
return new CacheProvider()
    .GetItemFromCache(CacheKey.MembershipFullNameByUsername
        , this.Page.User.Identity.Name
        , 5
        , ()  => {
                var member = DependencyFactory.MembershipService()
                    .MemberGetByUsername(this.Page.User.Identity.Name);
                return string.Format("{0},{1}", 
                    member.Lastname, 
                    member.Firstname);
        });


Depending on personal taste I guess one way of calling the provider might seem simpler than the other.

Thanks for reading,

Roberto Hernandez

Ramblings on ASP.NET MVC - A new start!

The following is a link to a free PDF book chapter on ASP.NET MVC.  It is no secret that I am a big fan of ASP.NET MVC and I believe that it is one of the key new technologies that we should all be looking into sooner rather than later.

 

http://weblogs.asp.net/scottgu/archive/2009/03/10/free-asp-net-mvc-ebook-tutorial.aspx

 

The following is a list of my personal beliefs regarding ASP.NET MVC and how I think it currently affects my day to day decisions as an application architect and developer.

  • I believe it is easier to code with a strict separation of concerns using the ASP.NET MVC Framework.
    • Duh! It is one of the goals of the MVC Pattern, but I still think it should be mentioned since this makes ASP.NET MVC the appropriate technology to use when working with multi-tiered enterprise applications.
  • I believe it is easier to develop a Web 2.0 application using the ASP.NET MVC Framework.
    • No viewstate, and strange ASP.NET WebForms control renderings that get in the way of using current web standards and top of the line AJAX frameworks like jquery, extjs, yui, and prototype.
  • I believe it is easier to implement, and manage security in an ASP.NET MVC application.
    • There is less exposure as security is managed at the controller method instead of the .aspx page.
    • Implementing security trimming as an attribute rocks!! It is not a new idea by any means, but it should be noted that it provides you with the ability to move your security configuration out of the Web.Config file without having to go code crazy.
  • I don't believe ASP.NET MVC is an environment for building RAD applications.  So for small/medium projects and applications that are less prone to change over time, I would still recommend using ASP.NET WebForms.
    Warning: I reserve the right to change my mind completely in the near future.
    • No current UI designer support.
    • No existing third party controls available.
    • No need to be an Architecture Astronaut.
    • Exception: If you are building a RIA application it makes perfect sense to use ASP.NET MVC as your JSON web services tier and you can use any third party controls developed for your presentation tier technology (Silverlight, Flex, Flash, Air, Ajax, etc.) while still maintaining a solid architecture.

 

Have fun reading the book,

 

Roberto Hernandez

Silverlight 1.0 (RC) - Surface Demo

Hi Everybody,

One of my favorite demos of Silverlight 1.1 Alpha (Currently Silverlight 2.0) has always been the Surface demo (click here). Having said that it has always been frustrating for me that this demo was only available for the Managed Code version of Silverlight.   So, I took it as a task to make this demo available and downloadable for the Silverlight 1.0 RC crowd.

So, without any delays,

Click here to view and here to download.

Thank you,
_____________
Roberto Hernández-Pou
MCAD MCSD.NET MCT MCDBA MCSE


Saludos!!!

De las demostraciones de Silverlight 1.1 Alpha (actualmente Silverlight 2.0) que he visto la favorita siempre ha sido el "Silverlight Surface" (click here). Habiendo dicho eso, siempre me ha molestado que esta demostración solo este disponible para codigo manejado.  Obviamente, me decidi a escribir esta demostración para Javascript y Silverlight 1.0 RC.

Entonces, sin más retrasos,

Dele aqui para  visualizar y aqui para descargar.

Gracias,
_____________
Roberto Hernández-Pou
MCAD MCSD.NET MCT MCDBA MCSE -