I have a BCS model which is causing problems in the production environment. Everything works fine from within SharePoint context, but outside the context (a WCF service to be precise) I'm getting errors pointing that my account has insufficient rights. Here's the 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)
So it's checking to see wether the current account (I assume) has access, and decides that it doesn't. But I made sure that the account under which the service (app pool) runs has sufficient rights in the BCS service application. I even triple checked by adding all authenticated users and giving them full permissions, it still isn't working.
When I change my code to being elevated, the following is thrown:
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 there's an access denied problem allright. But why? I am 100% sure that the BCS rights are set correctly. Perhaps they can't be read correctly or something, I'm stuck.
The BCS model is a .NET assembly which uses Linq to query a SQL database. I'm not using SQL directly because I need to add filtering in the .NET class.
For more info, here are some code snippets (pulled from different classes, so the variable names might not add up):
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);