I spent yesterday retrofitting StructureMap into an ASP.Net MVC site that I wrote earlier in the year. I ran into a number of minor issues that made me stop and think, and decided to post them here for future reference.
I had already added a constructor to each of my controller classes that allowed services to be passed in as parameters (as it improves testability), so was pretty well prepared for letting StructureMap AutoWire the services as needed.
The site consumed implementations of three interfaces I had defined:
- IHoldSettingsForTheSite
- ILogEvents
- IAmTheSiteRepository
I configured default instances of the implementations in the BootStrapStructureMap procedure which I called from the Application_Start method in the Global.asax:
1: private void BootStrapStructureMap()
2: {
3: ObjectFactory.Initialize(rep =>
4: {
5: rep.ForRequestedType<IHoldSettingsForTheSite>().TheDefaultIsConcreteType<Settings>();
6: rep.ForRequestedType<ILogEvents>().TheDefault.Is.OfConcreteType<EventLogging>().WithCtorArg("sourceName").EqualToAppSetting("ApplicationName");
7: rep.ForRequestedType<IAmTheSiteRepository>().TheDefault.Is.OfConcreteType<Repository>().WithCtorArg("connectionString").EqualTo(ConfigurationManager.ConnectionStrings["OpenFields.MainSite.Data"].ConnectionString);
8: });
9: }
StructureMap Exception Code: 202 No Default Instance defined for PluginFamily AssenblyName.Controllers.IFormsAuthentication, AssenblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
I’d originally built the site using the “out of the box” AccountController class which is added by default in the ASP.Net MVC project template. This class calls a MembershipProvider object to provide for account authentication. I’d configured the application to use the ActiveDirectoryMembershipProvider in production and I wired up a dummy MembershipProvider class for use during development and testing.
Within the AccountController.cs file there are a number of other objects declared:
- IMembershipService
- IFormsAuthentication
- AccountMembershipService (Implements IMembershipService)
- FormsAuthenticationService (Implements IFormsAuthentication)
1: rep.ForRequestedType<IFormsAuthentication>().TheDefaultIsConcreteType<FormsAuthenticationService>();
2: rep.ForRequestedType<IMembershipService>().TheDefaultIsConcreteType<AccountMembershipService>();
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily System.Web.Security.MembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
1: <membership defaultProvider="DUMMY">
2: <providers>
3: <clear />
4: <add name="DUMMY" type="OpenFields.Dummy.MembershipProvider, OpenFields.Dummy" />
5: <add name="AD" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" />
6: </providers>
7: </membership>
rep.ForRequestedType<MembershipProvider>().TheDefault.IsThis(Membership.Provider);
This would be little tricky to do in web.config?
ReplyDeleteThanks!
ReplyDeleteOf course, now with the latest version, the syntax should be:
x.For().Use(Membership.Provider);
No worries Jason. I'll update this post for the latest version of Structure Map this week! :-)
ReplyDeleteI would say "this is article is life saver"
ReplyDeletethis article helped me. Thank you
ReplyDeleteI have been trying to get this set up work but have some really strange problems! When ever the user is updated via the repository, a call to the dbcontext just throws System.ObjectDisposedException! The update does wrap the dbcontext object in a using statement but this is standard practice isn't it? Using entity framework by the way.
ReplyDelete