Building a widget system in ASP.NET MVC Part 2

Posted by ben 13. April 2011 23:11

In my previous post I built out a widget system using ASP.NET MVC.

In this post I am going to cover how we can extend the widget system to support complex widgets that perform their own data binding using external services.

In this example I am going to create a widget that displays a specific project in our portfolio application. We will want to store the Id of the project to display in our widget properties but we also need a way of loading the project itself from our project service.

To do this I defined a new interface that a widget can implement:

    public interface IWidgetWithDisplayModel {
        dynamic DisplayModel { get; set; }
        void CreateDisplayModel();
    }

This works a bit like the EditViewModel in that we have a specific view model for display purposes.

The CreateDisplayModel method is what we will call in our controller to initialize the model.

The ProjectWidget can be seen below:

    public class ProjectWidget : Widget, IWidgetWithDisplayModel
    {
        public override string WidgetName
        {
            get { return "ProjectWidget"; }
        }

        public override string WidgetDescription
        {
            get { return "Displays a specific project."; }
        }

        public override dynamic EditViewModel
        {
            get
            {
                var vm = this.CreateEditViewModel<EditProjectWidgetViewModel>();
                vm.ProjectSlug = this.GetProperty<string>("projectslug");
                return vm;
            }
        }

        public override void UpdateFromViewModel(dynamic viewModel) {
            EditProjectWidgetViewModel vm = this.ValidateViewModel<EditProjectWidgetViewModel>(viewModel);

            this.Title = vm.Title;
            this.SystemName = vm.SystemName;

            this.SetProperty("projectslug", vm.ProjectSlug); // TODO - use reflection to set these automatically
        }

        #region IWidgetWithDisplayModel Members

        public IProjectService ProjectService { get; set; }
        
        public dynamic DisplayModel { get; set; }

        public void CreateDisplayModel()
        {
            var project = this.ProjectService.GetProjectBySlug(this.GetProperty("projectslug"));

            if (project == null)
                return;

            var model = new ProjectWidgetViewModel
            {
                Id = project.Id,
                Title = project.Title,
                Slug = project.Slug,
                ShortDescription = project.ShortDescription,
                Category = project.Category.Name,
                Tags = string.Join(", ", this.ProjectService.GetProjectTags(project.Id).Select(t=> t.Name)) // TODO refactor into service method
            };


            var defaultImage = this.ProjectService.GetProjectImages(project.Id).FirstOrDefault();
            if (defaultImage != null)
                model.ImageId = defaultImage.ImageId;

            this.DisplayModel = model;
        }

        #endregion
    }

    public class EditProjectWidgetViewModel : EditWidgetViewModel {
        [Required(ErrorMessage = "The project slug is required")]
        [Display(Name = "Project Slug", Description = "The slug of the project you wish to display")]
        public string ProjectSlug { get; set; }
    }

    public class ProjectWidgetViewModel
    {
        public Guid Id {get;set;}
        public string Title { get; set; }
        public string Slug { get; set; }
        public string ShortDescription { get; set; }
        public string Category { get; set; }
        public string Tags { get; set; }

        public Guid? ImageId { get; set; }
        public string VideoUrl { get; set; }

        public bool HasVideo
        {
            get
            {
                return !string.IsNullOrEmpty(this.VideoUrl);
            }
        }
    }

For details on the overall architecture of the Widget system please see the previous post. The points of interest are the ProjectWidgetViewModel (at the very bottom of the snippet) and the CreateDisplayModel method.

In this method we retrieve the project from our project service using the project id (or slug) stored in widget properties. Then we map the project to our model and set the DisplayModel property accordingly.

A key point is how we got a reference to our project service. This was actually injected for us using StructureMap. The bit of magic is in our WidgetService. When we retrieve a widget to be displayed, we check if it implements IWidgetWithDisplayModel and if so, call ObjectFactory.BuildUp on our widget to fulfil any dependencies using setter injection:

	public Widget GetWidgetBySystemName(string systemName, bool buildDisplayModel = false) {
		var widget = widgetRepo.GetAll().SingleOrDefault(w => w.SystemName == systemName.ToLower());

		if (widget != null && widget is IWidgetWithDisplayModel) {
			ObjectFactory.BuildUp(widget);
		}

		return widget;
	}

