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
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?
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
Hi Örjan!
Dont you get the callstack trace included with the error on the error page?
/johan
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.
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
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.
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
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/
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?