After Thought

Archive for the ‘C#’ Category

Continuous build and one click deployment

with 2 comments

Wouldn’t it be great if we deployed every time we checked in our code to reduce the stress associated with deployment. With the goal of making deployment as easy as possible, we at MVBA follow a process that seem to work really well for us. We tend to deploy every two two weeks to production and numerous times on test servers. Even though, we had one click deployment process, it was becoming tedious to manage multiple rake scripts for build and deployments. So we decided to clean up the process. After couple iterations we had a script in our hands that did exactly what we were looking for at the moment. We use albacore for our Rake tasks. If you are not using albacore for Rake tasks, you should definitely check it out.  It has a number of predefined tasks and it also makes adding generic or custom tasks easier. We use TeamCity as our continuous integration server. settings.yaml is used to maintain settings for different environments (developer, build, test and prod). Before compiling the solution, a task replaces all the config files with the current environment settings. For example, rake compile['developer'] will update the web.config and App.config files with developer.yaml file. You can also add settings related to deployment like dist_directory (directory where distributable is available), website path (like C:\WebSite) etc to the yaml file that the rake file can pick up when deploying. We divided our Build configuration into three categories -

  • Compile, run unit tests, run integration tests, run environment tests, create a temp distributable with version number that includes Web build, Windows Service build (we also deploy windows services as part of our deployment), TestBuild, DatabaseRebuild zip (scripts to rebuild the database), DatabaseUpdate zip (scripts to update the database) and Deployment Scripts zip (rake scripts that are needed to deploy the app).

  • Set up deployment files: Unzips the latest deployment zip file into a folder from where you can deploy

  • Deploy and run UI tests: Deploy the latest files onto web server, update your windows services, rebuild database (only on build and developer machines) and run the update scripts. Below is a rough draft of our deploy task. It can be re-factored to make it much cleaner.
class Deploy
include Albacore::Task

attr_accessor :website_base, :website_dir, :processor_dir, :tests_dir, :dist_directory, :web_dist, :service_dists, :tests_dist, :messages_dist, :messages_dir, :env, :database_build_type, :url, :rebuild_dir, :update_dir, :rebuild_dist, :update_dist

def initialize
@service_dists = []
@iis = "w3svc"
end

def execute
deploy
end

def deploy
puts "Deploying #{@web_dist}"

# stop iis
manage(@iis, 'stop', 1)

puts "Waiting for all the messages to be processed before stopping the service"
while(Dir["#{@messages_dir}/*.request"].count > 0)
sleep(2)
puts "."
end

# stop services
manage_windows_services(@service_dists, 'stop', 1)

# deploy website
deploy_app "#{@website_base}/#{@website_dir}", "#{@dist_directory}/#{@web_dist}"

# deploy services
@service_dists.each do |svc_name, svc_dist|
puts "Deploying #{svc_dist[:dist]}"
deploy_app "#{@website_base}/#{svc_dist[:dir]}", "#{@dist_directory}/#{svc_dist[:dist]}"
end

#deploy tests, messages and rebuild database
if (@database_build_type == "rebuild")
# deploy tests
puts "Deploying #{@tests_dist}"
deploy_app "#{@website_base}/#{@tests_dir}", "#{@dist_directory}/#{@tests_dist}"

# deploy rebuild
puts "Deploying #{@rebuild_dist}"
deploy_app "#{@website_base}/#{@rebuild_dir}", "#{@dist_directory}/#{@rebuild_dist}"

if File.exists? "#{@website_base}/#{@rebuild_dir}/rebuild_database.json"
puts "Rebuilding Database"
run_tests "#{@website_base}/#{@rebuild_dir}/#{@rebuild_dir}.dll"

# deploy messages
puts "Deploying #{@messages_dist}"
Dir.mkdir(@messages_dir) unless Dir.exists?(@messages_dir)
unzip("#{@website_base}/#{@rebuild_dir}/#{@messages_dist}", @messages_dir)
else
puts "There is no need to rebuild the database as there are no changes in the mapping files"
end
end
# deploy update
puts "Deploying #{@update_dist}"
deploy_app "#{@website_base}/#{@update_dir}", "#{@dist_directory}/#{@update_dist}"
puts "Updating Database"
run_tests "#{@website_base}/#{@update_dir}/#{@update_dir}.dll"

# start services
manage_windows_services(@service_dists, 'start', 1)

# start iis
manage(@iis, 'start', 1)
end