If we look at the action method on our widget controller again, you will see how we call CreateViewModel prior to returning the widget view:

	[HttpGet]
	public ActionResult Get(string name)
	{
		var widget = widgetService.GetWidgetBySystemName(name, true);
		
		if (widget == null)
			return Content(string.Format("Widget [{0}] not found!", name));
		
		if (!this.ViewExists(widget.WidgetName))
			return Content(string.Format("A template for widget [{0}] was not found.", widget.WidgetName));
			
		if (widget is IWidgetWithDisplayModel) {
			(widget as IWidgetWithDisplayModel).CreateDisplayModel();
		}

		return PartialView(widget.WidgetName, widget);
	}

The markup for our view is as follows:

@{
    var project = Model.DisplayModel as PlanetCloud.Portfolio.Widgets.Widgets.ProjectWidgetViewModel;
}

@if (project != null)
{
    <div class="project-widget lazy-wrap">
        @if (project.HasVideo)
        {
            <div class="project-video">
                @Portfolio.OEmbed(project.VideoUrl)
            </div>  
        }
        else
        { 
            <div class="overlay">
                <div class="overlay-content">
                    <h3>
                        <a class="link" href="@Url.Action("Project", "Project", new { id = project.Slug })" title="@project.Title">
                            @project.Title
                        </a>
                    </h3>
                    <p class="project-category">@project.Category</p>
                    <span class="tags">
                        @project.Tags
                    </span>
                </div>
            </div>
            <div class="project-image">
                <a href="@Url.Action("Project", "Project", new { id = project.Slug })">
                    @Portfolio.Image(project.ImageId, 565, new { @class = "lazy" })
                </a>           
            </div>
        }      
    </div>
}

At the top of the view we are casting the dynamic DisplayModel property as a strongly typed ProjectViewModel object. We can do this because it’s a known type although there is nothing stopping you from just working with the dynamic model directly.

Here’s an example of this widget in action on the Us site:

image

Tags: ,
Categories ASP.NET | C# | Development | Entity Framework | StructureMap

Building a widget system in ASP.NET MVC

Posted by ben 13. April 2011 21:50

One area that I think ASP.NET Web Forms makes easier, is the ability to create self contained user interface components that contain all the logic necessary to load data, perform any required processing and produce an output.

ASP.NET MVC provides a greater separation of concerns resulting in applications that are easier to manage and test. So when it comes to creating a widget system we have to take a different perspective. Of course we could just load the data for our widget inline within our views, but then this would violate MVC principles that our controller is responsible for passing the Model to the View.

One feature of ASP.NET MVC that makes creating widget style interfaces possible is the RenderAction method. This allows us to call an action on a controller and render the response of that action within an existing page. However, in order to make our widget system dynamic, I don’t want to have to create a separate controller, routes etc. for every widget. The same applies to configuration. It would be better if we could have a generic configuration interface for all widgets.

So some high level requirements are:

  • Provide a single endpoint (controller action) for displaying widgets
  • Provide a generic way of configuring widgets
  • Find a way of creating complex widgets that can load their own data without violating MVC principles
  • Allow widgets to be dropped into our app as assemblies without requiring an additional configuration.

There are a few framework features and tool that I will be using to create the widget system:

  • As previously mentioned, RenderAction to display the plugin
  • Dynamic view models
  • MVC’s EditorFor template helper for widget configuration
  • Entity Framework Code First (although I’m likely going to switch to NH for reasons I will explain).
  • StructureMap to provide the “pluggable” aspects of the application and inject dependencies into our widgets.

The first thing I want to do is create an interface that each widget must implement. This defines some of the behaviours of a widget:

    public interface IWidget {
        string WidgetName { get; }
        string WidgetDescription { get; }
        string Title { get; set; }
        string SystemName { get; set; }
        ICollection<WidgetProperty> Properties { get; set; }

        // view models
        dynamic EditViewModel { get; }
        void UpdateFromViewModel(dynamic viewModel);
    }

Some of the properties/methods require an explanation:

