2012-12-21

Asp.net MVC MEF: Per Request Lifetime

,

Like the title says, i want to use MEF in an Asp.Net MVC application and the lifetime of the object has to be exactly the same as the lifetime of the request. In short, i want 1 single unique object that is recreated per request.

In MEF there is a way to control the lifetime of the created object. This is specified the PartCreationPolicy attribute that you can use to decorate the object. In my test project i installed the nuget package i created in this post to incorporate MEF in an Asp.net MVC application. I also created an object called MyCustomObject with an interface IMyCustomObject. This object has only one property called Created that contains the date when the object is created. In the constructor of that object i have but an thread.sleep. This way i am sure that the Created property will be different for every created object.

 public interface IMyCustomObject
{
DateTime Created { get; set; }
}
 [Export(typeof(IMyCustomObject))]    
public class MyCustomObject : IMyCustomObject
{
public DateTime Created { get; set; }

public MyCustomObject()
{
Created =
DateTime.Now;
System.Threading.
Thread.Sleep(1000);
}
}

I also created an object called MyCustomObjectContainer. This object will contain a property of the type IMyCustomObject.

 [Export]   
public class MyCustomObjectContainer
{
[
Import]
public IMyCustomObject MyCustomObject { get; set; }
}


The controller will have 2 properties. The first of type IMyCustomObject aand the other of type MyCustomContainer. In the action method of the controller, i will write the Created value that is found in those 2 properties to the viewbag. That way i will be sure if the application is using the same object.

    [Export]
[
PartCreationPolicy( CreationPolicy.NonShared)]
public class HomeController : Controller
{
[
Import]
public IMyCustomObject MyCustomObject { get; set; }

[
Import]
public MyCustomObjectContainer MyCustomObjectContainer { get; set; }

public ActionResult Index()
{
this.ViewBag.MyCustomtObjectDateCreated = MyCustomObject.Created;
this.ViewBag.MyCustomObjectContainerDateCreated = MyCustomObjectContainer.MyCustomObject.Created;
return View();
}
}

Choosing the right PartCreationPolicy


In MEF there are 3 different type of creation policies that we can choose. More information can be found here.



  • Shared: the part author is telling MEF that at most one instance of the part may exist per container.
  • NonShared: the part author is telling MEF that each request for exports of the part will be served by a new instance of it.
  • Any or not supplied value: the part author allows the part to be used as either “Shared” or “NonShared”.

The Shared Creation policy


We will set Creation policy to Shared and run the application.


image


 


We see that the same instance of the MyCustomOject is used. But when we refresh the page, we will get exactly the same value, over and over again. So this is not the behavior that we want.


The NonShared Creation Policy


We will set the creation policy to NonShared.


image


With every refresh, we will get a different value for the Created property, but everytime that an IMyCustomObject is asked form the MEF container, a new value is created so this is not a solution for my problem.



The solution


We can create a solution for this problem using the Proxy-pattern, HttpContext and ExportFactory<T>.


The ExportFactory<T> class was introduced in MEF 2. It allows us to create new instances and control the lifetime of those instances. This will be  perfect to create the MyCustomObject object since we need to control the lifetime of this object.


The HttpContext contains Http information about an HttpRequest. There is one property that is very interesting  in our case, the Items property. This property is in fact a dictionary where you can insert objects into. This collection is cleared with every request (perfect). We will use this dictionary to add the created MyCustomObject. So every time that this object is requested, we will look in this dictionary. When it is not found, the ExportFactory<T> will create it and add it to the dictionary.


The proxy pattern will be used to make this a transparent as possible.


image


The Implementation


I’ll create an IItemContainer that has one property Container of type IDictionary. Then i’ll create an HttpContextContainer that will implement this interface. This object will map the Container property to the HttpContext.Items property.

public interface IItemContainer
{
IDictionary Container { get; }
}
[Export(typeof(IItemContainer))]
[
PartCreationPolicy(CreationPolicy.Shared)]
public class HttpContextContainer : MEF_Asp.Net_MVC_Per_Request.Models.IItemContainer
{
public IDictionary Container
{
get
{
return HttpContext.Current.Items;
}
}
}

Next I'll create the proxy object (MyCustomObjectPerRequest). This object will contain the IItemContainer and the Exportfactory<T> instances and implement the IMyCustomObject. This object will be served by the MefContainer when something is request of type IMyCustomObject.

[Export(typeof(IMyCustomObject))]
public class MyCustomObjectPerRequest : IMyCustomObject
{
[
Import]
public ExportFactory<MyCustomObject> Factory { get; set; }

[
Import]
public IItemContainer ItemContainer { get; set; }

private IMyCustomObject MyCustomObject
{
get
{
if (null == ItemContainer.Container["MyCustomObject"])
{
ItemContainer.Container[
"MyCustomObject"] = Factory.CreateExport().Value;
}

return (IMyCustomObject)ItemContainer.Container["MyCustomObject"];
}
}

public DateTime Created
{
get
{
return MyCustomObject.Created;
}
set
{
MyCustomObject.Created =
value;
}
}
}

 


We also need to change the ExportAttribute on the MyCustomObject class so that it doesn’t specify a ContractType.

 [Export] 
public class MyCustomObject : IMyCustomObject

The Result


When we know run the application, we will use the same MyCustomObject object per request. When we refresh, we’ll get an other instance.


image





Conclusion


This solution can also be used to use the same instance per Session or to incorporate a caching mechanism.  All that needs to been done is to implement the IItemsContainer and map the Container property. The Visual Studio solution can be downloaded here.

Read more →

2012-12-16

Asp.net MVC: reuse Areas from external project

,

I created a MVC project that has an Area defined that i would like to use in an other MVC project. Here is the structure.

image

I created a reference between the AlphaArea and MainApp project. When i run the application is see that the area registration of the AlphaArea is executed. But when i try to go to the area i get an error.

image

What this error says, is that the view for the Index of the AlphaController in the Alpha area isn’t found. This makes perfect sense because the Index view isn’t declared in the MainApp project and this is where MVC  tries to find the view. We need to make sure that the view engine can resolve the view.

There are a couple solutions to resolve this. We could copy or create a link in the MainApp to the index view that is defined in the AlphaArea. We would need to copy the whole Area structure. Don’t know about you but I'm not really found of that solution. An other solution is to compile the AlphaArea views in the DLL. This can be done by a Visual Studio extension and a Nuget package.

First you need to install the Razor Generator extension for Visual Studio.

image

This extension will create a .cs file for a view, but in the properties of that view, the Custom Tool needs to be set to “RazorGenerator”.  Otherwise the VS extension will not create a .cs file for that view.

image                                                 image

When we compile the project, the view will be added to the DLL of the AlphaArea project. This isn’t enough. Now we need a way to tell the view engine that the view can be found in the DLL. Luckily, there is a Nuget package that does the trick. You simply need to install the package “RazorGenerator.Mvc” in the AlphaArea project.

image

This package will add a file (RazorGeneratorMvcStart) in the AppStart folder. This file will create a PrecompiledMvcEngine and add it to the ViewEngines. The code will be executed when the applications starts. This is done by using the WebActivator.

using System.Web;
using System.Web.Mvc;
using System.Web.WebPages;
using RazorGenerator.Mvc;

[
assembly: WebActivator.PostApplicationStartMethod(typeof(AlphaArea.App_Start.RazorGeneratorMvcStart), "Start")]

namespace AlphaArea.App_Start {
public static class RazorGeneratorMvcStart {
public static void Start() {
var engine = new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly) {
UsePhysicalViewsIfNewer =
HttpContext.Current.Request.IsLocal
};

ViewEngines.Engines.Insert(0, engine);

// StartPage lookups are done by WebPages.
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
}
}

When we now run the application and go to the Alpha area, the view is resolved.


image


The same system can also be used on Controllers in external projects. The example for the post can be downloaded here.

Read more →

2012-12-12

Web Api: Passing a Complex type in JSON

,

In one project i wanted to pass a complex type to the Post method of an Web Api controller. The Post itself will be done using JQuery in the JSON format. I noticed that the parameter was always null. After a bit of searching i found the solution.

The Set Up

Server side

public class ValuesController : ApiController
{
// POST api/values
public void Post(MyComplexType value)
{
}
}

public class MyComplexType
{
public string Name { get; set; }

public MyComplexSubType MyComplexSubType { get; set; }
}

public class MyComplexSubType
{
public int Age { get; set; }
}

Client Side

 <script type="text/javascript">