def deploy_app(working_dir, zip_file)
Dir.mkdir(working_dir) unless Dir.exists?(working_dir)
# unzip the files to working directory
unzip(zip_file, working_dir)
t = Dir.entries(working_dir).grep(/\.config\.#{@env}$/)
config_with_env = Dir.entries(working_dir).grep(/\.config\.#{@env}$/).first
return if (config_with_env.nil?)
config = File.basename(config_with_env, ".#{@env}")
FileUtils.mv "#{working_dir}/#{config_with_env}", "#{working_dir}/#{config}"
end

def manage(service, action, total_tries = 1, tries=0)
begin
sh "net #{action} #{service}"
rescue
tries +=1
puts "Caught error while performing #{action} on #{service}"
return if (tries == total_tries)
puts "Next try to #{action} the #{service} in 30 seconds"
sleep(30)
manage(action, tries) unless (tries >= total_tries)
end
end

def manage_windows_service(service_name, action, exe, tries)
if (action == 'start' && (`sc query #{service_name}`=~ /.*does not exist.*/) != nil)
sh "#{@website_base}/#{exe} install" unless (exe == nil)
end
manage(service_name, action, tries)
end

def manage_windows_services(services, action, tries)
services.each do |svc_name, svc_dist|
manage_windows_service(svc_name, action, "#{svc_dist[:dir]}/#{svc_dist[:exe]}", tries)
end
end

def unzip(file, dest)
unzip = Unzip.new
unzip.destination = dest
unzip.file = file
unzip.force = true
unzip.execute
end

def run_tests(assemblies)
nunit = NUnitTestRunner.new
nunit.command = get_nunit_x86
nunit.assemblies assemblies
nunit.execute
end
end

Before we deploy, we stop IIS, wait till all the services have finished processing before stopping all the windows services. We then deploy web and services. Tests are deployed only if the database_build_type is “rebuild” which is decided by :database_build_type in the settings file. :database_build_type is set to “rebuild” in developer and build, but it is set to “update” in test and prod (You don’t want to rebuild your production). We rebuild the database only if any of the fluent nHibernate mappings are changed in the latest check in. We then run the update scripts irrespective of what environment you are running on (We have an internal check that makes sure that a script is not run if it has already been run before). We then restart the windows services and finally IIS is restarted to complete the deployment process. Once the website is deployed, we run the UI tests and if all the UI tests are successful web dist, services dist, database update dist and deployment scripts dist are moved to its final destination folder from where you can deploy to test or prod. In our test and production servers we have a single batch script that calls 3 tasks

call rake set_up_deploy_files['test']
call rake copy_dist['test']
rake deploy['test']

The first line gets the latest deployment scripts or the deployment version you are looking for (you can pass in the version number as part of arguments to deploy a specific version like rake set_up_deploy_files['test','1.0.25.9217']). Second line gets Web dist, services dist and database update dist. Third line deploys web, services and updates the database structure if needed. This has reduced considerable overhead in maintaining scripts for different needs ensuring that we are always using the right deployment script. Moreover, we now have just one RakeFile that is used to build and deploy making it easier to maintain. As a result, we are now more confident of our deployment process.

Written by shashankshetty

July 25, 2011 at 1:00 pm

Posted in ASP.net, ASP.net MVC, C#, Rake, Uncategorized

Tagged with , ,

Setting up Elmah in your application to log into FogBugz (Bug tracking system)

with 2 comments

ELMAH (Error Logging Modules and Handlers)  is a pluggable error logging system created by Atif Aziz that can be hooked onto an ASP.Net application. It is very straight forward to set up and gives options to log errors to several back-end storages including databases, in-memory, XML files and send out email notification. Scott Hanselman blogged about setting up ELMAH a while back. This is just an extension to that post to log the error to bug tracking system like FogBugz if you are using one.

Here is how to set up ELMAH on your ASP.Net MVC that logs an entry in FogBugz when there is an error. Fogbugz allows to log an error just by sending an email to the FogBugz connected mailbox. So we will set up ELMAH to send an email when there is an error.

Download ELMAH Core Binary and add it your library. Add a reference to Elmah.dll in your web project.

Add following entries to your web.config

<httpModules>
 ...
 <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/>
</httpModules>

<modules runAllManagedModulesForAllRequests="true">
 ...
 <add name="Elmah.ErrorMail" type="Elmah.ErrorMailModule" preCondition="managedHandler" />
 <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
 <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/>
</modules>
<handlers>
 <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" preCondition="integratedMode" type="Elmah.ErrorLogPageFactory, Elmah"/>
</handlers>

<configSections>
 <sectionGroup name="elmah">
 <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
 </sectionGroup>
</configSections>
<elmah>
 <errorMail
 from="from@domain.com"
 to="to@domain.com"
 subject="<Application Name> Error"
 async="false"
 useSsl="true|false"
 smtpPort="60"
 userName="username"
 password="password"
 smtpServer="smtp.domain.com" />
</elmah>

That is it. ELMAH is set up and your application is ready to log any errors to FogBugz.

Before you proceed any further check if ELMAH is properly set up by going to http://localhost/elmah.axd. You should get the following screen.

You will still encounter yellow screen when there is an error. You can always redirect users to a nice looking page if there is an error by configuring your customErrors section as follows.

<customErrors mode="On" defaultRedirect="~/Error/SomeError">
 <error statusCode="404" redirect="~/Error/NotFound"/>
</customErrors>

Written by shashankshetty

January 13, 2011 at 11:23 am

Posted in ASP.net, ASP.net MVC, C#, Uncategorized

Tagged with ,

Eliminate if else using Smart Enums

with 4 comments

Open/Close principle (SOLID) states that class should be Open for extension and closed for modification. One way to achieve this is to eliminate conditional statements (if…else) in our code. Continuing our example of PlasticType from the Smart Enums post, let us say we have to write a method that has to decide the recycling program based on the plastic type.

public class Controller
{
	private readonly IRecycleManager _recycleManager;

	public Controller(IRecycleManager recycleManager)
	{
		_recycleManager = recycleManager;
	}

	public void Recycle(PlasticData plasticData)
	{
		if (plasticData.PlasticType == "pet")
		{
			_recycleManager.RecycleType1(plasticData);
		}
		if (plasticData.PlasticType == "hdpe")
		{
			_recycleManager.RecycleType2(plasticData);
		}
		if (plasticData.PlasticType == "pvc")
		{
			_recycleManager.RecycleType3(plasticData);
		}
	}
}

In the above example, we inject RecycleManager in to our Controller class that is responsible for recycling the plastic. The Recycle method calls the appropriate recycling program based on the plastic type supplied in the PlasticData model.

public class PlasticData
{
	public string PlasticType { get; set; }
	public decimal Weight { get; set; }
	public string Color { get; set; }
}

 

 

public interface IRecycleManager
{
	void RecycleType1(PlasticData plasticData);
	void RecycleType2(PlasticData plasticData);
	void RecycleType3(PlasticData plasticData);
}

 

 

public class RecycleManager : IRecycleManager
{
	public void RecycleType1(PlasticData plasticData)
	{
		// code here
	}

	public void RecycleType2(PlasticData plasticData)
	{
		// code here
	}

	public void RecycleType3(PlasticData plasticData)
	{
		// code here
	}
}

 

We see that Recycle method is filled with multiple conditional statements making it open to modification violating the Open/Close principle. The reason I say it is open to modification is because if we want to add recycling program to another type of plastic in future, we have to add another conditional statement and add another method to RecycleManager class. It also makes our tests less maintainable and brittle. If we can eliminate the conditional statements in the Recycle method, we have a good chance of making this code adhere to Open/Close principle. One effective way of doing this is to use Smart Enums. Read more about about Smart Enums here. Let us go ahead and add a behavior to PlasticType from the previous post as shown below.

public class PlasticType
{
	public static PlasticType PET = new PlasticType("pet", "Polyethylene Terephthalate",
													(recycleManager, plasticData) =>
													recycleManager.RecycleType1(plasticData));

	public static PlasticType HDPE = new PlasticType("hdpe", "High-density Polyethylene",
													 (recycleManager, plasticData) =>
													 recycleManager.RecycleType2(plasticData));

	public static PlasticType PVC = new PlasticType("pvc", "Polyvinyl Chloride", 
													(recycleManager, plasticData) =>
													recycleManager.RecycleType3(plasticData));

	private PlasticType(string key, string description, Action<IRecycleManager, PlasticData> recycle)
	{
		Key = key;
		Description = description;
		Recycle = recycle;
		NamedConstants.Add(key, this);
	}


	public static PlasticType GetFor(string key)
	{
		if (key == null)
		{
			return null;
		}

		PlasticType plasticType;
		NamedConstants.TryGetValue(key, out plasticType);
		return plasticType;
	}

	private static readonly Dictionary<string, PlasticType> NamedConstants = new Dictionary<string, PlasticType>();

	public string Key { get; set; }
	public string Description { get; set; }
	public Action<IRecycleManager, PlasticData> Recycle;
}

Now the plastic type also defines the recycling program that it is associated with. Now let us go ahead an modify our Recycle method in the Controller class.

public class Controller
{
	private readonly IRecycleManager _recycleManager;

	public Controller(IRecycleManager recycleManager)
	{
		_recycleManager = recycleManager;
	}

	public void Recycle(PlasticData plasticData)
	{
		PlasticType.GetFor(plasticData.PlasticType).Recycle(_recycleManager, plasticData);
	}
}

We see that the Recycle method is reduced to just one line and we got rid of all the conditional statements in the method. Now our Controller is open to extension and closed to modification. If were to add a new recycling program for another type of plastic in the future, we just have to add another method to RecycleManager class.

Written by shashankshetty

July 18, 2010 at 10:39 pm

Posted in C#, Uncategorized

Tagged with

Smart Enums

with 2 comments

Our team was introduced to Smart Enums by J.P. Boodhoo in one of his Nothin’ but .NET classes in Austin. An example of a simple Smart Enum is shown below.

public class PlasticType
{
	public static PlasticType PET = new PlasticType("pet");
	public static PlasticType HDPE = new PlasticType("hdpe");
	public static PlasticType PVC = new PlasticType("pvc");
	public static PlasticType LDPE = new PlasticType("ldpe");
	public static PlasticType PP = new PlasticType("pp");
	public static PlasticType PS = new PlasticType("ps");
	public static PlasticType Other = new PlasticType("other");

	private PlasticType(string key)
	{
		Key = key;
	}
	public string Key { get; set; }
}

PlasticType is a Smart Enum that is just a collection of static classes that can be used instead of a regular Enum in our code.

The example above describes different types of plastic  (source: Wikipedia) that are in use today. The numbers were devised by Plastic Bottle Institute of the Society of the Plastics Industry to make recycling easier (On a separate note, please recycle plastic after use. Let us make the world a better place to live for the next generation). You may ask what are PET, HDPE or PVC. To make the output more readable if the PlasticTypes were to be printed, let us add Description property as shown below.

public class PlasticType
{
	public static PlasticType PET = new PlasticType("pet", "Polyethylene Terephthalate");
	public static PlasticType HDPE = new PlasticType("hdpe", "High-density Polyethylene");
	public static PlasticType PVC = new PlasticType("pvc", "Polyvinyl Chloride");
	public static PlasticType LDPE = new PlasticType("ldpe", "Low-density Polyethylene");
	public static PlasticType PP = new PlasticType("pp", "Polypropylene");
	public static PlasticType PS = new PlasticType("ps", "Polystyrene");
	public static PlasticType Other = new PlasticType("other", "Others");

	private PlasticType(string key, string description)
	{
		Key = key;
		Description = description;
	}

	public string Key { get; set; }
	public string Description { get; set; }	
}

Smart Enum is already looking better than our regular Enum with the addition of Description property. We (myself and Clinton Sheppard) decided to take it a step further to make the usage of PlasticType easier in our code. So we added a GetFor(key) method as shown below.

public class PlasticType
{
	public static PlasticType PET = new PlasticType("pet", "Polyethylene Terephthalate");
	public static PlasticType HDPE = new PlasticType("hdpe", "High-density Polyethylene");
	public static PlasticType PVC = new PlasticType("pvc", "Polyvinyl Chloride");
	public static PlasticType LDPE = new PlasticType("ldpe", "Low-density Polyethylene");
	public static PlasticType PP = new PlasticType("pp", "Polypropylene");
	public static PlasticType PS = new PlasticType("ps", "Polystyrene");
	public static PlasticType Other = new PlasticType("other", "Others");

	private PlasticType(string key, string description)
	{
		Key = key;
		Description = description;
        NamedConstants.Add(key, this);
	}

	public static PlasticType GetFor(string key)
	{
		if (key == null)
		{
			return null;
		}

		PlasticType plasticType;
		NamedConstants.TryGetValue(key, out plasticType);
		return plasticType;
	}

	private static readonly Dictionary<string, PlasticType> NamedConstants = new Dictionary<string, PlasticType>();

	public string Key { get; set; }
	public string Description { get; set; }
}

GetFor(key) method converts a given key to the corresponding Smart Enum that can be used within our code. This limits the usage of strings only within the Smart Enum making renaming easier across the project. We have created a NamedConstant class (our name for Smart Enum) that is part of MvbaCore project that provides other helper methods like Equals, Values (enumerates over all the available PlasticTypes). Inheriting PlasticType from NamedConstant class would add all the helper methods automatically as shown below.

public class PlasticType : NamedConstant&lt;PlasticType&gt;
{
	public static PlasticType PET = new PlasticType("pet", "Polyethylene Terephthalate");
	public static PlasticType HDPE = new PlasticType("hdpe", "High-density Polyethylene");
	public static PlasticType PVC = new PlasticType("pvc", "Polyvinyl Chloride");
	public static PlasticType LDPE = new PlasticType("ldpe", "Low-density Polyethylene");
	public static PlasticType PP = new PlasticType("pp", "Polypropylene");
	public static PlasticType PS = new PlasticType("ps", "Polystyrene");
	public static PlasticType Other = new PlasticType("other", "Others");

	private PlasticType(string key, string description)
	{
		Key = key;
		Description = description;
		NamedConstants.Add(key, this);
	}

	public string Description { get; set; }
}

NamedConstant<T> makes creating Smart Enums easier, so we can focus on solving a business problem rather than building helper methods around it.

We can use Smart Enums not only to compare types like any other regular Enum but also add behavior to them making it smarter as described in this post.

You can create a Smart Enum as described above without a key or description. It depends on the problem you are trying to solve.

Written by shashankshetty

July 18, 2010 at 9:51 pm

Posted in C#, Uncategorized

Tagged with

Separation of concerns in Input Builders

with 2 comments

Note: We have moved on to use UIMaps as described in this blog post.

In our ASP.Net MVC application we want to separate the presentation code associated with HTML views from the act of binding data to HTML controls. We also want to get more of the UI control generation under test. This is our latest refinement towards those goals.

Html page for Address:

<div>
	<%= Model.Street
	.WithLabel("Street:")
	.Width("400px") %>
</div>
<div>
	<%= Model.City
	.WithLabel("City:") %>
</div>
<div>
	<%= Model.States
	.WithDefault("Select", "")
	.WithLabel("State:") %>
</div>
<div>
	<%= Model.ZipCode
	.WithLabel("Zip:")
	.Width("50px") %>-<%=
	Model.ZipPlus
	.Width("50px")%>
</div>

Here we only set css and other view related attributes. Now our HTML views are more concerned with how to display the data rather than what to display. Our model uses FluentWebControls to build the HTML inputs:

public class AddressInputProvider
{
	private readonly IRepository _repository;
	private Address _address;
	public AddressInputProvider(IRepository repository)
	{
		_repository = repository;
	}
	public void SetAddress(Address address)
	{
		_address = address;
	}
	public TextBoxData Street
	{
		get
		{
			return Fluent.TextBoxFor(_address, x => x.Street)
				.WithId((AddressModel address) => address.Street);
		}
	}
	public TextBoxData City
	{
		get
		{
			return Fluent.TextBoxFor(_address, x => x.City)
				.WithId((AddressModel address) => address.City);
		}
	}
	public DropDownListData States
	{
		get
		{
			return Fluent.DropDownListFor<State, AddressModel, string>(
				_repository.GetAll<State>(),
				state => state.Name,
				state => state.StateCode,
				x => x.State)
				.WithSelectedValue(() => _address.State);
		}
	}
	public TextBoxData ZipCode
	{
		get
		{
			return Fluent.TextBoxFor(_address, x => x.ZipCode)
				.WithId((AddressModel address) => address.ZipCode);
		}
	}

	public TextBoxData ZipPlus
	{
		get
		{
			return Fluent.TextBoxFor(_address, x => x.ZipPlus)
				.WithId((AddressModel address) => address.ZipPlus);
		}
	}
}

Now we can test the AddressInputBuilder, including the HTML control types and their properties in unit tests. We can eliminate mapping Domain objects to a Model before building the view. As FluentWebControls can bind against the model to get validation information, we only have to define the validation in one place – just in our Domain object or however we choose to do that. Other benefit is that it reduces our reliance on UI tests.

co-authored with Clinton Sheppard

Written by shashankshetty

March 5, 2010 at 4:56 pm

Posted in ASP.net MVC, C#, Uncategorized

Tagged with

Unit of Work Part 2

leave a comment »

In the previous post we started off with a brief discussion on Unit of Work and its implementation. We also implemented  ISessionContainer that is a wrapper for ISession and used it to persist changes into the database. In this post let us see if we can isolate the below piece of code that has to be repeated in all the methods that deals with repository.

try
{
	// do work
	_repository.Save(Entity);
	_sessionContainer.Commit();
}
finally
{
	_sessionContainer.Dispose();
}

Following implementation is inspired by Fubu Behaviors concept. Imagine every call from the client or web as a request and this request has to pass through a Request handler to reach our business logic. Let us create an interface IRequestHandler that would attempt to encapsulate a Request.

public interface IRequestHandler
{
  TOutput ProcessRequest<TInput1, TInput2, TOutput>(TInput1 input1, TInput2 input2, Func<TInput1, TInput2, TOutput> func)
    where TInput1 : class
    where TInput2 : class
    where TOutput : class;
}

The above interface takes in two input entities and a func that process these input entities and returns an output entity. Now let us go ahead and implement it.

public class AtomicRequestHandler : IRequestHandler
{
	private readonly ISessionContainer _sessionContainer;

	public AtomicRequestBehavior(ISessionContainer sessionContainer)
	{
		_sessionContainer = sessionContainer;
	}

	public TOutput ProcessRequest<TInput1, TInput2, TOutput>(TInput1 input1, TInput2 input2, Func<TInput1, TInput2, TOutput> func)
		where TInput1 : class
		where TInput2 : class
		where TOutput : class
	{
		try
		{
			var output = func.Invoke(input1, input2);

			_sessionContainer.Commit();

			return output;
		}
		finally
		{
			_sessionContainer.Dispose();
		}
	}
}

The name AtomicRequestHandler (name is subject to change upon a better name suggestion) means Handler for one request (imagine a web request). Initialized SessionContainer gets injected to AtomicRequestHandler.The ProcessRequest method invokes the method that has to be executed which in this case is UpdateBook. Upon completion of execution of UpdateBook method, it commits the transaction and closes the session. In case of any error anywhere in the execution, the transaction and session are closed throwing away all the unsaved changes.

Now let us re-implement the UpdateBook method with AtomicRequestHandler in mind.

public class SampleService : ISampleService
{
   private readonly IRepository _repository;

   public SampleService(IRepository repository)
   {
      _repository = repository;
   }

   public Book UpdateBook(Book book, Author author)
   {
      book.AddAuthor(author);
      book.Price =100m;
     _repository.Save(book);
     return book;
   }
}

The above illustration has no sign of SessionContainer at all. The reason we were able to separate the code so easily is because of Inversion of Control.

StructureMap is IoC of choice in my implementations, but you can choose to use your favorite IoC.  The following code shows how all this is magically constructed.

ISampleService sampleService = ObjectFactory.GetInstance<ISampleService>();
IRequestHandler atomicRequestHandler = ObjectFactory.GetInstance<IRequestHandler>();
Book result = atomicRequestHandler.ProcessRequest<Book, Author, Book>(GetBook(), GetAuthor(), sampleService.UpdateBook)

The above code calls atomicRequestHandler.ProcessRequest method with input entities – Book and Author and sampleService.UpdateBook method as a delegate that makes sure that the UpdateBook method is executed within the transaction boundary.

This is exactly how Fubu makes sure your web Request is executed within a transaction boundary. The Handle Request method in ActionHttpHandler redirects request to the action method through a behavior similar to AtomicRequestHandler.

You can implement this in ASP.net MVC by writing your own CustomHttpModule that initializes a new SessionContainer on BeginRequest and disposes it on EndRequest. You can alternatively do this in Application_BeginRequest and Application_EndRequest in Global.asax.cs file. ActionFilter is another place where you can stick in unit of work, but it is generally not recommended as you will have to do this for every single action.

If you compare them, Fubu does it the best when compared to ASP.Net Mvc, because of its architectural preference of Composition over Inheritance.

Finally, I wouldn’t have been able to write this exhaustive analysis on Unit of Work if not for multiple discussions with Chad Myers, Josh Flanagan and Weston Binford. Download the sample application on which the examples discussed above are based on.

Written by shashankshetty

October 29, 2009 at 10:33 pm

Unit of Work Part 1

with 4 comments

Quoting from Martin Fowler’s Patterns of Enterprise Application Architecture, “Unit of Work maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems”.

This post delves into the details and implementation of Unit of Work based on Martin Fowler’s explanation of Unit of Work in his book. First, we will try to understand the Unit of Work concept, then implement a Unit of Work and finally, we will see how it can be effectively used in a sample application.

An application request can be atomic (affecting single business object) or composite in nature (affecting multiple business objects). It becomes even more tricky when a database has to be updated with these changes. If you imagine a scenario where a request updates multiple business objects, then the following questions arise.

  • Do you make multiple calls to the database to save each of the objects  ?
  • You save all of them together into the database ?

The main drawback of the former approach is that your request handler has to be database aware. It has to make multiple calls to database for each and every request and if there is any error in the process, rollback the changes. Other issues are having to keep the transaction open throughout the request and maintain referential integrity when saving the objects into the database.

The latter approach keeps track of all the business objects that were changed during a request and at the end of the request all the business objects that were changed are saved into the database. This may involve opening a transaction, committing the changes and then closing the transaction. For this approach to work, it needs someone to track the objects that were changed, managing transaction and committing the changes. This is exactly what Unit of Work is intended to do.

Unit of Work keeps track of all the objects that are changed during a request, open a transaction, save the business objects in to the database and then close the transaction. In case of error, rollback all the changes. By doing this, it also accomplishes another important aspect of development – separation of concern which will be discussed in detail in part 2. Thus, the developer need not worry about persisting business objects into the database or dealing with database calls.

Before we go and implement our own Unit Of Work, let us see if there is already something out there that we can use. ISession in NHibernate represents the conversation between application and the database. ISession is just a container for Unit of Work that keeps track of objects that are changed during a request.

To leverage the Unit of Work in ISession, let us go ahead and implement ISessionContainer that wraps an ISession.

public interface ISessionContainer : IDisposable
{
	void Commit();
	ISession CurrentSession { get; }
}

public class SessionContainer : ISessionContainer
{
	private readonly ITransaction _transaction;
	private bool _isDisposed;

	public SessionContainer(ISessionFactory sessionFactory)
	{
		CurrentSession = sessionFactory.OpenSession();
		_transaction = CurrentSession.BeginTransaction();
	}

	public void Commit()
	{
		if (_isDisposed)
		{
			throw new InvalidOperationException(&quot;Could not commit as Unit of Work was not initialized&quot;);
		}
		_transaction.Commit();
	}

	public ISession CurrentSession { get; private set; }

	public void Dispose()
	{
		if (_isDisposed) return;
		_transaction.Dispose();
		CurrentSession.Dispose();
		_isDisposed = true;
	}
}

Creating a new instance of SessionContainer opens a new Session and starts a new transaction. It also has a Commit method that saves all the changes to the database and closes the transaction. Dispose method closes the transaction if not already closed and then closes the Session.

The next step is to delegate persistence management to SessionContainer. Let us imagine a situation where we want to update Book details that is still in works with the newly recruited high profile Author and update the projected price of the book. Before we proceed with the example here are the details of the Book and Author and their properties.

public class Book : DomainEntity<Book>
{
        public Book()
	{
		Authors = new List<Author>();
	}

	public virtual string ISBN { get; set; }
	public virtual string Title { get; set; }
	public virtual decimal Price { get; set; }

	public virtual IList<Author> Authors { get; private set; }
	public virtual void AddAuthor(Author author)
	{
		if (!Authors.Contains(author))
		{
			author.AddBook(this);
			Authors.Add(author);
		}
	}
}

public class Author : DomainEntity<Author>
{
	public Author()
	{
		Books = new List<Book>();
	}

	public virtual string Name { get; set; }

	public virtual IList<Book> Books { get; private set; }
	public virtual void AddBook(Book book) { ... }
}
public class Author : DomainEntity<Author>
{
public Author()
{
Books = new List<Book>();
Publishers = new List<Publisher>();
}
public virtual string Name { get; set; }
public virtual IList<Book> Books { get; private set; }
public virtual IList<Publisher> Publishers { get; private set; }
public virtual void AddBook(Book book)
{
if (Books.Contains(book))
return;
book.AddAuthor(this);
Books.Add(book);
}
public virtual void AddPublisher(Publisher publisher)
{
if (!Publishers.Contains(publisher))
{
publisher.AddAuthor(this);
Publishers.Add(publisher);
}
}
}

UpdateBook is a method (imagine an action method in a MVC Controller) that adds the new author to the Book and updates the price.

public class BookService : IService
{
    private readonly IUnitOfWork _sessionContainer;
    private readonly IRepository _repository;

    public BookService(IUnitOfWork unitOfWork, IRepository repository)
    {
        _sessionContainer = unitOfWork;
        _repository = repository;
    }

    public Book UpdateBook(Book book, Author author)
    {
        try
        {
            book.AddAuthor(author);
            book.Price = 100m;
            _repository.Save(book);
            _sessionContainer.Commit();
        }
        finally
        {
            _sessionContainer.Dispose();
        }
        return book;
    }
}

In the UpdateBook method, we add the newly recruited author and updated the price to $100.  We used the SessionContainer that we created in the previous post to commit the changes at the end of the method and dispose the transaction. If there is any error while committing the changes, a call to Dispose() method (as the control always ends up in the finally block) ensures that the transaction is disposed and in the process all the unsaved changes will be lost.

Only hiccup in the above solution is that you will have to inject ISessionContainer into all the classes that deal with repository. Furthermore, you will have to repeat the same lines of code to commit the changes and dispose the transaction object in all the methods that update the repository. This puts the onus on developer not to forget to add these lines of code in all the methods.

The next step would be to isolate this responsibility so that developer doesn’t have to deal with committing the changes and disposing the transaction.  In the next post we will implement a small console application that tackles this issue. Since Web especially MVC frameworks (ASP.net and Fubu) are so relevant today, we will also discuss how these frameworks handle this seperation of concern.

Written by shashankshetty

October 28, 2009 at 10:11 pm

More FubuMvc features

leave a comment »

In April I blogged on how to set up a simple application using FubuMvc. Today, we will look at more features that I left out in my earlier post. Thanks to Weston Binford for enumerating these changes. Please be aware that Chad Myers is planning to work on several enhancements to the FubuMvc framework including making FubuMvc controller less.

Debug: If you are wondering what is the url that invokes an action, what controllers are these actions part of, what is the method signature, what are its behaviors, how are all these wired up etc, you can find out all the details just by appending __debug to your root url. Please note that it works only on your root directory. For example url for FubuMvcSampleApplcation that is running on cassini web server is http://localhost:2052/__debug that results in the following output.

debug

You can find more details on the Debug feature in this post that was posted on the FubuMVC Development Group.

404 or Page Not Found: To configure a 404 error page we will have to wire up the 404 behavior in our ControllerConfiguration.Configure() method.

x.ActionConventions(convention =&amp;gt;
{
   convention.Add<wire_up_404_handler_URL>();
});

Now we can add a PageNotFoundController with an Index action that takes in a PageNotFoundViewModel and returns the same model back as follows:

public class PageNotFoundController
{
  public PageNotFoundViewModel Index(PageNotFoundViewModel pageNotFoundViewModel)
  {
     return new PageNotFoundViewModel
       {
          Description = "Requested Url not found"
       };
  }
}

public class PageNotFoundViewModel : ViewModel
{
  public string Description { get; set; }
}

It is now time to add a PageNotFound View that displays the description that we populated in our controller.
PageNotFoundView

<asp:Content ID="IndexUser" ContentPlaceHolderID="MainContent" runat="server">
 <%= Model.Description %>. Please check your url.
</asp:Content>

public class PageNotFoundView : FubuMvcSampleApplicationPage&amp;lt;PageNotFoundViewModel&amp;gt;
{
}

Other Url: If you want to call your action with a different url other than the standard url ({controllername}/{actioname}), you can easily override the default behavior for that action in your ControllerConfiguration.Configure() method as shown below:

x.OverrideConfigFor<UserController>(controller => controller.Index(null),
 configuration => configuration.AddOtherUrl("user/List.aspx"));

Now we can reach our Index page with an alternate url user/List.aspx. I have updated the FubuMvcSampleApplication with all the changes discussed in this post that can be downloaded here.

Written by shashankshetty

August 1, 2009 at 7:02 pm

Posted in C#, Fubu Mvc, FubuMvc, Uncategorized

Tagged with , ,

Setting up FubuMVC application on IIS7

leave a comment »

Recently my colleague Weston Binford was trying to set up a FubuMvc application to do a comparison analysis with Asp.net Mvc. He had some issues with running FubuMvcSampleApplication FubuMvc under IIS7. After much debugging he found out that UrlRoutingModule and UrlRoutingHandler must be added under system.webServer tag.

<system.webServer>
 <modules>
 <remove name="UrlRoutingModule" />
 <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
 </modules>
 <handlers>
 <remove name="UrlRoutingHandler" />
 <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
 </handlers>
</system.webServer>

Written by shashankshetty

July 29, 2009 at 10:32 am

Posted in C#, Fubu Mvc, FubuMvc, Uncategorized

Tagged with , ,

Now you can insert records into Excel using ExcelMapper

leave a comment »

You can now use ExcelMapper to insert records into Excel as well. Continuing with the same User example, we can insert a User (John Doe) into Excel using ExcelMapper.

ExcelMapper.SetUp();
IRepository repository = ServiceLocator.Current.GetInstance<IRepository>();

List<User> users = new List<User>
{
   new User
   {
       Id = 1,
       LastName = "Doe",
       FirstName = "John
       DateOfBirth  = Convert.ToDateTime("2/2/1990")
   }
};
repository.Put<User>(users);

Note that User DTO was generated using BuildDTOsFromExcel.exe.

repository.Put<User>(User) saves the Users List into Excel. Since we don’t have the concept of unique keys yet, it can only insert and not update.

Written by shashankshetty

July 27, 2009 at 10:11 am

Posted in C#, ExcelMapper, Microsoft Excel

Tagged with , , ,

Follow

Get every new post delivered to your Inbox.