0

I am trying to configure a custom membership provider, using the advice of: Custom MembershipProvider in .NET 4.0

My environment: VS2012, ASP.NET NVC4 Internet Application (created by wizard). My goal is to manage the users in an external data store.

After adding a provider code... I added the following section to the section of web.config:

 <membership defaultProvider="MyMembershipProvider">
  <providers>
    <clear/>
    <add name="MyMembershipProvider" type=" MvcApplication2.Models.MyMembershipProvider" connectionStringName="DefaultConnection"
         enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
         maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
         applicationName="/" />
  </providers>
</membership>

After trying to debug the app, I got the following error:

Server Error in '/' Application.

Configuration Error

Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately. 

Parser Error Message: This method cannot be called during the application's pre-start initialization phase.

Source Error: 


Line 41:       <providers>
Line 42:         <clear/>
Line 43:         <add name="MyMembershipProvider" type="MvcApplication2.Models.MyMembershipProvider" connectionStringName="DefaultConnection"

I tried to follow the advice of this article: ASP.NET: This method cannot be called during the application's pre-start initialization stage

Unfortunately, after adding the setting as described:

 <add key="enableSimpleMembership" value="false"/>

The app comes up , but after pressing the Login I am getting the following exception in the Visual Studio:

System.Reflection.TargetInvocationException was unhandled by user code
  HResult=-2146232828
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
       at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
           at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at System.Threading.LazyHelpers`1.ActivatorFactorySelector()
   at System.Threading.LazyInitializer.EnsureInitializedCore[T](T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory)
   at System.Threading.LazyInitializer.EnsureInitialized[T](T& target, Boolean& initialized, Object& syncLock)
   at MvcApplication5.Filters.InitializeSimpleMembershipAttribute.OnActionExecuting(ActionExecutingContext filterContext) in c:\Users\max\Documents\Visual Studio 2012\Projects\MvcApplication2\MvcApplication5\Filters\InitializeSimpleMembershipAttribute.cs:line 21
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<>c__DisplayClass3b.<BeginInvokeActionMethodWithFilters>b__35()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain)
  InnerException: System.InvalidOperationException
       HResult=-2146233079
       Message=The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588
       Source=MvcApplication5
   StackTrace:
        at MvcApplication5.Filters.InitializeSimpleMembershipAttribute.SimpleMembershipInitializer..ctor() in c:\Users\max\Documents\Visual Studio 2012\Projects\MvcApplication2\MvcApplication5\Filters\InitializeSimpleMembershipAttribute.cs:line 45
   InnerException: System.Configuration.Provider.ProviderException
        HResult=-2146233088
        Message=The Role Manager feature has not been enabled.
        Source=System.Web
        StackTrace:
             at System.Web.Security.Roles.EnsureEnabled()
             at System.Web.Security.Roles.get_Provider()
             at WebMatrix.WebData.WebSecurity.InitializeProviders(DatabaseConnectionInfo connect, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables)
             at WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection(String connectionStringName, String userTableName, String userIdColumn, String userNameColumn, Boolean autoCreateTables)
             at MvcApplication5.Filters.InitializeSimpleMembershipAttribute.SimpleMembershipInitializer..ctor() in c:\Users\max\Documents\Visual Studio 2012\Projects\MvcApplication2\MvcApplication5\Filters\InitializeSimpleMembershipAttribute.cs:line 41
        InnerException: 

What could be wrong? Thanks for any hint,

Max

Community
  • 1
  • 1
Max
  • 643
  • 11
  • 27
  • Update: tried to resolve the exception via enabling the Role MNanager via . This helped to resolve the exception, but once a new user performs registration, I am getting the exception: To call this method, the "Membership.Provider" property must be an instance of "ExtendedMembershipProvider". – Max Sep 09 '13 at 11:12
  • Looks like the exceptions disappear, after implementing WebMatrix.WebData.SimpleMembershipProvider . ExtendedMembershipProvider was good for forms authentication, but not for OAuth (Facebook). – Max Sep 09 '13 at 12:31

1 Answers1

2

There could be a couple of items wrong here. First it does not look like you configuration for the membership provider is correct for the type attribute. You have:

type="MvcApplication2.Models.MyMembershipProvider"

The type should also include the assembly name like this:

type="MvcApplication2.Models.MyMembershipProvider, MvcApplication2"

Assuming that MvcApplication2 is the name of the assembly that contains your provider.

Also the SimpleMembership that is inserted into the base code for an MVC 4 Internet template uses some lazy initialization that looks from your error is being called. Be sure to remove the InitializeSimpleMembership attribute from the AccountController.

[Authorize]
[InitializeSimpleMembership] //Remove this attribute
public class AccountController : Controller
{

This causes SimpleMembership to initialize whenever you access actions on this controller. You can read more about removing this initialization here. This article also discusses how to customize SimpleMembership. You may want to look at that option rather than creating your own membership provider from scratch.

If you want to use SimpleMembership with your own provider inherit from SimpleMembershipProvider and configure it in the web.config.

<membership defaultProvider="SimpleMembershipProvider">
  <providers>
    <clear/>
    <add name="MySimpleMembershipProvider" type="MyNamespace.MySimpleMembershipProvider, MyAssembly" />
  </providers>
</membership>

If you need to initialize your database you can do so in the Global.asax Application_Start method.

Another issue may be that you do not have a role provider configured. Did you create your own custom role provider or are you trying to use the SimpleMembership role provider. If you are not using a role provider remove this entry from the web.config.

<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
  <providers>
    <clear/>
    <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
  </providers>
</roleManager>

And add this to your web.config

<system.webServer>
  ...
  <modules runAllManagedModulesForAllRequests="true">
    <!-- This makes sure the ASP.NET security pipeline does not use any role provider.-->
    <remove name="RoleManager" />
  </modules>
</system.webServer>
Kevin Junghans
  • 17,475
  • 4
  • 45
  • 62
  • Kevin, thanks. Actually, removing the "attribute" would require me to define a DB connection. Maybe I can describe my design goals: 1. Manage users in NoSQL store, accessible via driver, in a format of my choice. 2. Support forms-based and OAuth login from browser 3. Provide Web API to be consumed by the web app, in user context. This lead me to think I can take Forms and OAuth from MVC4 (without investing in Do It Yourself), and override the membership provider to work with my NoSQL data store format. Wrong way? Should I abandon MVC4? Thanks a lot. – Max Sep 09 '13 at 20:50
  • 1
    Why would removing the "attribute" require you to define a DB connection? I am not following your reasoning. MVC4 with forms authentication will work fine with any data store. The problems I am seeing are that you have not properly configured the system to use your providers and have not totally ripped out the old providers (SimpleMembership). What are you trying to reuse in MVC4 for OAuth? SimpleMembership? You also have the option of using your own data store for SimpleMembership by inheriting your provider from SimpleMembershipProvider instead of MembershipProvider. – Kevin Junghans Sep 10 '13 at 12:22
  • Thanks. I am on the right track to implement my own provider inherited from SimpleMembershipProvider . Appreciate your help. – Max Sep 11 '13 at 18:32
  • Actually, I tried to remove the RoleManager (I don't need it), and started getting exceptions about DB connections again. The question is what is the clean way to remove all the default DB connections generated by the "wizard", and use only my own data store connectivity implemented in a class inherited from SimpleMembershipProvider. – Max Sep 13 '13 at 09:57
  • I added some more information to my answer. Look at the last web.config changes; that may be your problem. I hope this helps. – Kevin Junghans Sep 13 '13 at 12:26