Problems with custom membershipProvider and MultiplexingRoleProvider

Vote:
 

Hi!

I have made a custom MembershipProvider and a custom RoleProvider which authenticate against a simple user and role xml file (only for develop purpose. My plan is to work against a non-AD ldap).

Authentications/login works fine on my CMS 5 (5.2.375.7) if I, in web.config, set default provider = "myCustomMembershipProvider" in <roleManager> and defaultProvider="myCustomRoleProvider" in <membership>. But in this way I can't login with default windows account. If a change defaultProvider to WindowsMembershipProvider I manage to login with my windows account but using my customProvider account will fail. So I thought I could use the MultiplexingRoleProvider like this in <roleManager>:

<add name="MultiplexingRoleProvider" type="EPiServer.Security.MultiplexingRoleProvider, EPiServer" provider1="WindowsRoleProvider" provider2="myCustomRoleProvider" providerMap1="WindowsMembershipProvider" providerMap2="myCustomMembershipProvider" />
         
It works for me using the windows account but my application will throw System.StackOverFlowExeption when I try with a user from my custom source.

Am I on the wrong track when the custom myCustomMembershipProvider derive from system.web.security.MembershipProvider and myCustomRoleProvider from system.web.security.myCustomRoleProvider?

Any suggestions?

#25509
Oct 28, 2008 17:21
jo
Vote:
 

Hi Örjan!

Youre on the right track deriving from Membership/Role-provider, the problem is caused by some logic error in the code, probably an infinite recursion.

This should be easy to spot by looking at the callstack, so if you could please post it (the callstack), someone here could probably point to the problem?

Regards,
johan

 

#25522
Oct 29, 2008 1:26
Vote:
 

Thanks Johan!

The problem is I can't debug the assembly, even if I try to attach aspnet_wp.exe to the process or set the project to debug VS 2008 tells me:

The following module was built either with optimizations enabled or without debug information:
C:\WINDOWS\assembly\GAC_MSIL\CustomMembershipProvicers\1.0.0.0__dbdc5ebfa03522a7\CustomMembershipProviders.dll

When I run the site (using default provider MultiplexingMembershipProvider and useid from my custom provider) gives me output:

An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll

With same config the windows account works fine. Just to make it clear I can use my custom provider if in web.config I change default provider to my own provider.

Does anyone have an idea how I can trace my custom membership provider .dll?

#25691
Oct 31, 2008 11:06
Vote:
 

Use a decompiler and add the decompiled project into your solution, that has saved me quite a few times.

Take a look here: http://www.red-gate.com/products/reflector/index.htm

#25701
Oct 31, 2008 19:55
jo
Vote:
 

Hi Örjan!

Dont you get the callstack trace included with the error on the error page?

/johan

#25704
Nov 02, 2008 22:11
Vote:
 

Nope! The only error page I get is a 500 message:

Server Application Unavailable - The web application you are attempting to access on this web server is currently unavailable.  Please hit the "Refresh" button in your web browser to retry your request.

I can see that the MultiplexingMembershipProvider include my custom provider, so this will work:

if(Membership.Providers["MyCustomMembershipProvider"].ValidateUser("foo", "test"))
        Response.Write("Validated!");
else   
        Response.Write("NOT validated!");

The event viewer says error for .net runtime 2.0, system.stackoverflowexeption. My log4net doesn't give me anything. I'm not that experienced when it comes to debugging and OO so please forgive me if my line of reasoning is a little bit limited.

Maybe the MultiplexingMembershipProvider expect a certain interface or member which I haven't included in my custom provider class. I am going to dig deeper into that.

Thanks Johan and Espen for helping me out.

#25710
Nov 03, 2008 10:42
jo
Vote:
 

Hi Örjan!

No, the multiplexingprovider doesnt expect any other "interface" than the MembershipProvider baseclass.

The one "odd" thing with it is that it in its implementation of ValidateUser() first calls into the custom membershipprovider's GetUser(username)-implementation *before* calling into the ValidateUser().

So, how's your GetUser(username)-implementation look like? Can you test your implementation of GetUser(username) explicitly like you do with ValidateUser()?

/johan

#25715
Nov 03, 2008 12:04
Vote:
 

Hi Johan! 

Yep! The method works fine. For example:

Response.Write(Membership.Providers["MyCustomMembershipProvider"].GetUser("foo", false).ProviderName.ToString());

Also when I pass the object providerUserKey instead of the username string I get a nice result without overflow exception.

#25723
Nov 03, 2008 14:24
jo
Vote:
 

Hi Örjan!

I think that you'll need the debugger to fix this. Can you remove the assembly from the GAC, recompile it using DEBUG flag and put it and the accompanying .pdb into the /bin folder instead and then reproduce the error.

Also make sure that <compilation debug="TRUE" /> and <customErrors  mode="off" /> in web.config.

You should see a stacktrace in the errorpage now...

Another option is to install debugging tools for windows, and then run adplus with a configuration file to catch CLR exceptions, then reproduce the error and then use windbg to inspect the exception and the faulting threads callstack.

As the second alternative requires some experience with windbg and sos.dll, I'd really suggest you to get the VisualStudio debugger running.

/johan

#25743
Nov 03, 2008 23:23
Vote:
 

Thanks Johan! That really worked. I remove my assembly from the GAC and after that I could debug much better.

I found out that I made an annoying mistake. In my GetUser (which is called before ValidateUser) I returned a nice MemberShipUser, but instead of using
my custom membershipproviders name I used Membership.Provider.Name.

public override MembershipUser GetUser(string username, bool userIsOnline) 
{
MembershipUser MyMemberShipUser = null;
...
MyMemberShipUser = new MembershipUser(Membership.Provider.Name, ...
...
}

Of course the Membership.Provider.Name gives me the defaultProvider (defined in web.config) "MultiplexingMembershipProvider". = system.stackoverflowexeption.

I just change MyMemberShipUser = new MembershipUser("MyCustomMembershipProvider", ...

That's why my custom provider works when I used it as a defaultProvider.

Your suggestions about windbg and sos was really good. I started out here:
http://support.microsoft.com/kb/892277
http://world.episerver.com/en/Articles/Items/Debugging-EPiServer-CMS-5-R2/

 

#25758
Nov 04, 2008 14:44
jo
Vote:
 

Hi Örjan!

Im pleased to hear that it worked out ok for you!

/johan

 

#25764
Nov 04, 2008 16:58