function
MyComplexSubType()
{
var self = this;

self.Age = 26;
}

function MyComplexType()
{
var self = this;

self.Name =
"Kenny Tordeur";
self.MyComplexSubType =
new MyComplexSubType();
}


function PostComplexType()
{
$.ajax(
"/api/values", {
data: JSON.stringify(
new MyComplexType()),
contentType:
'application/json',
type:
'POST',
success: SendComplexTypeCallBack
});
}


function SendComplexTypeCallBack(data)
{
alert(
"Complex type sended");
}
</script>

The PostComplexType will be trigged by a click event on a button. It will create a javascript object called MyComplexType. This object will map directly to the object we created on the server side.


 


image


The missing link


With this set-up the parameter will always be null. We need to add a line of code to the global.asax.

ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());

 


Value providers are used by the model binding system in MVC to populate the values of model objects. We basically add a provider that enables to bind a model to a JSON model.  The solution can be downloaded here.

Read more →

2012-12-07

WebApi: File upload and download using JQuery and submit button

,

I am going to create a WebApi service called FileService that can be used to upload and download files. The service will only contain 2 methods. A Post to upload and a Get method that accepts an id parameter to identify the file that needs to be downloaded. Let’s start with the Post method.

The Post method

This method will look in the Request object to see if there are any posted files. If so, it will loop over the files and create them on the server side. The server will return a 201 HttpStatus and a list of strings that will contain the full path of the file(s) at server side. When there are no files posted, the service will return a 401 status a.k.a. BadRequest.

public HttpResponseMessage Post()
{
HttpResponseMessage result = null;
var httpRequest = HttpContext.Current.Request;

// Check if files are available
if (httpRequest.Files.Count > 0)
{
var files = new List<string>();

// interate the files and save on the server
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
postedFile.SaveAs( filePath);

files.Add(filePath);
}

// return result
result = Request.CreateResponse(HttpStatusCode.Created, files);
}
else
{
// return BadRequest (no file(s) available)
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}

return result;
}

The Get Method


As mentioned before, the Get Method will accept a string file that will identify (= filename) the file that needs to be downloaded.

public HttpResponseMessage Get(string id)
{
HttpResponseMessage result = null;
var localFilePath = HttpContext.Current.Server.MapPath("~/" + id);

// check if parameter is valid
if (String.IsNullOrEmpty(id))
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
// check if file exists on the server
else if (!File.Exists(localFilePath))
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{// serve the file to the client
result = Request.CreateResponse( HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = id;
}

return result;
}

Uploading a File


Using a submit  button

 <form name="form1" method="post" action="api/file" enctype="multipart/form-data">
<
div>
<
label>
Using submit</label>
<
input name="myFile" type="file" />
</
div>
<
div>
<
input type="submit" value="Submit" />
</
div>
</
form>


Using JQuery

<form enctype="multipart/form-data">
<
label>
Using JQuery</label>
<
input name="file" type="file" />
<
input type="button" id="Upload" value="Upload" />
</
form>
        <script type="text/javascript">
$(function () {
$('#Upload').click(function () {
var formData = new FormData($('form')[0]);
$.ajax({
url: 'api/file',
type: 'POST',
// Form data
data: formData,
//Options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: false,
processData: false
});
});
});
</script>

Downloading a File


image


Summary


The solution can be downloaded here.

Read more →

2012-12-01

Paged Grid with Knockout.js and WebApi

,
I want to see how easily you can create a custom grid that uses an WebApi as datasource and that allows the user to page the data and also allow them to choose a page size for the grid.

The WebApi

The WebApi will return a viewmodel that contains an array of names (string) and a property that specifies how many pages that there are available.
    public class NamesGridViewModel
    {
        public IEnumerable<String> Names { get; set; }

        public int NumberOfPages { get; set; }
    }

The WebApi itself will contain a method that accepts 2 parameters. The parameters will be page (the page that we request) and pagesize (how many entries a page contains). This method will be responsible for calculating how many pages there are and to serve the requested names based on the 2 parametes.
    public class ValuesController : ApiController
    {
        public IList<String> Names
        {
            get { return new List<String> { "Fred", "Barney", "Betty", "Wilma", "Bart", "Lisa", "Maggie", "Homer", "Marge" }; }
        }
            
        public NamesGridViewModel Get(int page, int pagesize)
        {
            return new NamesGridViewModel
                       {
                           // get the request names for the specific page
                           Names = (0 == page? null : Names.Skip((page - 1)*pagesize).Take(pagesize).ToArray())
                           ,
                           // calculated number of pages and ceil the value
                           NumberOfPages = ((int) Math.Ceiling((double) Names.Count/pagesize))
                       };
        }
    }

The client


The client will need a reference to kockout.js. With knockout.js it is possible to apply the MVVM pattern and also work with templates in javascript.


The UI

Page size: <select data-bind="options: availablePageSize, optionsText: $data, value: selectedPageSize"></select><!-- the grid --><table data-bind="with: namesGridViewModel">
    <thead>
        <tr>
            <th>
                Name
            </th>
        </tr>
    </thead>
    <tbody data-bind="foreach: Names">
        <tr>
            <td data-bind="text: $data">
            </td>
        </tr>
    </tbody>
</table><!--Contains the page links--><div id="pager"></div>

The Javascript

<script type="text/javascript">
    // Our  ViewModel.
    function pageViewModel() {
        var self = this;
        self.namesGridViewModel = ko.observable(); // contains the viewmodel returned by the WebApi
        self.selectedPageSize = ko.observable(3); // contains the selected page size, default value is 3
        self.availablePageSize = ko.observableArray([1, 2, 3, 4, 5]); // contains the available page sizes a user can select
        self.selectedPage = ko.observable(1); // contains the selected page

        // Add a click event to all future element with a class "pageIndex". This event will fire
        // when the user clicks a specific page.
        $("#pager").on("click", ".pageIndex", function (event) {
            // set the selected page in the viewModel
            self.selectedPage($(this).text());
        });

        // This function will be used to get the data from our WebApi. The requested page and page size are passed
        // as a parameter. The result will be stored in the namesGridViewModel property. This will cause that the subscribe event
        // for the namesGridViewModel will be fired ==> the page links will be created.
        self.navigate = function () {
            $.get("/api/values?page=" + self.selectedPage() + "&pagesize=" + self.selectedPageSize(), self.namesGridViewModel);
        };

        // Function that will subscribe to all the needed events.
        self.SubscribeToEvents = function () {

            // This event will fire when selectedPageSize is changed.
            self.selectedPageSize.subscribe(function (newValue) {
                self.selectedPage(1);
                self.navigate();
            });

            // This event will be fired when the selectedPage is changed.
            self.selectedPage.subscribe(function (newValue) {
                self.navigate();
            });

            // This event will fire when a new value is defined for the namesGridViewModel.
            // It will create the page links below the grid.
            self.namesGridViewModel.subscribe(function (newValue) {
                var numberOfPages = newValue.NumberOfPages;
                var $pager = $("#pager");
                // clear the pager
                $pager.html("");
                // created the pages the user can click on
                for (var i = 1; i <= numberOfPages; i++) {
                    var link = $('<a class="pageIndex">' + i + '</a>');
                    $pager.append(link);
                }
            }, this);
        };
        
        // This function will be used to kick start everything.
        self.bind = function () {
            self.SubscribeToEvents();
            self.navigate();
            ko.applyBindings(self);
        }
    }
    // Create the viewModel and bind it.
    $(function () { new pageViewModel().bind(); })</script>

The result


image

Summary


You have seen how to create a basic paging grid using Knockout.js.You can easily extend this example to also allow sorting. The solution can be downloaded here.
Read more →

2012-11-28

Nuget package: integrated MEF in Asp.Net MVC 4 and WebApi

,
Today i wanted to create my first Nuget package and i already knew what i would publish to the world. I wanted to make the code that is used to use MEF in Asp.Net MVC 4 and the WebApi (view this post) easy to reuse in other projects. I rewrote the code in a class libary.
After a little google-ing i found a video that explained how to create a Nuget package using the Nuget Package Explorer.  After that i created a user at the Nuget gallery so i got my API Key. With this, i had all the information i needed to published my first Nuget package and i have a feeling that it will not be my last :-)
The package can be installed from the Package Manager Console by typing: Install-Package MEF.MVC4
Read more →

2012-08-31

MEF in Asp.Net MVC 4 and WebApi

