Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SimpleMembership with EF model-first

Tags:

Can SimpleMembership be used with EF model-first? When I try it, I get "Unable to find the requested .NET Framework Data Provider" when I call WebSecurity.InitializeDatabaseConnection.

To put it another way: I can't get the call to WebSecurity.InitializeDatabaseConnection to work when the connection string employs the System.Data.EntityClient provider (as it does when using the model-first paradigm).

To repro the issue, create an MVC 4 app, and replace the code-first UserProfile entity class (which you get for free with the MVC 4 template) with a model-first User class that you have created in the Entity Designer:

  1. Create an MVC 4 app in VS 2012 and add a new, blank Entity Data Model.
  2. Add a new Entity named User to the model, with fields for Id, UserName, and FullName. So, at this point, the User data entity is mapped to a Users table and is accessed via a funky connection string that employs the System.Data.EntityClient provider.
  3. Verify that the EF can access the User entity. One easy way to do that is to scaffold out a Users controller based on the User table and its associated DbContext.
  4. Edit the AccountModels.cs file to remove the UserProfile class and its associated UsersContext class. Replace the references to the (now missing) UserProfile and UsersContext classes with references to your new User class and its associated DbContext class.
  5. Move the call to InitializeDatabaseConnection from the InitializeSimpleMembershipAttribute filter class to the Application_Start method in Global.asax.cs. While you're at it, modify the arguments to use your new User entity's connection string, table name, and UserId column name.
  6. Delete the (no longer used) InitializeSimpleMembershipAttribute class and the references to it.

When you run the repro, it will get an Exception at the call to InitializeDatabaseConnection.

Bob

like image 438
Bob.at.Indigo.Health Avatar asked Sep 25 '12 02:09

Bob.at.Indigo.Health


1 Answers

SimpleMembership can work with model first. Here is the solution.

1.InitializeSimpleMembershipAttribute.cs from MVC 4 Internet Application templete should look like this

namespace WebAndAPILayer.Filters {     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]     public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute     {         private static SimpleMembershipInitializer _initializer;         private static object _initializerLock = new object();         private static bool _isInitialized;          public override void OnActionExecuting(ActionExecutingContext filterContext)         {             // Ensure ASP.NET Simple Membership is initialized only once per app start             LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);         }          private class SimpleMembershipInitializer         {             public SimpleMembershipInitializer()             {                 try                 {                     WebSecurity.InitializeDatabaseConnection("ConnStringForWebSecurity", "UserProfile", "Id", "UserName", autoCreateTables: true);                 }                 catch (Exception ex)                 {                     throw new InvalidOperationException("Something is wrong", ex);                 }             }         }     } } 

2.Delete CodeFirst Classes from AcountModel.cs

3.Fix AccountCotroler.cs to work with your Model-first DbContext (ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl) method)

4.Define your "ConnStringForWebSecurity" connection string which is not same as that funky conn string for model-first db access, notice that we use provider System.Data.SqlClient not System.Data.EntityClient

 <connectionStrings>          <add name="ModelFirstEntityFramework" connectionString="metadata=res://*/Context.csdl|res://*/Context.ssdl|res://*/Context.msl;provider=System.Data.SqlClient;provider  connection string=&quot;data source=.\SQLEXPRESS;Initial  Catalog=aspnet-MVC4;Integrated  Security=SSPI;multipleactiveresultsets=True;App=EntityFramework&quot;"  providerName="System.Data.EntityClient" />          <add name="ConnStringForWebSecurity" connectionString="data source=.\SQLEXPRESS;Initial Catalog=aspnet-MVC4;Integrated  Security=SSPI" providerName="System.Data.SqlClient" />        </connectionStrings> 
like image 167
Mario Zderic Avatar answered Sep 28 '22 18:09

Mario Zderic