Showing posts with label StructureMap. Show all posts
Showing posts with label StructureMap. Show all posts

Sunday, 18 December 2011

MVC3 EntityFramework POCO StructureMap

The purpose of this post is to explain how to setup an MVC3 solution which uses Entity Framework POCO as an Object-Relational Mapping (ORM) tool and StructureMap as an Inversion of Control (IoC) tool.

Step 1 - New MVC 3 Project

There are plenty of resources available to show you how to start a new MVC 3 Project in Visual Studio 2010 so i won't go into that...

Step 2 - Add Entity Framework 4.1 as your ORM

There are a few different ways to do this but i use the NuGet package which is pretty straight forward.

  1. Open your MVC3 project in VS2010
  2. Tools > Library Package Manager > Manage NuGet packages
    • Click 'Online' in the left hand menu so you can search for new packages
    • Search for 'Entity Framework' - at the time of writing, version 4.2 was available but you can also go direct to the nuget site and some previous versions may be available, for instance, i'm using version 4.1.10331.0
    • See http://nuget.org/packages/entityframework
  3. Simply click 'Install' button and the framework will be installed your machine for future use
  4. Now you have EF installed, right-click on the 'Models' folder (or where-ever you want your .edmx file to end up) in your solution and choose Add > New item
    • Under the 'Data' heading, choose 'ADO.Net Entity Data Model'
    • Follow the prompts accordingly...use Google for more info ;-)
Step 3 - Install and configure StructureMap

  1. You can get the latest version of StructureMap from here: http://sourceforge.net/projects/structuremap/ 
  2. The easiest way to install and configure Structure Map though, is to use the NuGet package manager again
  3. Similarly to step 2.2 above, search for 'structure' within the Online NuGet packages and you should find one (at the time of writing) called 'StructureMap.MVC3'
    • Be sure not to confuse this with another very similar package called 'StructureMap-MVC3' which is now deprecated
to be continued...

Thursday, 6 October 2011

StructureMap + MVC3 + Generic Repository Pattern

I had this exact same problem:

Have a Generic Repository:

public interface IRepository<TEntity> : IDisposable where TEntity : class
     { }
and a Concrete Implementation:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
     { }
which i wanted injected into the constructor of the Controllers at runtime where the TEntity would be the Model relevant to that Controller:
    public FooBarController(IRepository<FOO_BAR_TYPE> repository)
            {
                _repo = repository;
            }
the Controller would then use Repository "_repo" to update the Model:
    //
    // POST: /EmergencyServiceType/Create
    [HttpPost]
    public ActionResult Create(FOO_BAR_TYPE foobar)
    {
        if (ModelState.IsValid)
        {            
            // GetNextSequenceValue() deals with Oracle+EF issue with auto-increment IDs
            foobar.FOO_BAR_ID = _repo.GetNextSequenceValue(); 
            _repo.Add(foobar);
            _repo.SaveChanges();
            return RedirectToAction("Index");  
        }
    
        return View(foobar); // display the updated Model
    }
simonjreid elluded to the answer for me: had to add the ObjectContext to the StructureMap configuration (the Repository's purpose was to wrap up the Context generated by EntityFramework, which i called MyContextWrapper. Therefore because the Repository depended on MyContextWrapper, which in turn depends on ObjectContext):
    // This avoids 'No Default Instance for ...DbConnection' exception
    x.For<System.Data.Objects.ObjectContext>().Use<MyContextWrapper>();
    x.For<System.Web.Mvc.IController>().Use<Controllers.FooBarController>().Named("foobarcontroller"); // note that Named is required and is Case Sensitive
However, now i get the StructureMap runtime Exception:

StructureMap Exception Code: 205
Missing requested Instance property "connectionString"

After reading a post by Jeremy Miller [A Gentle Quickstart][1] (right at the bottom) i found that you can define what arguments to pass into the constructor of your registered types ie i needed to pass in the Connection String to the Constructor of the MyCustomContext class (here is the full listing of how i am initializing the ObjectFactory:
    string connStr = System.Configuration.ConfigurationManager.ConnectionStrings["MyContextWrapper"].ConnectionString;
    ObjectFactory.Initialize(x =>
                {
                    x.Scan(scan =>
                            {
                                // Make sure BUSINESS_DOMAIN assembly is scanned
                                scan.AssemblyContainingType<BUSINESS_DOMAIN.MyContextWrapper>(); 
                                scan.TheCallingAssembly();
                                scan.WithDefaultConventions();
                            });
                    // 'connStr' below is a local variable defined above
                    x.For<System.Data.Objects.ObjectContext>()
                        .Use<MyContextWrapper>()
                        .Ctor<string>().Is(connStr);
                    x.For<System.Web.Mvc.IController>().Use<Controllers.FooBarController>().Named("foobarcontroller"); 
                });
And BOOM! Can now have my Controller instaniated at runtime by StructureMap and get it to inject an instance of IRepository...happy days.

[1]: http://structuremap.net/structuremap/QuickStart.htm

StructureMap MVC3 Inject Repository Into a Controller

Been working on this for a while and had to pull together information from various sources.

The way i finally got it to work (and this will need to be refactored further) was to ensure that the Type you put into the Use() method is named - otherwise you'll get the exception: "No Parameterless Constructor...".

I am not using the StructureMap configuration file, but instead the Fluent Interface, Registry DSL to configure StructureMap programmatically in the Application_Start event of Global.asax.cs:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    StructureMap.ObjectFactory.Initialize(x =>
        {
            x.UseDefaultStructureMapConfigFile = false;
            x.For<System.Web.Mvc.IController>().Use<MvcSMTest.Controllers.BlogController>().Named("blog");
            x.For<MvcSMTest.Models.IPostRepository>().Use<MvcSMTest.Models.InMemoryPostRepository>();
        });
    ControllerBuilder.Current.SetControllerFactory(new MvcSMTest.Controllers.MyControllerFactory());
}

Wednesday, 5 October 2011

StructureMap Use() vs Add()

StructureMap 'For().Use()' vs 'For().Add()'


If you there's only *one* instance registered against a type, StructureMap goes ahead and assumes that that one is the default.

Use() == the default.  "Anonymous" in some other container's lingo
Add() == named instance (it gets a Guid for the name if you don't set it yourself)..

 Jeremy D. Miller
The Shade Tree Developer
jeremydmil...@yahoo.com