locked
Unable to cast object of type Microsoft.Crm.AUthentication.CrmWindowsIdentity to type System.Security.Principal.WindowsIdentity RRS feed

  • Question

  • Ok, so I've got a question, and its one I've been racking my brain on now for two days.  I'm hoping someone has ideas on this, because I'm all out.

    I have an asp.net webapp that uses the CRM Webservices to extend functionality.  Up till now, it had been set up on a separate server.  Let's say Server 1 is CRM, and server 2 is the webapp.  Everything has worked flawlessly, except we've been noticing some performance lag. 

    Believing part of this performance lag to be the constant passing of credentials from server 2 to server 1, we decided to move the webapp to server 1.  It is a .net framework 4.0 application and is in its own application pool.  Everything is configured the same as it was on server 2. 

    The problem is that whenever I try to open any page of the application, it blows up.  I get the following error.

    Unable to cast object of type 'Microsoft.Crm.Authentication.CrmWindowsIdentity' to type 'System.Security.Principal.WindowsIdentity'.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidCastException: Unable to cast object of type 'Microsoft.Crm.Authentication.CrmWindowsIdentity' to type 'System.Security.Principal.WindowsIdentity'.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.


    Stack Trace:

    [InvalidCastException: Unable to cast object of type 'Microsoft.Crm.Authentication.CrmWindowsIdentity' to type 'System.Security.Principal.WindowsIdentity'.]
    
     GF.CRMApp.GFCRMEntity.GetCRMServiceWithCRMImpersonator() in C:\GF Projects\GFCRM\Webapps\CRMAppIntegration2010\CRMAppIntegration\CRMAppIntegration\App_Code\GFCRMEntity.cs:282
    
     GF.CRMApp.GFCRMEntity.GetCRMService() in C:\GF Projects\GFCRM\Webapps\CRMAppIntegration2010\CRMAppIntegration\CRMAppIntegration\App_Code\GFCRMEntity.cs:114
    
     GF.CRMApp.SearchCRM.ExecuteSearch() in C:\GF Projects\GFCRM\Webapps\CRMAppIntegration2010\CRMAppIntegration\CRMAppIntegration\App_Code\SearchCRM.cs:202
    
     GF.CRMApp.SearchCRM.SearchOppStages() in C:\GF Projects\GFCRM\Webapps\CRMAppIntegration2010\CRMAppIntegration\CRMAppIntegration\App_Code\SearchCRM.cs:170
    
     GF.CRMApp.OpportunitySearch.GetPursuitStage() in C:\GF Projects\GFCRM\Webapps\CRMAppIntegration2010\CRMAppIntegration\CRMAppIntegration\OpportunitySearch.aspx.cs:206
    
     GF.CRMApp.OpportunitySearch.Page_Load(Object sender, EventArgs e) in C:\GF Projects\GFCRM\Webapps\CRMAppIntegration2010\CRMAppIntegration\CRMAppIntegration\OpportunitySearch.aspx.cs:26
    
     System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
    
     System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
    
     System.Web.UI.Control.OnLoad(EventArgs e) +91
    
     System.Web.UI.Control.LoadRecursive() +74
    
     System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207
    
    



    Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.1

    The problem is that this could works fine on the other server, so it has to be a problem on server 1, not a problem with the code used to create the CRMService object.

    Below is the code I'm using to create the CrmService object, like I said works fine on server 2.

    using (new Microsoft.Crm.Sdk.CrmImpersonator())
    
                {
    
                    HttpContext context = HttpContext.Current;
    
     
    
                    WindowsIdentity winId = (WindowsIdentity)context.User.Identity;
    
                    WindowsImpersonationContext ctx = null;
    
     
    
                    try
    
                    {
    
                        ctx = winId.Impersonate();
    
                        System.Net.NetworkCredential objDefCred = (System.Net.NetworkCredential)System.Net.CredentialCache.DefaultCredentials;
    
                        objService.Credentials = objDefCred;
    
                        objService.Url = {URL}
                         objService.PreAuthenticate = true;
    
     
    
                        CrmAuthenticationToken usertoken = new CrmAuthenticationToken();
    
                        usertoken.AuthenticationType = Constants.AuthenticationType.AD;
    
     
    
                        usertoken.OrganizationName = {OrganizationName}
     
    
                        objService.CrmAuthenticationTokenValue = usertoken;
    
                    }
    
                    catch (SoapException ex)
    
                    {
    
                        throw ex;
    
                    }
    
                    finally
    
                    {
    
                        if (ctx != null)
    
                        {
    
                            ctx.Undo();
    
                        }
    
                    }
    
                }
    Help!

    Monday, May 2, 2011 8:18 PM

