Membrane - CRUD Controller

John | .Net, IT, Membrane, MonoRail | Saturday, April 11th, 2009

I’ve banged on about Membrane having a CRUD Controller and Service quite a few times now. I suppose it’s time to explain this a little more. Especially as we now have some basic Membrane functionality running directly off them. (I’ll talk about the CRUDService in a later post, as most plugin controllers will not have to deal with it).

The plan

Since first thinking about Membrane what I wanted was a flexible tool that would help developers to create a content managed website with minimal effort, whilst at the same time maintaining certain coding standards.

As mentioned in a previous post, myself and Andy Pike have worked on a plugin architecture. What this allows is for developers to write controllers, services, DTOs, entities, mappers, queries and views that can be dropped into a “plugin” directory and Membrane will be able to use them without the need for recompiling. The purpose of the CRUDController and CRUDService is to make the creation of these plugins very simple.

The CRUDController

The controller relies on the following interface

public interface ICRUDController<DTO, Entity>
{
	void List();
	void List(int currentPage, int pageSize);
	void New();
	void Edit(Guid id);
	void Submit(DTO item);
	void ConfirmDelete(Guid id);
	void Delete(Guid id);
	void LoadSupportiveData();
}

Each of these actions is completely override-able so developers can make each action do exactly as they need. In most cases the default behavior should do what is needed. Of course developers can even write completely new actions as well if they need them.

The only method that is probably worth a little explanation is the LoadSupportiveData. It is used to load related data. For example if we have two entities Products and Accessories, when editing Products the controller will need to know about the Accessories data for <select>s etc in the editing form. We will be looking to develop this functionality to automatically load the related data.

Adding a new controller

To show how simple it is to create a new editor plugin see the example below for editing Navigation Types.

public class NavigationTypesController : CRUDController<NavigationTypeDTO, NavigationType>
{
	public NavigationTypesController(ICRUDService<NavigationTypeDTO, NavigationType> service, IAutoGenerator<NavigationTypeDTO> autoGenerator) : base(service, autoGenerator)
	{
	}
}

So other than creating the NavigationTypeDTO and the NavigationType entity that’s it. As we only need the default CRUDService functionality we don’t even need to write a new service for the navigation type work.

The CRUDController uses shared view code and so in most cases these views can be used for all of the editors. Again if required the views can be overwritten. The New and Edit views use a automatic form creation viewcomponent and service that generates the necessary fields. This will be the subject of another post.

Unit Testing

Writing unit tests for new controllers inheriting from the CRUDController is incredibly simple, as we have the CRUDControllerFixture. As with the CRUDController each of the tests are completely overridable and new tests can be added as well.

Going back to the Navigation Type controller as mentioned above, to have series of controller unit tests we will inherit from the CRUDControllerFixture and just do a simple setup

public class NavigationTypesControllerFixture : CRUDControllerFixture<NavigationTypeDTO, NavigationType>
{
	/// <summary>
	/// Overriding the base SetUp to set up the relevant TDto objects
	/// </summary>
	public override void SetUp()
	{
		base.SetUp();
		NewDTO = new NavigationTypeDTO { Name = "Primary Navigation" };
		EditDTO = new NavigationTypeDTO { Id = Guid.NewGuid(), Name = "Secondary Navigation" };
		InvalidDTO = new NavigationTypeDTO { Id = Guid.NewGuid() };
		DeleteDTO = new NavigationTypeDTO { Id = Guid.NewGuid(), Name = "Tertiary Navigation" };
 
		Controller = new NavigationTypesController(Service, AutoGenerator);
 
		PrepareController(Controller);
 
	}
}

Again, that’s all there is to it. The trick is just setting up the relevant DTOs and preparing the controller.

Acceptance Testing

We are currently working on a series of CRUD acceptance tests using WatiN, so that the acceptance testing side of things will be just as simple.

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress | Theme by Roy Tanck