Properties: Most widgets instances are going to need to store information that will be used directly within the widget View (e.g. displaying some html content) or perhaps used to configure the widget (e.g. twitter user id for a twitter widget). Since we want to be able to add new widgets without changing our database, we need to create a simple key value pair store for such properties. We will use EF to wire up this association.

EditViewModel: This allows us to create a model containing all the properties we wish to be able to set for our widget instance, along with any validation rules. We can then make use of ASP.NET MVC’s EditorFor template helper and dynamic views to create a configuration interface that works for all widgets.

UpdateFromViewModel: Since each widget’s edit view model is likely to be different it makes sense to let the widget handle the updating of it’s properties from the view model. Once done, we can pass the updated widget instance to our repository so that all the changes are persisted.

The widget property class can be seen below:

    public class WidgetProperty : Entity {
        public string PropertyKey { get; set; }
        public string PropertyValue { get; set; }

        public Widget Widget { get; set; }

        public WidgetProperty() { }

        public WidgetProperty(string key, string value) {
            this.PropertyKey = key;
            this.PropertyValue = value;
        }
    }

Since the Entity Framework does not support mapping to interfaces (like NH) we have created an abstract Widget class that all widgets will inherit from. We will be using Table-Per-Hierarchy mapping (TBH) to map instances of this class to a Widgets table in our database. All custom widget properties will be stored inside the WidgetProperties table.

image

It is the TPH mapping that will allow us to add new widget types without requiring any database changes since EF will automatically add the top level widget properties to the existing Widget table along with a type discriminator.

I mentioned above that I will be moving away from EF to NHibernate. One of the reasons is the way in which EF auto maps properties. If I create a Twitter Widget with a writable property “UserId” and try and save this widget, EF will expect to persist this to a TwitterWidget table. The only way around this would be to explicitly configure a mapping for the custom widget that tells EF to ignore the properties which violates my “drop in” design goal.

Whilst we can use read-only properties within our widgets, I’m generally not a fan of auto-anything where I don’t have any control.

Anyway, our base widget class is as follows:

    public abstract class Widget : Entity, IWidget {

        public Widget() { }
        
        public abstract string WidgetName { get; }
        public abstract string WidgetDescription { get; }

        public virtual string Title { get; set; }
        public virtual string SystemName { get; set; }
        public virtual ICollection<WidgetProperty> Properties { get; set; }

        // viewmodels

        public abstract dynamic EditViewModel { get; }
        public abstract void UpdateFromViewModel(dynamic viewModel);

        public virtual WidgetProperty FindProperty(string key) {
            return this.Properties.SingleOrDefault(p => p.PropertyKey == key.ToLowerInvariant());
        }

        public virtual void SetProperty(string key, object value) {
            key = key.ToLowerInvariant();
            var property = this.FindProperty(key);

            if (property != null)
                property.PropertyValue = value.ToString();
            else
                property = new WidgetProperty(key, value.ToString());
                this.Properties.Add(property);
        }

        public virtual T GetProperty<T>(string key, T defaultValue = default(T)) {
            var result = defaultValue;
            var property = FindProperty(key);
            if (property != null)
                result = CommonUtils.To<T>(property.PropertyValue);

            return result;
        }

        public virtual string GetProperty(string key) {
            return GetProperty<string>(key);
        }

        public T ValidateViewModel<T>(object viewModel) where T : class {
            if (viewModel == null)
                throw new ArgumentNullException("viewModel");

            var vm = viewModel as T;
            
            if (vm == null)
                throw new ArgumentException(string.Format("The viewModel object could not be cast as {0}.", typeof(T).Name));

            return vm;
        }

        public TViewModel CreateEditViewModel<TViewModel>() where TViewModel : EditWidgetViewModel, new() {
            var model = new TViewModel {
                Id = this.Id,
                Title = this.Title,
                SystemName = this.SystemName
            };

            return model as TViewModel;
        }
    }

Aside from the properties you have already seen on the IWidget interface, there are also a number of convenience methods that handle getting and setting custom widget properties and validating the edit view model.

The final method CreateEditViewModel just updates the common widget properties found on all Widget edit view models.

