SP2010: BCS issue; CalculatePermissionsForCurrentThread

This probably is the last post in my latest BCS series for now, since our project is almost finished 🙂 One of the last hurdles I had to take was an error which only occured in our production environment for some reason (I guess production and test still aren’t similar enough). It occurred when trying to get a single BCS entity in code and had something to do with the permissions not being valid.

Here’s the code I used to get the entity:

BdcService bdcService = SPFarm.Local.Services.GetValue<BdcService>();
SPServiceApplication serviceApp = bdcService.Applications.Where(a => a.Name == bcsServiceAppName).First();

SPServiceContext context = SPServiceContext.GetContext(serviceApp.ServiceApplicationProxyGroup, SPSiteSubscriptionIdentifier.Default);
IMetadataCatalog catalog = bdcService.GetDatabaseBackedMetadataCatalog(context);

Microsoft.BusinessData.MetadataModel.IEntity entity = catalog.GetEntity(entitySchema, entityName);

// just get the first lobSystemInstance, there won't be more then one
ILobSystemInstance LobSysteminstance = entity.GetLobSystem().GetLobSystemInstances()[0].Value;

IEntityInstance entityinst = entity.FindSpecific(new Microsoft.BusinessData.Runtime.Identity(identifiers), LobSysteminstance);

Ok so that wasn’t working. It was instead giving me this error:

Microsoft.SharePoint.SPException: Cannot complete this action.  Please try again. ---> System.Runtime.InteropServices.COMException (0x80004005): Cannot complete this action.  Please try again.     
 at Microsoft.SharePoint.Library.SPRequestInternalClass.CalculatePermissionsForCurrentThread(Object& pvarAcl, Boolean bOnlyAces, UInt64& pPermGrant, UInt64& pPermDeny, Boolean& pbIsSiteAdmin, Boolean& pbIsSiteAuditor)     
 at Microsoft.SharePoint.Library.SPRequest.CalculatePermissionsForCurrentThread(Object& pvarAcl, Boolean bOnlyAces, UInt64& pPermGrant, UInt64& pPermDeny, Boolean& pbIsSiteAdmin, Boolean& pbIsSiteAuditor)     - 
 -- End of inner exception stack trace ---     
 at Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)     
 at Microsoft.SharePoint.Library.SPRequest.CalculatePermissionsForCurrentThread(Object& pvarAcl, Boolean bOnlyAces, UInt64& pPermGrant, UInt64& pPermDeny, Boolean& pbIsSiteAdmin, Boolean& pbIsSiteAuditor)     
 at Microsoft.SharePoint.Administration.SPAcl`1.CalculatePermissions()     
 at Microsoft.SharePoint.BusinessData.Infrastructure.BdcAccessControlList.AccessCheck(BdcRights rights)     
 at Microsoft.SharePoint.BusinessData.Runtime.DataClassRuntime.ExecuteInternal(IDataClass thisDataClass, ILobSystemInstance lobSystemInstance, ILobSystem lobSystem, IMethodInstance methodInstanceToExecute, IMethod methodToExecute, IParameterCollection nonReturnParameters, Object[]& overrideArgs)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.ExecuteInternal(IDataClass thisDataClass, ILobSystemInstance lobSystemInstance, ILobSystem lobSystem, IMethodInstance methodInstanceToExecute, IMethod methodToExecute, IParameterCollection nonReturnParameters, Object[]& overrideArgs, IFilterCollection filters)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.FindSpecific(IEntity thisEntity, Identity entityInstanceIdentity, String specificFinderName, ILobSystemInstance lobSystemInstance)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.FindSpecific(IEntity thisEntity, Identity entityInstanceIdentity, String specificFinderName, ILobSystemInstance lobSystemInstance, OperationMode mode)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.FindSpecific(IEntity this, Identity identifierValue, ILobSystemInstance lobSystemInstance, OperationMode operationMode, Boolean readNow)     
 at Microsoft.SharePoint.BusinessData.MetadataModel.Static.Entity.FindSpecific(Identity identity, ILobSystemInstance lobSystemInstance)    

And when running elevated, it changed to:

Access Denied for User 'CONTOSO\\spservice', which may be an impersonation by 'CONTOSO\\spservice'. Securable MethodInstance with Name 'GetSingleObjectEntityByID' denied access. Stack Trace:    
 at Microsoft.SharePoint.BusinessData.Runtime.DataClassRuntime.ExecuteInternal(IDataClass thisDataClass, ILobSystemInstance lobSystemInstance, ILobSystem lobSystem, IMethodInstance methodInstanceToExecute, IMethod methodToExecute, IParameterCollection nonReturnParameters, Object[]& overrideArgs)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.ExecuteInternal(IDataClass thisDataClass, ILobSystemInstance lobSystemInstance, ILobSystem lobSystem, IMethodInstance methodInstanceToExecute, IMethod methodToExecute, IParameterCollection nonReturnParameters, Object[]& overrideArgs, IFilterCollection filters)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.FindSpecific(IEntity thisEntity, Identity entityInstanceIdentity, String specificFinderName, ILobSystemInstance lobSystemInstance)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.FindSpecific(IEntity thisEntity, Identity entityInstanceIdentity, String specificFinderName, ILobSystemInstance lobSystemInstance, OperationMode mode)     
 at Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime.FindSpecific(IEntity this, Identity identifierValue, ILobSystemInstance lobSystemInstance, OperationMode operationMode, Boolean readNow)     
 at Microsoft.SharePoint.BusinessData.MetadataModel.Static.Entity.FindSpecific(Identity identity, ILobSystemInstance lobSystemInstance) 

Ok. So to cut a very long story short: i tried A LOT of different things with permissions, different code snippets, you name it. And after too much time, I finally found the solution. Which is not in the FindSpecific call itself (which you would expect), but much earlier when retrieving the metadata catalog. I’m now using the following method:

    private IEntityInstance GetBCSEntity(SPWebApplication application, string bcsServiceProxyName, string entitySchema, string entityName, object[] identifiers)
    {
      // retrieve the BDC (BCS) proxy 
      BdcServiceApplicationProxy proxy = (BdcServiceApplicationProxy)application.ServiceApplicationProxyGroup.Proxies.Single(p => p.DisplayName == bcsServiceProxyName);

      IMetadataCatalog catalog = proxy.GetDatabaseBackedMetadataCatalog();

      // fetches the entity (not an instance, but the model itself)
      Microsoft.BusinessData.MetadataModel.IEntity entity = catalog.GetEntity(entitySchema, entityName);

      // just get the first lobSystemInstance, there won't be more then one
      ILobSystemInstance LobSysteminstance = entity.GetLobSystem().GetLobSystemInstances()[0].Value;

      // execute the FindSpecific method to find our entity and then return it
      return entity.FindSpecific(new Microsoft.BusinessData.Runtime.Identity(identifiers), LobSysteminstance);
    }

I’m sorry I can’t really clarify what’s the difference between the two (they receive the same catalog as far as I know), but the second one works. One little tip: you probably do need to run this elevated because your normal user won’t have enough rights in the BCS app to query the model / services like this (if it does; it really shouldn’t).

, ,

Related posts

Latest posts

Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *