Wednesday, March 26, 2008

I'm speaking at the next Sussex Geek Dinner

Simon Harriyott has invited me to talk at the next Sussex Geek Dinner on Wednesday, April 23, 2008 at 8:00  PM at The Black Horse on Church Street in Brighton.  Here's a map.


View Larger Map

I'll be reprising my DDD6 talk, "Why do I need an Inversion of Control Container", but renamed as "Alternative Architectures: Inversion of Control", since Simon thought the first title was too geeky ;) I've covered a lot of the subject matter here if you'd like an introduction. Check out:

The Castle Project's Windsor Container and why I might need it.

What is Inversion of Control

Windsor Container Resources

Come along if you can, it should be fun. Sign up here.

Tuesday, March 25, 2008

File uploads with the MVC Framework

UPDATE: This post is out of date. It talks about an earlier version of the MVC Framework. Please check the ASP.NET MVC documentation for how to do file uploads.

There have been a couple of questions on the ASP.NET MVC newsgroup about this recently. It's pretty straight forward, you simply use the standard HTML input tag (type="file") in your form and then iterate through the HttpRequest's Files collection in your controller.

Here's the view's HTML:

<form action="/Document.mvc/UpdateDocument/" method="post" enctype="multipart/form-data">
   <label for="file1">Document 1</label>
   <input type="file" id="file1" name="file1" />

   <label for="file2">Document 2</label>
   <input type="file" id="file2" name="file2" />

   <label for="file3">Document 3</label>
   <input type="file" id="file3" name="file3" />
</form>

And here's the controller action:

public void SaveDocuments()
{
   foreach (string inputTagName in Request.Files)
   {
       HttpPostedFile file = Request.Files[inputTagName];
       if (file.ContentLength > 0)
       {
           string filePath = Path.Combine(@"C:\MyUploadedFiles", Path.GetFileName(file.FileName));
           file.SaveAs(filePath);
       }
   }
}

Thursday, March 20, 2008

Using the IRepository pattern with LINQ to SQL

27th March 2009. It's now a year since I wrote this post. Thanks to some comments by Janus2007 I've realised that it needs updating. I've replaced the code with the current version of the Suteki Shop LINQ generic repository. There are a number of changes in the way it works. The most obvious, and one that I should have updated a long time ago is the GetAll method returns  an IQueryable<T> rather than an array. I actually changed this soon after I wrote the post, but totally forgot about the naive implementation given here.

The other major change is marking the SubmitChanges methods as obsolete. Jeremy Skinner, who has been doing some excellent work on Suteki Shop has pushed this change. UoW (DataContext) management is now handled by attributes on action methods.

Please have a look at the Suteki Shop code to see the generic repository in action:

LINQ to SQL is a quantum leap in productivity for most mainstream .NET developers. Some folks may have been using NHibernate or some other ORM tool for years, but my experience in a number of .NET shops has been that the majority of developers still hand code their data access layer. LINQ is going to bring some fundamental changes to the way we architect our applications. Especially being able to write query style syntax directly in C# against both a SQL Server database and against in memory object graphs begs some interesting questions about application architecture.

So where is our point of separation between data access and domain? Surely I'm not recommending that we abandon a layered architecture and write all our data access directly into our domain classes?

My current project is based on the new MVC Framework. I've been using LINQ to SQL for data access as well as an IoC container (Windsor) and NUnit plus Rhino Mocks for testing. For my data access layer I've used the IRepository pattern popularized by Ayende in his excellent MSDN article on IoC and DI. My Repository looks like this:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Linq;
using Suteki.Common.Extensions;
namespace Suteki.Common.Repositories
{
    public interface IRepository<T> where T : class
    {
        T GetById(int id);
        IQueryable<T> GetAll();
        void InsertOnSubmit(T entity);
        void DeleteOnSubmit(T entity);
		[Obsolete("Units of Work should be managed externally to the Repository.")]
        void SubmitChanges();
    }
    public interface IRepository
    {
        object GetById(int id);
        IQueryable GetAll();
        void InsertOnSubmit(object entity);
        void DeleteOnSubmit(object entity);
		[Obsolete("Units of Work should be managed externally to the Repository.")]
        void SubmitChanges();
    }
    public class Repository<T> : IRepository<T>, IRepository where T : class
    {
        readonly DataContext dataContext;
        public Repository(IDataContextProvider dataContextProvider)
        {
            dataContext = dataContextProvider.DataContext;
        }
        public virtual T GetById(int id)
        {
            var itemParameter = Expression.Parameter(typeof(T), "item");
            var whereExpression = Expression.Lambda<Func<T, bool>>
                (
                Expression.Equal(
                    Expression.Property(
                        itemParameter,
                        typeof(T).GetPrimaryKey().Name
                        ),
                    Expression.Constant(id)
                    ),
                new[] { itemParameter }
                );
            return GetAll().Where(whereExpression).Single();
        }
        public virtual IQueryable<T> GetAll()
        {
            return dataContext.GetTable<T>();
        }
        public virtual void InsertOnSubmit(T entity)
        {
            GetTable().InsertOnSubmit(entity);
        }
        public virtual void DeleteOnSubmit(T entity)
        {
            GetTable().DeleteOnSubmit(entity);
        }
        public virtual void SubmitChanges()
        {
            dataContext.SubmitChanges();
        }
        public virtual ITable GetTable()
        {
            return dataContext.GetTable<T>();
        }
        IQueryable IRepository.GetAll()
        {
            return GetAll();
        }
        void IRepository.InsertOnSubmit(object entity)
        {
            InsertOnSubmit((T)entity);
        }
        void IRepository.DeleteOnSubmit(object entity)
        {
            DeleteOnSubmit((T)entity);
        }
        object IRepository.GetById(int id)
        {
            return GetById(id);
        }
    }
}

As you can see, this generic repository insulates the rest of the application from the LINQ to SQL DataContext and provides basic data access methods for any domain class. Here's an example of it being used in a simple controller.

using System.Web.Mvc;
using Suteki.Common.Binders;
using Suteki.Common.Filters;
using Suteki.Common.Repositories;
using Suteki.Common.Validation;
using Suteki.Shop.Filters;
using Suteki.Shop.Services;
using Suteki.Shop.ViewData;
using Suteki.Shop.Repositories;
using MvcContrib;
namespace Suteki.Shop.Controllers
{
	[AdministratorsOnly]
    public class UserController : ControllerBase
    {
        readonly IRepository<User> userRepository;
        readonly IRepository<Role> roleRepository;
    	private readonly IUserService userService;
    	public UserController(IRepository<User> userRepository, IRepository<Role> roleRepository, IUserService userService)
        {
            this.userRepository = userRepository;
            this.roleRepository = roleRepository;
        	this.userService = userService;
        }
        public ActionResult Index()
        {
            var users = userRepository.GetAll().Editable();
            return View("Index", ShopView.Data.WithUsers(users));
        }
        public ActionResult New()
        {
            return View("Edit", EditViewData.WithUser(Shop.User.DefaultUser));
        }
		[AcceptVerbs(HttpVerbs.Post), UnitOfWork]
		public ActionResult New(User user, string password)
		{
			if(! string.IsNullOrEmpty(password))
			{
				user.Password = userService.HashPassword(password);
			}
			try
			{
				user.Validate();
			}
			catch(ValidationException ex)
			{
				ex.CopyToModelState(ModelState, "user");
				return View("Edit", EditViewData.WithUser(user));
			}
			userRepository.InsertOnSubmit(user);
			Message = "User has been added.";
			return this.RedirectToAction(c => c.Index());
		}
        public ActionResult Edit(int id)
        {
            User user = userRepository.GetById(id);
            return View("Edit", EditViewData.WithUser(user));
        }
		[AcceptVerbs(HttpVerbs.Post), UnitOfWork]
		public ActionResult Edit([DataBind] User user, string password)
		{
			if(! string.IsNullOrEmpty(password))
			{
				user.Password = userService.HashPassword(password);
			}
			try
			{
				user.Validate();
			}
			catch (ValidationException validationException) 
			{
				validationException.CopyToModelState(ModelState, "user");
				return View("Edit", EditViewData.WithUser(user));
			}
			return View("Edit", EditViewData.WithUser(user).WithMessage("Changes have been saved")); 
		}
        public ShopViewData EditViewData
        {
            get
            {
                return ShopView.Data.WithRoles(roleRepository.GetAll());
            }
        }
    }
}

Because I'm using an IoC container I don't have to do any more than request an instance of IRepository<User> in the constructor and because the Windsor Container understands generics I only have a single configuration entry for all my generic repositories:

<?xml version="1.0"?>
<configuration>
  <!-- windsor configuration. 
  This is a web application, all components must have a lifesytle of 'transient' or 'preWebRequest' -->
  <components>
    <!-- repositories -->
    <!-- data context provider (this must have a lifestyle of 'perWebRequest' to allow the same data context
    to be used by all repositories) -->
    <component
      id="datacontextprovider"
      service="Suteki.Common.Repositories.IDataContextProvider, Suteki.Common"
      type="Suteki.Common.Repositories.DataContextProvider, Suteki.Common"
      lifestyle="perWebRequest"
     />
	<component
		id="menu.repository" 
		service="Suteki.Common.Repositories.IRepository`1[[Suteki.Shop.Menu, Suteki.Shop]], Suteki.Common"
		type="Suteki.Shop.Models.MenuRepository, Suteki.Shop"
		lifestyle="transient"
		/>
		
    <component
      id="generic.repository"
      service="Suteki.Common.Repositories.IRepository`1, Suteki.Common"
      type="Suteki.Common.Repositories.Repository`1, Suteki.Common"
      lifestyle="transient" />
    
	....
  </components>
  
</configuration>

The IoC Container also provides the DataContext. Note that the DataContext's lifestyle is perWebRequest. This means that a single DataContext is shared between all the repositories in a single request.

To test my UserController I can pass an object graph from a mock IRepository<User>.

[Test]
public void IndexShouldDisplayListOfUsers()
{
    User[] users = new User[] { };
    UserListViewData viewData = null;

    using (mocks.Record())
    {
        Expect.Call(userRepository.GetAll()).Return(users);

        userController.RenderView(null, null);
        LastCall.Callback(new Func<string, string, object, bool>((v, m, vd) => 
        {
            viewData = (UserListViewData)vd;
            return true;
        }));
    }

    using (mocks.Playback())
    {
        userController.Index();
        Assert.AreSame(users, viewData.Users);
    }
}

Established layered architecture patterns insulate the domain model (business objects) of a database from the data access code by layering that code into a data access layer that provides services for persisting and de-persisting objects from and to the database. This layered approach becomes essential as soon as you start doing Test Driven Development which requires you to test you code in isolation from your database.

So is LINQ data access code? I don't think so. Because the syntax for querying in-memory object graphs is identical to that for querying the database it makes sense to place LINQ queries in your domain layer. During testing, the component under test can work with in memory object graphs, but when integrated with the data access layer those same queries become SQL queries to a database.

Here's a simple example. I've got the canonical Customer->Orders->OrderLines business entities. Now say I get an Customer from my IRepository<Customer>, I can then query my Customer's Orders using LINQ inside my controller:

Customer customer = customerRepository.GetById(customerId);
int numberOfOrders = customer.Orders.Count(); // LINQ

I unit test this by returning a fully formed Customer with Orders from my mock customerRepository, but when I run this code against a concrete repository LINQ to SQL will construct a SQL statement, something like:

SELECT COUNT(*) FROM Order WHERE CustomerId = 34.

Saturday, March 15, 2008

LINQ to String

LinqInAction

I'm currently reading the excellent Linq in Action by Marguerie, Eichert and Wooley. It's great exposition of all things Linq and there are lots really well explained examples. Something which tickled me, which I hadn't realized before is that you can use Linq over strings. Well of course, since System.String implements IEnumerable<T>. It gives you some interesting alternatives to standard string functions:

string text = "The quick brown fox jumped over the lazy dog.";

// substring
text.Skip(4).Take(5).Write();   // "quick"

// remove characters
text.Where(c => char.IsLetter(c)).Write(); // "Thequickbrownfoxjumpedoverthelazydog."

string map = "abcdefg";

// strip out only the characters in map
text.Join(map, c1 => c1, c2 => c2, (c1, c2) => c1).Write(); // "ecbfedeeadg"

// does text contain q?
text.Contains('q').Write(); // true

The 'Write()' at the end of each expression is just an extension method on IEnumerable<T> that writes to the console.

OK, so most of these aren't that useful and there are built in string functions to do most of these (except the mapping I think). The cool thing is that you can write a little function, called 'Chars' in my example, that exposes a file stream as IEnumerable<T>. This means you can do the same tricks on a file and since we're just building up a decorator chain of enumerators the entire file isn't loaded into memory, only one character at a time. In this example, showing the 'substring' again, the file will stop being read after the first nine characters.

string text = "The quick brown fox jumped over the lazy dog.";
string myDocuments = System.Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string path = Path.Combine(myDocuments, "someText.txt");

File.WriteAllText(path, text);

using (StreamReader reader = File.OpenText(path))
{
    reader.Chars().Skip(4).Take(5).Write();
}

Here's the code for the 'Chars' function.

public static class StreamExtensions
{
    public static IEnumerable<char> Chars(this StreamReader reader)
    {
        if (reader == null) throw new ArgumentNullException("reader");

        char[] buffer = new char[1];
        while(reader.Read(buffer, 0, 1) > 0)
        {
            yield return buffer[0];
        }
    }
}

In the book the authors show a similar function that reads a file line by line and they use it to enumerate over a csv file. The resulting syntax is extremely neat, but I'll let you buy the book and see it for yourself:)

Thursday, March 13, 2008

Currying in C# with Oliver Sturm

I really enjoyed last night's talk at the London DNUG by Oliver Sturm titled 'Functional programming with C#'. I had a genuine 'I did not know you could do that' moment when he showed us how to do Currying in C#. Of course there was much more to the talk than that, including lambda expressions, closures and map-filter-reduce, but they were less of a surprise. Still an excellent explanation of all things functional.

So, what's currying? Well it's got nothing to do with vindaloo, it's a really simple idea which basically says that if you give a function less arguments than it expects you get back another function that only expects the missing arguments. Now, of course if you give a function in C# less arguments than it expects you get a compilation error. What Oliver showed us was that its trivially easy to write a 'Curry' function that will return any function you give it in a curried version. You can curry to your hearts content.

OK, so lambda expressions give us this great syntax for creating anonymous delegates, or little functions you can assign to a variable. Here's a trivial example; add:

Func<int, int, int> add = (x, y) => x + y;
int a = add(2, 3);  // a = 5

You use the add function like any other. Here we're adding 2 and 3 and returning 5. Now we can also use the lambda syntax to build an add function that within it returns a function that's just waiting for the other side of the add expression. OK, that's gobbledygook, it's easier to show than explain:

Func<int, Func<int, int>> curriedAdd = x => y => x + y;
int b = curriedAdd(2)(3); // b = 5

The result is the same, it's just that the syntax looks unfamiliar. Now we can curry our curriedAdd by just supplying one argument and then use our new add5 function as many times as we want:

var add5 = curriedAdd(5);

int c = add5(3); // c = 8
int d = add5(5); // d = 10

But you don't have to explicitly define your curried function when you've got a 'Curry' function that will create it for you. Here's another stupidly trivial example: We've got a function called addFourThings, we pass it into our Curry function and out pops curriedAddFourThings. We can use that to simply add four numbers, or we can progressively assign the arguments one at a time.

Func<int, int, int, int, int> addFourThings = (a, b, c, d) => a + b + c + d;

var curriedAddFourThings = Curry(addFourThings);

int result = curriedAddFourThings(1)(2)(3)(4);  // result = 10

var addOne = curriedAddFourThings(1);
var addOneAndTwo = addOne(2);
var addOneAndTwoAndThree = addOneAndTwo(3);

int result2 = addOneAndTwoAndThree(4); // result2 = 10

Here is Oliver's set of Curry function overloads.

public Func<T1, Func<T2, T3>> Curry<T1, T2, T3>(Func<T1, T2, T3> function)
{
    return a => b => function(a, b);
}

public Func<T1, Func<T2, Func<T3, T4>>> Curry<T1, T2, T3, T4>(Func<T1, T2, T3, T4> function)
{
    return a => b => c => function(a, b, c);
}

public Func<T1, Func<T2, Func<T3, Func<T4, T5>>>> Curry<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5> function)
{
    return a => b => c => d => function(a, b, c, d);
}

Pretty simple eh. This is all very neat, and I can imagine how it could be very useful in factoring algorithms. Oliver showed us an example in his talk. But I think I'm going to need to see a few more cases of it being used in real world situations and maybe try it out a few times before it becomes a natural part of my programming toolkit.

Windsor IoC Container and MVC Framework CTP 2

I spent all morning upgrading my current MVC project to use the MVC Framework CTP 2. It went mostly OK. There are a few funnies, like the way the arguments to Html.Form() extension method's parameters have been reversed and the changes to Html.ActionLink, but generally speaking it was pretty smooth. All the stuff that was in the MvcToolkit is now in the System.Web.Mvc assembly, so I was able to remove that reference from my project. MvcContrib has been updated for CTP 2, but the source is in a branch, so you shouldn't just get the latest trunk like I did initially (Duh!) Go here instead: http://mvccontrib.googlecode.com/svn/branches/MVCPreview2/. I checked it out and it built no problem. Then it was a simple case of dropping in the new assemblies.

I'm using Castle Windsor in my MVC project which means I use the WindsorControllerFactory from MvcContrib rather than the default controller factory. One of the things that has changed is the signature of the IControllerFactory's CreateController method, it now takes a string of the controller name rather than its type. I can see why this makes more sense because your controller factory might not have the same idea about the type it wants to supply as the routing framework. This means that we have to use the string ID of the controller that's registered with windsor rather than it's type. I had to make a small change in the code of the WindsorControllerFactory to fix a casing bug (URLs aren't case sensitive, but the windsor service ids are):

public IController CreateController(RequestContext context, string controllerName)
{
 //Hack...
 controllerName = controllerName.ToLower() + "controller"; 

 IWindsorContainer container = GetContainer(context);
 return (IController)container.Resolve(controllerName);
}

That means you also have to register the controllers with lower case names. Here's my InitializeWindsor method in my global.asax file:

protected virtual void InitializeWindsor()
{
    if (container == null)
    {
        // create a new Windsor Container
        container = new WindsorContainer(new XmlInterpreter("Configuration\\Windsor.config"));

        // automatically register controllers
        Assembly.GetExecutingAssembly().GetExportedTypes()
            .Where(type => IsController(type))
            .Each(type => container.AddComponentWithLifestyle(
                type.Name.ToLower(), 
                type, 
                Castle.Core.LifestyleType.Transient));

        // set the controller factory to the Windsor controller factory (in MVC Contrib)
        ControllerBuilder.Current.SetControllerFactory(typeof(WindsorControllerFactory));
    }
}

private bool IsController(Type type)
{
    return typeof(IController).IsAssignableFrom(type);
}

The .Each extension method is a little addition to Linq that a lot of people have blogged about, including me in this post.

Update

Jeremy Skinner, who's responsible for the WindsorControllerFactory has updated it in MvcContrib. He's also added some extension methods for the windsor container to register controllers, so now my InitializeWindsor method looks like this:

protected virtual void InitializeWindsor()
{
    if (container == null)
    {
        // create a new Windsor Container
        container = new WindsorContainer(new XmlInterpreter("Configuration\\Windsor.config"));

        // automatically register controllers
        container.RegisterControllers(Assembly.GetExecutingAssembly());

        // set the controller factory to the Windsor controller factory (in MVC Contrib)
        ControllerBuilder.Current.SetControllerFactory(typeof(WindsorControllerFactory));
    }
}

Thursday, March 06, 2008

Forms Authentication with the MVC Framework

I'm just wrapping up writing my first commercial application with the new MVC Framework. Because it sits on top of ASP.NET, simply replacing the Web Forms model, you can use all of the ASP.NET infrastructure. This includes Forms Authentication. I want to show how I used Forms Authentication with my own database rather than using the membership API, but you can plug in membership quite easily too.

The first thing you need to do is set up your Web.config file to use Forms authentication:

<!--Using forms authentication-->
<authentication mode="Forms">
  <forms loginUrl="/login.mvc/index" defaultUrl="/home.mvc/index" />
</authentication>

Just set mode to Forms and the login URL to your login page. This means that any unauthenticated users are redirected to the login page. I've also set the default URL to my home page. The other change you'll need to make to your web.config file is to allow unauthenticated users to see your login page and any CSS and image files (although this depends on how you configure IIS). If you've got public areas of your web site you will need to add these as well.

  <!-- we don't want to stop anyone seeing the css and images -->
  <location path="Content">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <!-- allow any user to see the login controller -->
  <location path="login.mvc">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>

Next we need to set up the login controller. Since I'm using my own data access I need to pass in my user repository; that's the class that wraps my user data access.

public class LoginController : Controller
{
    readonly IUserRepository userRepository;

    public LoginController(IUserRepository userRepository)
    {
        this.userRepository = userRepository;
    }
}

We need a controller action method to render the login form. I've called mine Index. The LoginViewData simply allows me to include an error message, we'll see how that works later on.

[ControllerAction]
public void Index()
{
    RenderView("index", new LoginViewData());
}

Next we need to create the view for the login form. I've just rendered a simple form.

<%= Html.ErrorBox(ViewData.ErrorMessage) %>

<% using(Html.Form("Authenticate", "Login")) { %>
<div id="login_form">

    <p>Enter your details</p>
    
    <label for="username">User name</label>
    <%= Html.TextBox("username") %>
    
    <label for="password">Password</label>
    <%= Html.Password("password") %>

    <%= Html.SubmitButton() %>
</div>
<% } %>

Note that the form posts to the Authenticate action. This action is where we do all the work of checking the user's credentials and logging them in.

[ControllerAction]
public void Authenticate(string username, string password)
{
    User user = userRepository.GetUserByName(username);

    if (user != null && user.Password == password)
    {
        SetAuthenticationCookie(username);
        RedirectToAction("Index", "Home");
    }
    else
    {
        // If we got here then something is wrong with the supplied username/password
        RenderView("Index", new LoginViewData
            {
                ErrorMessage = "Invalid User Name or Password."
            });
    }
}

public virtual void SetAuthenticationCookie(string username)
{
    FormsAuthentication.SetAuthCookie(username, false);
}

Yes, I know, it's very naughty storing passwords unencrypted in the database, but I wanted to keep this demonstration simple. That's my excuse anyway :) You can see that we simply get the user with the given username from the database (my user repository) , make sure the passwords match and call the public virtual method SetAuthenticationCookie which calls the forms authentication API's SetAuthCookie method. This effectively logs the user in. Why is SetAuthenticationCookie a separate method, why not just call SetAuthCookie in the Authenticate action? This is so that we can unit test the Login controller without invoking the forms authentication API. We can create a partial mock of the Login controller and set up an expectation for SetAuthenticationCookie because it's marked public and virtual.

This is all you need to do to make forms authentication work with the MVC Framework. However, there was one additional thing I wanted to achieve. I have my own User class that implements IPrinciple:

public partial class User : IPrincipal
{
    public static User Guest
    {
        get
        {
            return new User() { Username = "Guest", Role = Role.Guest };
        }
    }

    #region IPrincipal Members

    public IIdentity Identity
    {
        get 
        {
            bool isAuthenticated = !(Role.Name == Role.Guest.Name);
            return new Identity(isAuthenticated, this.Username);
        }
    }

    public bool IsInRole(string role)
    {
        return this.Role.Name == role;
    }

    #endregion
}

This User class was generated by the LINQ to SQL designer and the above code is simply a partial extension of it. My data model also includes Roles so I can supply an implementation of IsInRole method. The identity property is handled by returning a simple implementation of IIdentity. To be able to make use of my IPrinciple implementation I need to supply my User to the HttpContext on each request and the best way of doing this is to handle the OnAuthenticateRequest event in Global.asax.

protected void Application_OnAuthenticateRequest(Object sender, EventArgs e)
{
    if (Context.User != null)
    {
        if (Context.User.Identity.IsAuthenticated)
        {
            User user = userRepository.GetUserByName(Context.User.Identity.Name);

            if (user == null)
            {
                throw new ApplicationException("Context.User.Identity.Name is not a recognised user.");
            }

            System.Threading.Thread.CurrentPrincipal = Context.User = user;
            return;
        }
    }
    System.Threading.Thread.CurrentPrincipal = Context.User = CreateGuestUser();
}

We get HttpContext's user, check if it's been authenticated. If it has, it means this user has already logged in and is one of the users in our database. We retrieve the user from our user repository and set the HttpContext's User to our user. We also set the current thread's currentPrinciple to our user. If the user is not authenticated we create a guest user and use that instead.

Now that the current thread's currentPrinciple is one of our users, we can do role based checks on any bit of code we want. Here, for example we're making sure that only administrators can execute this DeleteSomethingImportant action:

[ControllerAction]
[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]
public void DeleteSomethingImportant(int id)
{
 ....
}

You can access the current user at any time in the application simply by casting the HttpContext's User to your User. This makes role based menu's or features trivial to write.

Update

I had a question recently (hi Jasper) about the Identity class returned by the Identity property of my User class. This is a simple implementation of the System.Security.Principle.IIdentity interface that just returns the Username of my User class. Here it is in full:

public class Identity : IIdentity
{
    bool isAuthenticated;
    string name;

    public Identity(bool isAuthenticated, string name)
    {
        this.isAuthenticated = isAuthenticated;
        this.name = name;
    }

    #region IIdentity Members

    public string AuthenticationType
    {
        get { return "Forms"; }
    }

    public bool IsAuthenticated
    {
        get { return isAuthenticated; }
    }

    public string Name
    {
        get { return name; }
    }

    #endregion
}

Hopefully this makes things a little clearer.

Monday, March 03, 2008

How to output Windsor Container's dependency graph

I was asked about this today (hi Sham!). It turns out to be very easy since the Windsor Container exposes it's dependency graph via it's GraphNodes collection. Here's a little console application that'll output the dependency graph of any application. You simply give it the path of the Windsor configuration file and the path of your application's bin folder.

Here's the output from a sample run:

C:\>Suteki.DependencyViewer
"C:\source\Suteki\Suteki.SomeApplication\Configuration\Windsor.config"
"C:\source\Suteki\Suteki.SomeApplication\bin"

Suteki.SomeApplication.Controllers.StatusController
        Suteki.SomeApplication.Repositories.UserRepository
                Suteki.SomeApplication.SomeApplicationDataContext
        Suteki.SomeApplication.Repositories.InstructionRepository
                Suteki.SomeApplication.SomeApplicationDataContext
        Suteki.SomeApplication.Repositories.Repository`1
                Suteki.SomeApplication.SomeApplicationDataContext
        Suteki.SomeApplication.Repositories.Repository`1
                Suteki.SomeApplication.SomeApplicationDataContext
        Suteki.SomeApplication.Services.MatterSubmissionService
                Suteki.SomeApplication.MatterServiceProxy.MatterServiceClient
                Suteki.SomeApplication.Services.DocumentUploadServiceProxy
                Suteki.SomeApplication.Services.InstructionPdfService
                        Suteki.SomeApplication.Service.Model.Services.DocumentService
                                Suteki.SomeApplication.Service.Model.Services.DateService
        Suteki.SomeApplication.Services.EmailToFileSender
        Suteki.SomeApplication.Services.EmailTemplateService

And here's the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.Windsor;
using Castle.Core;
using System.Reflection;
using System.IO;

namespace Suteki.DependencyViewer
{
    public class Program
    {
        private Dictionary<string, Assembly> assemblyList;

        public static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                Console.WriteLine("usage: Suteki.DependencyViewer <config file> <bin directory>");
                return;
            }

            Program program = new Program();
            program.Execute(args[0], args[1]);
        }

        private void Execute(string configPath, string binPath)
        {
            if (!File.Exists(configPath))
            {
                Console.WriteLine("The config file at '{0}' does not exist");
            }
            if (!Directory.Exists(binPath))
            {
                Console.WriteLine("The bin directory at '{0}' does not exist");
            }

            LoadDlls(binPath);

            WindsorContainer container = new WindsorContainer(configPath);

            GraphNode[] graphNodes = container.Kernel.GraphNodes;

            foreach (GraphNode graphNode in graphNodes)
            {
                if (graphNode.Dependers.Length == 0)
                {
                    Console.WriteLine();
                    WalkGraph(graphNode, 0);
                }
            }
        }

        private void WalkGraph(IVertex node, int level)
        {
            ComponentModel componentModel = node as ComponentModel;
            if (componentModel != null)
            {
                Console.WriteLine("{0}{1}", new string('\t', level), componentModel.Implementation.FullName);
            }

            foreach (IVertex childNode in node.Adjacencies)
            {
                WalkGraph(childNode, level + 1);
            }
        }

        private void LoadDlls(string binPath)
        {
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

            string[] dlls = System.IO.Directory.GetFiles(binPath, "*.dll");
            assemblyList = new Dictionary<string, Assembly>(dlls.Length);

            foreach (String fileName in dlls)
            {
                Assembly asm = System.Reflection.Assembly.LoadFrom(fileName);
                assemblyList.Add(asm.FullName.Split(',')[0], asm);
            }
        }

        Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            return assemblyList[args.Name];
        }
    }
}