Friday, December 17, 2010

Rewriting WebForms to MVC

This week we finally started to port our project from ASP.NET WebForms to ASP.NET MVC. We made this decision, because we were so sick of the grief the Infragistics Grid control was causing us. Not only does it output horrific html. Our dynamic data structure also causes us way too much grief with the grid.

The main problem with Infragistics is that the product is so mature that there are half a dozen ways to do any particular thing. Since the documentation is so scant and the community so poor, it's hard to figure out how to actually accomplish what it is you're trying to do. A lot of the time it just feels like you're working inside a glove box and glove box has been spray painted black.


There really doesn't seem to be a method to solve a particular issue, just a lot of fiddling. Setting a property to this, handle this event, call this method on the column, etc. So this frustration has finally boiled over and we've begun rewriting the app to pull out Infragistics and at the same time move our app to MVC.

I was dreading doing the port. However, so far it has been quite easy. Fortunately for us, when we designed our application, we designed with our own MVC style pattern that sat on top of WebForms. Similar to what they've done over at WebFroms MVP So the code behind was only used for handling the UI. All of the complex business logic was passed on to Controllers. So for the most part it has been a fair amount of copy and paste. We haven't gotten to the grid portion so I may be paying for this early optimism yet, but I have been pleasantly surprised with our progress so far.

Addendum
We had to keep around a couple of server controls that were reports. So we had to find a way to render WebForms as part of an MVC action. Here's how we did it.

Thursday, July 8, 2010

Awesome jQuery date time picker

Recently came across this great jQuery date/time picker. Most pickers out there are strictly date pickers, but this one does both and quite elegantly in my opinion. Check it out.

http://www.ama3.com/anytime/

Friday, May 14, 2010

NInject, NHibernate, and unit testing

I recently came across an interesting problem in my tests. In the application I am working on, I have recently created a framework for generating tag numbers for pieces of equipment. I put unit tests around the code and decided that the system was complex enough to warrant some integration tests.

The set up for the integration tests is quite complex as I have to not only set up an NHibernate session, but also the Ninject kernel. In my app the way I bind the NHibernate session is through the following line:

Bind<ISession>().ToMethod(c => NHibernateSessionFactory.Instance.OpenSession()).InRequestScope();

In my integration test SetUp I create a session for the test to use and start a transaction. In the TearDown I rollback the transaction and dispose the session. So I needed to manually change the binding to ISession in Ninject. I did that using the following code

foreach (var binding in _kernel.GetBindings(typeof (ISession)))
{
 _kernel.RemoveBinding(binding);
}
_kernel.Bind<ISession>().ToMethod(c => _session).InRequestScope();

(I would love if anyone suggested a better way to do this)

The integration test was working fine. Until I started working on another completely unrelated module for doing auditing on certain changes to domain objects. Once the module was finished I ran the entire build again and the integration tests started failing with a message that the ISession object was closed. If they were run independently or even as part of an entire integration tests run, they passed. I finally figured out that they would only fail, when they were being run together with the tests for this new module.

The culprit turned out to be this line of code I was running in the TestFixtureSetUp for the auditing tests:

HttpContext.Current = new HttpContext(new HttpRequest(string.Empty, "http://domain.com", string.Empty), new HttpResponse(new StringWriter()));

Since the HttpContext.Current was staying the same, the integration tests were only ever providing one ISession instance for all of the tagging integration tests. So once the first test ran and disposed of the session, any other components that required an ISession were still getting the old disposed instance of the ISession. The fix was simple, I just had to set HttpContext.Current back to null in the TestFixtureTearDown for the audit module test.