Our EditWidgetViewModel class is as follows:

    public class EditWidgetViewModel : IEditWidgetViewModel {
        [HiddenInput(DisplayValue=false)]
        public Guid Id { get; set; }

        [Required(ErrorMessage = "The System name is required")]
        [Display(Name = "System Name", Order = 1)]
        public string SystemName { get; set; }
        
        [Required]
        [Display(Order = 2)]
        public string Title { get; set; }
    }

I’ve listed the entity framework mapping for Widget below. Pretty standard stuff:

    public class WidgetMap : EntityTypeConfiguration<Widget> {
        
        public WidgetMap() {
            ToTable("Widgets");
            HasKey(w => w.Id);
            Property(w => w.SystemName).IsRequired();
            Property(w => w.Title).IsRequired();
            HasMany(w => w.Properties).WithRequired(wp => wp.Widget).WillCascadeOnDelete();
        }
    }

    public class WidgetPropertyMap : EntityTypeConfiguration<WidgetProperty> {
        public WidgetPropertyMap() {
            ToTable("WidgetProperties");
            HasKey(wp => wp.Id);
            Property(wp => wp.PropertyKey).IsRequired();
            Property(wp => wp.PropertyValue).IsMaxLength();
            HasRequired(wp => wp.Widget).WithMany(w => w.Properties);
        }
    }

So let’s go ahead and create a custom widget. This one will be a simple content widget used for displaying HTML on our page:

    public class ContentWidget : Widget
    {
        public override string WidgetName {
            get { return "ContentWidget"; }
        }

        public override string WidgetDescription {
            get { return "A widget for displaying HTML content"; }
        }

        public override dynamic EditViewModel {
            get {
                var viewModel = this.CreateEditViewModel<EditContentWidgetViewModel>();
                viewModel.Content = this.GetProperty("content");
                return viewModel;
            }
        }

        public override void UpdateFromViewModel(dynamic viewModel) {
            EditContentWidgetViewModel vm = this.ValidateViewModel<EditContentWidgetViewModel>(viewModel);
            this.Title = vm.Title;
            this.SystemName = vm.SystemName;
            this.SetProperty("content", vm.Content);
        }

        // used within our view
        public string Content { get { return this.GetProperty("content");} }
    }

    public class EditContentWidgetViewModel : EditWidgetViewModel {
        [AllowHtml]
        [DataType(DataType.MultilineText)]
        [UIHint("Editor")]
        public string Content { get; set; }
    }

Note that we have a readonly property for “Content”. This is just a convenience property for use by our view. We could also just use Model.GetProperty(“content”).

We have also defined an edit view model for our widget that sets up the validation and a UIHint for the Content property. We are using the UIHint to render a custom editor template (uses CKEditor).

Registering widgets

Now that we have created the widget we can use StructureMap’s assembly scanning features to locate and register all our IWidget instances:

	Scan(scan => {
		scan.AddAllTypesOf<IWidget>();
		scan.AssemblyContainingType<Widget>();
	});

Now to get a list of all registered IWidget types, I can just have a dependency on IEnumerable<IWidget> and StructureMap will inject a list of Widgets. Simple.

Creating a Widget Instance

To keep things simple I thought I would use the same Create view model for all widgets. This only contains the properties common to all widgets. Once the widget is saved, we can edit the widget and use it’s specific edit view model.

    public class CreateWidgetViewModel : ViewDataBase {
        [Required]
        public string Title { get; set; }

        [Required(ErrorMessage = "The System Name is required")]
        [Display(Name = "System Name")]
        public string SystemName { get; set; }

        [Required]
        [Display(Name = "Widget Type")]
        public string WidgetType { get; set; }

        public SelectList WidgetTypes { get; set; }
    }

The CreateWidgetViewModel has a select list property that allows the user to choose the type of widget instance they want to create.

The controller actions for both GET and POST methods can be seen below:

	[HttpGet]
	public ActionResult Create() {
		var widgetTypes = from wt in widgetService.WidgetTypes
						  select new
						  {
							  Name = wt.WidgetName,
							  WidgetType = wt.GetType().AssemblyQualifiedName
						  };

		var viewModel = new CreateWidgetViewModel {
			WidgetTypes = new SelectList(widgetTypes, "WidgetType", "Name")
		};

		return View(viewModel);
	}

	[HttpPost]
	public ActionResult Create(CreateWidgetViewModel viewModel) {
		if (ModelState.IsValid)
		{
			var widgetType = Type.GetType(viewModel.WidgetType);
			var widget = Activator.CreateInstance(widgetType) as Widget;
			
			if (widget != null) {
				widget.Title = viewModel.Title;
				widget.SystemName = viewModel.SystemName;
				
				widgetService.SaveWidget(widget);

				this.NotifyInfo("Widget saved successfully.");
				return RedirectToAction("Index");
			}
		}

		return View();
	}

On our GET action we retrieve a list of registered IWidgets (see note above about Registering Widgets) and load our select list with the widget name and fully qualified assembly name.

On the POST method we use a bit of reflection to create an instance of the selected widget type, then save the widget.

image

image

Editing a Widget

Now that we have created the widget we can click Edit and edit our ContetWidget specific properties. This uses the EditViewModel that we defined on our ContentWidget.

Our View is surprisingly simple:

@{
    ViewBag.CurrentPage = "widgets";
}

<h2>@ViewBag.Title</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        @Html.EditorFor(model => model)

        <input type="submit" value="Save" />

    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

We are not strongly typing the view so it will use a dynamic viewmodel. The EditorFor template helper will then do it’s best to create an Edit form for the provided Model object.

Our GET and POST controller actions are below:

	[HttpGet]
	public ActionResult Edit(Guid id)
	{
		var widget = widgetService.GetWidgetById(id);
		if (widget != null) {
			ViewBag.Title = "Edit Widget: " + widget.Title;
			return View(widget.EditViewModel);
		}

		return RedirectToAction("Index");
	}

	[HttpPost]
	[ValidateInput(false)]
	public ActionResult Edit(Guid id, FormCollection formCollection)
	{
		if (ModelState.IsValid)
		{
			var widget = widgetService.GetWidgetById(id);

			if (widget != null) {
				var viewModel = widget.EditViewModel;
				this.UpdateModel(viewModel);
				widget.UpdateFromViewModel(viewModel); 
				widgetService.SaveWidget(widget);

				NotifyInfo("Widget saved successfully.");
			}

			return RedirectToAction("Index");
		}

		return View();
	}

In our GET action we retrieve the Widget instance from our database and return our View passing the widget’s EditViewModel.

The POST action is a little more interesting. We retrieve our Widget instance and use ASP.NET MVC’s UpdateModel helper to automatically update the Widget’s EditViewModel based on the posted FormColleciton. With the EditViewModel updated we call widget.UpdateFromViewModel before persisting all the changes to our database (widgetService.SaveWidget).

image

Displaying a widget

With our widget instance saved, we now need to display it.

We have a single controller action that is used to display all widgets. This is then called using the RenderAction method (which I’ve wrapped into a little helper method):

	[HttpGet]
	public ActionResult Get(string name)
	{
		var widget = widgetService.GetWidgetBySystemName(name, true);
		
		if (widget == null)
			return Content(string.Format("Widget [{0}] not found!", name));
		
		if (!this.ViewExists(widget.WidgetName))
			return Content(string.Format("A template for widget [{0}] was not found.", widget.WidgetName));
			
		if (widget is IWidgetWithDisplayModel) {
			(widget as IWidgetWithDisplayModel).CreateDisplayModel();
		}

		return PartialView(widget.WidgetName, widget);
	}

Ignore the IWidgetWithDisplayModel for now, I’ll cover this on the next post (as this one is getting a bit long).

This action returns a view with the same name as the widget’s WidgetName property, in our case ContentWidget. All our widget views have a dynamic Model:

<div class="content-widget">
    <h3>@Model.Title</h3>
    @Html.Raw(Model.Content)
</div>

Finally the thing that brings it all together our HTML helper for displaying widgets:

	public MvcHtmlString Widget(string systemName) {
		return html.Action("Get", "Widget", new { name = systemName });
	}
	
	// usage
	
	@Portfolio.Widget("about")
	