,
MEF stands for “Microsoft Extensibility Framework”. If you want an overview of MEF, you can look here. In this post we will integrated MEF with Asp.Net MVC 4 and with the WebApi.

Asp.Net MVC 4

First of all you need to reference the “System.ComponentModel.Composition.dll” assembly which contains the implementation of MEF. Now where are going to create a MEF controller factory. Like the name says, it will be responsible to create the controller that is requested.

public class MefControllerFactory : DefaultControllerFactory
   {
       private readonly CompositionContainer _compositionContainer;

       public MefControllerFactory(CompositionContainer compositionContainer)
       {
           _compositionContainer = compositionContainer;
       }

       protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
       {
           var export = _compositionContainer.GetExports(controllerType, null, null).SingleOrDefault();

           IController result;

           if (null != export)
           {
               result = export.Value as IController;
           }
           else
           {
               result = base.GetControllerInstance(requestContext, controllerType);
               _compositionContainer.ComposeParts(result);
           }
         
           return result;
       }
   }

The MefcontrollerFactory will inherit from the DefaultControllerFactory and has a constructor that accepts a CompositionContainer. To plug in MEF, the GetControllerInstance methode will be overridden. First will look in our exports if something is defined for the requested controller type. Mark that the SingleOrDefault method is used because if more exports are defined for a controller, an exception will be throw. If this exception is thrown, something is wrong with the configuration of the CompositionContainer. If a single export is found, we’ll get the object from the Value property.


If the export isn’t found, the base method will be invoked. That way, the controller is created the default-way. When the controller is created, the ComposeParts method on the CompositionContainer is invoked. This will resolve the needed import for the controller.



This is the object that will be injected. The GetMessage method will return a string that will be shown on the view.
public interface IMyTest{
    String GetMessage();
}

[Export(typeof(IMyTest))]
public class MyTest1 : IMyTest{
    public MyTest1()
    {
        creationDate = DateTime.Now;
    }

    public string GetMessage()
    {
        return String.Format("MyTest1 created at {0}", creationDate.ToString("hh:mm:ss")) ;
    }

    private DateTime creationDate;
}


The Export attribute says to MEF that this class can be exported. The type of IMyTest is pasted as a parameter. This indicates the contract that is used. So when an IMyTest is requested from MEF, an object of MyTest1 is returned.
[Export]
public class HomeController : Controller{
    [Import]
    private IMyTest _myTest;

    public ActionResult Index()
    {
        ViewBag.Message = _myTest.GetMessage();

        return View();
    }
}

The HomeController is marked for export and an import attribute is put on the “_mytest” property. Of course we still need to configure MVC to use our MefControllerFactorty. To accomplish this, is created a static class with one static public method (RegisterMef). This method will create a Mef CompositionContainer and pass this container to the MefControllerFactory. This MefControllerFactory will be set as the controller factory for MVC. To configure the CompositionContainer an AssemblyCatalog is used.
public static class MefConfig{
    public static void RegisterMef()
    {
        var container = ConfigureContainer();

        ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
        
        var dependencyResolver = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver;
    }

    private static CompositionContainer ConfigureContainer()
    {
        var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        var container = new CompositionContainer(assemblyCatalog);
        
        return container;
    }
}

The RegisterMef method will be called form the Application_Start method that resides in the global.asax.
public class MvcApplication : System.Web.HttpApplication{
     protected void Application_Start()
     {
        AreaRegistration.RegisterAllAreas();

        MefConfig.RegisterMef();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();
     }
}

When the Index action for the HomeController is requested through the browser, everything works just fine but when it is requested it again, an exception is thrown.

A single instance of controller 'MvcApplication5.Controllers.HomeController' cannot be used to handle multiple requests. If a custom controller factory is in use, make sure that it creates a new instance of the controller for each request.


This exception is thrown because the lifetime of the controller is linked to the lifetime of the CompositionContainer. The container keeps a reference to all the objects that it has created. If the same object is requested, the reference of the previous object is given. There are 2 ways to solve this problem.

You could pass an instance of a ComposablePartCatalog (in this case the AssemblyCatalog) to the MefControllerFactorty. Then in the “GetControllerInstance” method always compose a new CompositionContainer to resolve the controller. Personally I'm not really found about that.