Answers

  • A couple of things look a little strange:

    • It's stated that this is a .Net 4.0 application, but the code uses the classes (CrmAuthenticationToken, CrmImpersonator) from the Crm 4 SDK assemblies, which are .Net 2.0 assemblies. Which version of CRM is being targetted ?
    • I don't see the need for the CrmImpersonator class in this code, with the way it's deployed. CrmImpersonator allows you to use the ExtractCrmAuthenticationToken method, but ExtractCrmAuthenticationToken is not used in this code, and ExtractCrmAuthenticationToken only works if the code runs in the CrmAppPool. I see no need to use CrmImpersonator, and I think this is actually the cause of the problem

    I expect the underlying issue is that a CRM HttpModule (I think its CrmAuthentication) modifies the HttpContext.User object (probably to a CrmWindowsIdentity type). This HttpModule is registered in the web.config of the CRM web site. So, if the code has been moved from a location outside of the CRM website (which won't have this HttpModule), to a location within the CRM website (where the HttpModule is inherited), then this would explain the behaviour described.

    If the configuration is as I described, then the simplest solution would be to unregister the CrmAuthentication HttpModule in the local web.config. This won't reduce any functionality, as you're not making use of CrmImpersonator

    For some related information, see http://mscrmuk.blogspot.co.uk/2010/11/how-to-use-impersonation-in-asp-net.html


    Microsoft CRM MVP - http://mscrmuk.blogspot.com  http://www.excitation.co.uk


    Friday, May 18, 2012 8:26 AM
    Moderator

All replies

  • No code was changed correct? You also say this worked when it was on a different server?  I just want to confirm a couple things.  Is the app pool settings for your new app pool set to .NET 4.0 along iwth your website?
    Jamie Miley
    http://mileyja.blogspot.com
    Linked-In Profile
    Follow Me on Twitter!
    Monday, May 2, 2011 8:44 PM
    Moderator
  • Tuesday, May 3, 2011 11:22 AM
  • Yes there was no code change at all from server 2 to the CRM server.  The application pool is set for 4.0 on both server. 
    Tuesday, May 3, 2011 7:15 PM
  • I don't see how this will help.
    Tuesday, May 3, 2011 7:16 PM
  • I had the same situation with my application and CRM.

    error comes from  WindowsIdentity winId = (WindowsIdentity)context.User.Identity; as it shown in error

    try code below

    IntPtr userHandle = IntPtr.Zero();
    bool loggedOn = LogonUser(user,domain,password,LogonType.Interactive,LogonProvider.Default,out userHandle);
    if(!loggedOn)
        throw new Win32Exception(Marshal.GetLastWin32Error());

    // Begin impersonating the user
    WindowsImpersonationContext impersonationContext = WindowsIdentity.Impersonate(userHandle.Token);
    try
    {
     DoWhateverYouWantWhileImpersonating();
    }
    catch()
    {
    }
    Finally
    {
     impersonationContext.Undo();
    }

    Friday, May 13, 2011 4:45 PM
  • Thursday, May 17, 2012 7:07 PM
    Moderator
  • A couple of things look a little strange:

    • It's stated that this is a .Net 4.0 application, but the code uses the classes (CrmAuthenticationToken, CrmImpersonator) from the Crm 4 SDK assemblies, which are .Net 2.0 assemblies. Which version of CRM is being targetted ?
    • I don't see the need for the CrmImpersonator class in this code, with the way it's deployed. CrmImpersonator allows you to use the ExtractCrmAuthenticationToken method, but ExtractCrmAuthenticationToken is not used in this code, and ExtractCrmAuthenticationToken only works if the code runs in the CrmAppPool. I see no need to use CrmImpersonator, and I think this is actually the cause of the problem

    I expect the underlying issue is that a CRM HttpModule (I think its CrmAuthentication) modifies the HttpContext.User object (probably to a CrmWindowsIdentity type). This HttpModule is registered in the web.config of the CRM web site. So, if the code has been moved from a location outside of the CRM website (which won't have this HttpModule), to a location within the CRM website (where the HttpModule is inherited), then this would explain the behaviour described.

    If the configuration is as I described, then the simplest solution would be to unregister the CrmAuthentication HttpModule in the local web.config. This won't reduce any functionality, as you're not making use of CrmImpersonator

    For some related information, see http://mscrmuk.blogspot.co.uk/2010/11/how-to-use-impersonation-in-asp-net.html


    Microsoft CRM MVP - http://mscrmuk.blogspot.com  http://www.excitation.co.uk


    Friday, May 18, 2012 8:26 AM
    Moderator