And result:

image

Note the second widget “Clients” that has not yet been added.

In the next post I will cover how to create complex widgets that retrieve data from external services.

Before I get asked whether the source code available for download, the answer is unfortunately not. This was part of a much bigger commercial application so I have done my best to give you all the pieces of the Widget System so that you can build your own.

Tags: , ,
Categories ASP.NET | C# | StructureMap | Entity Framework | Development

EF Code First Common Practices

Posted by ben 13. April 2011 08:56

This post covers some common practices for working with Entity Framework Code First (or EF 4.1 as was just released today).

Session Per Request

With Session-Per-Request our entity framework DbContext implementation is shared across a http request. This is a fairly standard approach when working with ORMs (we do something similar with NHibernate’s ISession).

The first thing we did was to make our DbContext a dependency within our repositories. We could then use our IoC container to inject the context and scope it accordingly (per http request). However, this gave us some unwanted coupling between our repository classes and Entity Framework so we decided to abstract DbContext into a simple context, as seen below:

    public interface IDbContext {
        IDbSet<TEntity> Set<TEntity>() where TEntity : class;
        int SaveChanges();
    }

Strictly speaking there is still some coupling since IDbSet<T> is part of System.Data.Entity but overall this interface makes things more testable.

Our application context, then implements this interface, in addition to inheriting from the Entity Framework DbContext:

    public class PortfolioContext : DbContext, IDbContext
    {
        public PortfolioContext(string connectionStringName) : base(connectionStringName) {}
        
        public IDbSet<Project> Projects { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            modelBuilder.Configurations.Add(new ProjectMap());
            base.OnModelCreating(modelBuilder);
        }

        public string CreateDatabaseScript() {
            return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
        }

        public new IDbSet<TEntity> Set<TEntity>() where TEntity : class {
            return base.Set<TEntity>();
        }
    }

I can then inject IDbContext into my repositories instead of my concrete DbContext. The code below shows the StructureMap configuration to handle session per request:

For<IDbContext>().HttpContextScoped()
	.Use(ctx => new PortfolioContext("Portfolio"));

Specifying the connection provider using your connection string

If you’ve installed the SQL Compact Edition Code First NuGet package it will add some pre app start code that sets the default connection factory to the SQL CE 4.0 provider.

In my experience this is not necessary and you can change the provider just by specifying it in your connection string; for example:

    <add name="Portfolio" connectionString="Data Source=|DataDirectory|Portfolio.sdf" providerName="System.Data.SqlServerCe.4.0" />
    <add name="Portfolio" connectionString="Data Source=(local)\sqlexpress;user id=sa;password=xxxxx;Database=portfolio" providerName="System.Data.SqlClient" />

Generic Repositories

People have mixed views about generic repositories. I find that they can save a lot of code duplication. They are only really of value due to the IQueryable collections (and delayed execution) that EF provides (just like we get with NH Linq).

We typically have a service layer that will consume the generic repositories and construct more specific queries e.g GetRecentPosts.

These services will have a dependency on IRepository<T> that is located in a common assembly (we actually use the same interface when working with NHibernate):

    public interface IRepository<T> where T : class
    {
        void DeleteOnSubmit(T entity);
        IQueryable<T> GetAll();
        T GetById(object id);
        void SaveOrUpdate(T entity);
    }

Our EF repository implementation can be seen below:

    public class EFRepository<T> : IRepository<T> where T : class, IEntity
    {
        protected readonly IDbContext context;
        protected readonly IDbSet<T> entities;

        public EFRepository(IDbContext context) {
            this.context = context;
            entities = context.Set<T>();
        }

        public virtual T GetById(object id) {
            return entities.Find(id);
        }

        public virtual IQueryable<T> GetAll() {
            return entities;
        }

        public virtual void SaveOrUpdate(T entity) {
            if (entities.Find(entity.Id) == null) {
                entities.Add(entity);
            }

            context.SaveChanges();
        }

        public virtual void DeleteOnSubmit(T entity) {
            entities.Remove(entity);

            context.SaveChanges();
        }
    }

Notice the generic constraint that our class must implement IEntity. This is just a simple interface that defines an Id property:

    public interface IEntity
    {
        Guid Id { get; set; }
    }

Since StructureMap supports generic types, we can now register our generic interface like so:

For(typeof(IRepository<>)).Use(typeof(EFRepository<>));

Occasionally the generic repository didn’t meet all our requirements. We had a number of cases where we needed to eagerly load associations. Fortunately, since the EFRepository methods are virtual we can just create a new implementation and override the necessary methods:

    public class ProjectRepository : EFRepository<Project> {

        public ProjectRepository(IDbContext context) 
            : base(context) { }
        
        public override Project GetById(object id) {
            var project = entities
                .Include(p => p.Template)
                .Include(p => p.Category)
                .SingleOrDefault(p => p.Id == (Guid)id);
            return project;
        }
    }

Now to use this implementation instead of the default, we just update our StructureMap configuration:

For<IRepository<Project>>().Use<ProjectRepository>();

Seeding the Database

Below is the database initializer that we use to create our database (if it doesn’t already exist).

The initializer accepts a boolean parameter that determines whether or not to create sample data (a setting from web.config):

    public class PortfolioDatabaseInitializer : IDatabaseInitializer<PortfolioContext>
    {
        private readonly bool createSampleData;
        
        public PortfolioDatabaseInitializer(bool createSampleData = false) {
            this.createSampleData = createSampleData;
        }
        
        public void InitializeDatabase(PortfolioContext context)
        {
            if (context.Database.Exists()) return;
            
            context.Database.Delete();
            context.Database.Create();

            // Add seed data
            Seed(context);
        }

        protected void Seed(PortfolioContext context)
        {
            context.ApplyTo(
                SetupData.InsertDefaultUser
            );

            if (createSampleData) {
                context.ApplyTo(
                    TestData.InsertTestImages,
                    TestData.InsertCategories,
                    TestData.InsertProjects,
                    TestData.InsertBlogPosts
                );
            }

            context.SaveChanges();
        }
    }

The context.ApplyTo method is a handy functional extension method, courtesy of Mike Hadlow:

public static void ApplyTo(this T arg, params Action[] actions) {
            Array.ForEach(actions, action => action(arg));
        }

This will apply the context to the specified methods, for example:

	public static void InsertCategories(IDbContext context)
	{
		category1 = new Category { Name = "Test Category 1", Slug = "test-category-1" };
		category2 = new Category { Name = "Test Category 2", Slug = "test-category-2" };

		context.AddRange(category1, category2);
	}

Testing entity persistence

Below is the base class we use for testing entity persistence. For this we use SQL Compact Edition as it works well in groups. Note that you don’t even need to set a connection string, it will just create the database in your test project output directory, in our case the database will be named “Portfolio.sdf”.

    [TestFixture]
    public abstract class PersistenceTest
    {
        protected IDbContext context;

        [SetUp]
        public void SetUp()
        {
            DbDatabase.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
            SetupContext();
            context.Database.Delete();
            context.Database.Create();
        }
      
        /// <summary>
        /// Persistance test helper
        /// </summary>
        /// <typeparam name="T">Entity type</typeparam>
        /// <param name="entity">Entity</param>
        protected T SaveAndLoadEntity<T>(T entity) where T : BaseEntity
        {
            context.Set<T>().Add(entity);
            context.SaveChanges();

            object id = entity.Id;

            context.Dispose();
            SetupContext();

            var fromDb = context.Set<T>().Find(id);
            fromDb.ShouldNotBeNull();
            return fromDb;
        }
		
	protected void SetupContext() {
		context = new PortfolioContext("Portfolio");
	}
    }

Finally an example persistence test:

	[Test]
	public void Can_save_and_load_project()
	{
		var project = new Project
		{
			Title = "Some project",
			Slug = "some-project",
			ShortDescription = "A short description",
			Description = "<strong>Html for the win</strong>",
		};

		SaveAndLoadEntity(project);
	}

Overall we are finding that code first along with the above practices makes Entity Framework much more enjoyable to use, and due to it’s partial trust support and great integration with SQL CE, we are using it over NH on smaller projects.

Tags:
Categories Entity Framework | ASP.NET | C# | Development