The other solution is to use a CreatonPolicy. If we put a CreationPolicy of “NonShared” on the HomeController, a new instance of the HomeController is created from scratch every time it gets requested. Since this a standard feature of MEF, I'll use this solution.
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller{
    [Import]
    private IMyTest _myTest;

    public ActionResult Index()
    {
        ViewBag.Message = _myTest.GetMessage();

        return View();
    }
}

Now we can request the controller as many times as we want.


WebApi


This is the created WebApi controller. Mark that the controller also has a CreationPolicy defined. This is for the same reason a mentioned above.
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : ApiController{
    [Import]
    private IMyTest _myTest;

    public String GetMessage()
    {
        return _myTest.GetMessage();
    }
}

To plug in MEF in the WebApi a object needs to be created from the System.Web.Http.Dependencies.IDependencyResolver interface. This is how the object looks like.
public class MefDependencyResolver : IDependencyResolver{
    private readonly CompositionContainer _container;
    
    public MefDependencyResolver(CompositionContainer container)
    {
        _container = container;
    }

    public IDependencyScope BeginScope()
    {
        return this;
    }

    public object GetService(Type serviceType)
    {
        var export = _container.GetExports(serviceType, null, null).SingleOrDefault();

        return null != export ? export.Value : null;
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        var exports =_container.GetExports(serviceType, null, null);
        var createdObjects = new List<object>();

        if ( exports.Any())
        {
            foreach (var export in exports)
            {
                createdObjects.Add(export.Value);
            }
        }

        return createdObjects;
    }

    public void Dispose()
    {
        ;
    }
}



The “BeginScope” method returns a scope in with the create objects will life. Since we are going to use MEF to control the lifetime of the created objects, we can do a return of “this”.  We can do this because the IDependencyResolver inherits form IDependencyScope. If you really need a limited scope per request, the “BeginScope” method always needs to return a new object of type IDependencyScope.

You also need to implement a “Dispose” method to release the used resources. In the MefDependencyResolver, it isn’t implemented. This is because we return the current instance in the “BeginScope” method. If we disposed the CompositionContainer, we could only request the service once.


Right now, the only thing needed, is the register the create MefDependencyResolver. This will be done in the modified MefConfig class.
public static class MefConfig
   {
       public static void RegisterMef()
       {
           var container = ConfigureContainer();

           ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
           
           var dependencyResolver = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver;
           System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new MefDependencyResolver(container);
       }

       private static CompositionContainer ConfigureContainer()
       {
           var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
           var container = new CompositionContainer(assemblyCatalog);
           
           return container;
       }
   }



The example can be downloaded from here.
Read more →

2012-08-14

Entity Framework: Database Migrations

,

If you don’t like writing SQL DDL statement, like me, than Entity Framework is very handy. With the Code-First, you can write your model and don’t need to worry about your database. It is generated for you by Entity Framework. This is very handy but what if you are working with an existing database? Or if you need to support different versions of your database? That is where database migrations come in to play.

Before we start

  1. Create an Asp.Net MVC 4 application
  2. Use Nuget to install the latest version of the Entity Framework (5.0.0-rc)

Because i am not running an SQL Express or SQL Server on my machine, i am also going to install SqlServerCompact so i can work with an SDF file. This needs a little more configuration.

  1. Install EntityFramework.SqlServerCompact form Nuget.
  2. Change the connectionstring in the web.config
      <connectionStrings>
        <
    add name="DefaultConnection" connectionString="Data Source=|DataDirectory|\DBTest.sdf;Max Database Size=2047" providerName="System.Data.SqlServerCe.4.0" />   
      </
    connectionStrings>

Create your models. In my case i will create as Car and Make class.

namespace EF_DatabaseMigrations.Models
{
public class Car
{
public Int32 Id { get; set; }

public String Model { get; set; }

public Make Make { get; set; }
}

public class Make
{
public Int32 Id { get; set; }

public String Name { get; set; }
}
}

Next i will create a DbDatasource that will map my entities to the database. This datasource will pass the name of the connectionstring to the base constructor.

namespace EF_DatabaseMigrations.DB
{
public class DbDatasource : DbContext
{
public DbDatasource()
: base("DefaultConnection")
{ }

public DbSet<Car> Cars { get; set; }

public DbSet<Make> Makes { get; set; }
}
}

Let’s migrate


To configure your application to use migrations, you have to type “enable-migrations” command in the Package Manager Console. This will create a Migrations folder that contains a Configuration file. This class contains a seed method that accepts the DbDatasource as a parameter. The seed method will always be execute when you update your database. This method will typically be used to create users in the database or in our case to create the Makes in our database.  By default, AutomaticMigrationsEnabled will be set to false. Since we want to automate everything, we need to set it to true :-).


namespace EF_DatabaseMigrations.Migrations
{
internal sealed class Configuration : DbMigrationsConfiguration<EF_DatabaseMigrations.DB.DbDatasource>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}

protected override void Seed(EF_DatabaseMigrations.DB.DbDatasource context)
{
context.Makes.AddOrUpdate(m => m.Name, new Make { Name = "Ford" }
, new Make { Name = "Opel" }
, new Make { Name = "BMW" });
}
}
}

Because the Seed method is always called, we have to make sure that the Makes we are adding, only are getting inserted if they don’t exists or are updated when they do exists the database. That is why we are using the AddOrUpdate methode. The first parameter is in fact our condition for the insert or update. If a make with a name “Ford” doesn’t exists in the database, it is inserted. If it does exists, it gets updated.


 


When we type “update-database” command in the Package Manager Console, EF will create our database and will call the Seed method. The location of the database will be determined by the connectionstring that you specify. In our case it will be found in the App_Data folder.


When we open the database, we see that a Cars and a Makes table are created. The Makes table is pre-filled.


 image


In the table “_MigrationHistory” all migrations that where performed on this database are stored. That way you can always see what version of database this is. Also Entity Framework will need this information.


Now let’s assume that we want to add a BuildDate property to the Car. We can put this in a new migration. This way we can keep track of all our modifications in our database.


Change the Car entity.


    public class Car
    {
    public Int32 Id { get; set; }

    public String Model { get; set; }

    public Make Make { get; set; }

    public DateTime BuildDate { get; set; }
    }

Add Migration


Type “add-migration AddBuildDate” in the Package Manager Console. This will create a new file in the Migration folder. The file name will contain the date + the name that we specified.


This new file will contain 2 methods that we can override. The “Up” method will contain all new database modifications. The “Down” will contain the rollback of the modifications. This way we can easily “jump” through database versions. We manually add the AddColumn and DropColumn statements.

namespace EF_DatabaseMigrations.Migrations
{
public partial class AddBuildDate : DbMigration
{
public override void Up()
{
AddColumn("dbo.Cars", "BuildDate", c => c.DateTime(nullable: false));
}

public override void Down()
{
DropColumn("dbo.Cars", "BuildDate");
}
}
}

When we want to apply those modifications, we need to type “update-database -TargetMigration:AddBuildDate”. This will modify our database and add the new column.


image


 


If you want to rollback the database at it’s begin state, you type “update-database -TargetMigration:0” in the Package Console Manager.


What about the database adminstrators


We can’t forget these guys. They probably won’t like this way of creating the database and would probably prefer a script. Well you can add an extra parameter to the “update-database” called script that will create a clean SQL script that performs all the necessary steps to create the database.


“update-database –TargetMigration:AddBuildDate –script” will create this script:

ALTER TABLE [Cars] ADD [BuildDate] [datetime]
INSERT INTO [__MigrationHistory] ([MigrationId], [Model], [ProductVersion]) VALUES ('201208140904052_AddBuildDate', 0x1F8B0800000000000400ECBD07601C499625262F6DCA7B7F4AF54AD7E074A10880601324D8904010ECC188CDE692EC1D69472329AB2A81CA6556655D661640CCED9DBCF7DE7BEFBDF7DE7BEFBDF7BA3B9D4E27F7DFFF3F5C6664016CF6CE4ADAC99E2180AAC81F3F7E7C1F3F22FEC7BFF71F7CFC7BBC5B94E9655E3745B5FCECA3DDF1CE4769BE9C56B36279F1D947EBF67CFBE0A3DFE3E8374E1E9FCE16EFD29F34EDF6D08EDE5C369F7D346FDBD5A3BB779BE93C5F64CD78514CEBAAA9CEDBF1B45ADCCD66D5DDBD9D9D83BBBB3B777302F111C14AD3C7AFD6CBB658E4FC07FD79522DA7F9AA5D67E517D52C2F1BFD9CBE79CD50D317D9226F56D934FFECA3D367BFFFD3ACCD2659937F515CD4594B0835E3A74F3E4A8FCB22237C5EE7E5F97B22B7F310C87D64BBA58E4F09C1F6FACDF52AE7CE3FFBE824ABFD06D4E4F7CAAF830FE8A39775B5CAEBF6FA557EAEAF9DCD3E4AEF86EFDDEDBE685FF3DE41CFF4DBB2BDB7F751FA625D96D9A4A40FCEB3B2C93F4A579F3E7ADD5675FE79BECC8904F9EC65D6B679BDC4BB3963AE1478B4FAF47644787877670F44B89B2D9755CB54ED21DE4193E7CA60FABAAD89653E4A9F15EFF2D9F37C79D1CE2DB65F64EFCC27FB3B3BC4395F2D0B62317AABADD7B93F3CF97B73B74FD645392316C84DD7F8FD0D7153844E1D482FB2CBE282C7D61D4AF6965ABFCA4B61A779B1123E1AD3ACFFFEF2E5B3BA5ABCAA00DB7CF6FBBFAED6F51468549D2FDE64F545DE86DD3FBEEB586A23A371773FE2341F4DFCFBB3CD6843F373DC34D5B460349D26F8FD239374BA9CA5430C22982B43119EEBB22D566531A5FE3EFBE85BBDE147401996F240095F86B076C6E3DDEEB8BC11F4198F546F9B1534B73AB8A71368D74610EF6285175EE7ADA343F351EAA8E68FB037A0F055A01E7B5786D479D9C33FE85C05D3FBBA2BB45DA1D93045164333AE1089CD93E2BDAC23EB0A62388608DBD97970B6EFAE183F6324EF0E58C9C75F64AB1589846735F593F4B598CC93EDD7EF6F101702E3EEB489D8458BADED897444769177BEA5AE09D36745DDB4C6667F949ECC16BD66B7E13AD395C77CFD2932FC641AE3777961C86F607EED0072247C46A35A909EE301EAF00C93F4DF4AE1B064655647D4EC4955AE17CB2155BDE96DB5B33E00FDE8F6303CA3E9C3F13EEEC37A7CB743842EB93D8DA92D3B5CDF9DBB5BCDAC48D03732B53125708BB98DBFF6B333B962DAFCF7E5931FFE74842AAA276DAA6D6F4175D7F8164203B5DA214957BDF62971AB796010B1C900216C9FEF818E9A8AAF89CE7B6342EA7156B0DB71D6C071B15ECE2D06D93538FD09EFD99D6E13CB6ED6FE74ECCC63D5F98131626A7443B69E1190261FA534F4CB620603F0FABA69F3C5180DC6AF7F51F93AAF29263DC9C7FB08344DB32FB265719E37ED9BEA6D4EB69EBFFBBA419FF5429B6656FEBF30F22B96ADCACF26CFFBA6806753C4B6BCCCEAE99CDDD1AEDBFC8101D98C7E4778FFFEF8196EF668F0757CF6DE14FEDCC4543F2B7328E6E183A6F01B0C759C5178AFA02480C101C3FB86483447790D126625A9B0A6AD4989F52CE24B0A15A7C52A2B7D6CFBFAFB36F30EAA5970DD6F9EE6AB7C8909F546749B6E3698280BB2C37D378DFB3DC3BDBE7FDE9DA55ECC3714F2895227E99F54349DC27BB1502A1A0C0EC68231A8F118EB67234CF45173AEE10DB1613798FCD98906FBD6979863BDB4695562CAA6B87020E04F2CF369C016B6CDD9F2BC32ECD9C1C834E9AAEABCCD48CF67C7755B9C67D396BE9EE64DC3A9999FCCCA3535395D4CF2D9D9F2CB75BB5AB734E47C3129AF7D6280CB37F5CF216F88F3E32F57EC677E134320340B98AA2F976CC12CDECFFA6A780804C447753BE6B2858EBFB8B6905E54CB5B0252F23D3552FF265FAC281999375F2E5F6797F9306E37D330A4D8E3A74546CEFAA249EF1E09D3787C42EC4739FAA3FF270000FFFFEA4946EC18180000, '5.0.0-rc.net40')


The Visual Studio solution can be downloaded here.

Read more →