I need to connect and retrieve records in CRM Online through CRM 365 plugin. I have tried simplified connection using xrm.tooling.dll
but unfortunately it says Could not load file or assembly 'microsoft.xrm.tooling.connector
and when i used ClientCredential
the error says Metadata contain refereces that cannot be resolved
.
Strangely, i tried both method with console applcation and it's work prefectly. Just wanna knows what i miss in this case ? Do i need special requirement when i want to connect to CRM through plugin ? Please anybody share your knowledge.
EDIT
This just a sample code to get account name from CRM Online and display it using InvalidPluginExecutionException:
IOrganizationService _service;
public void Execute(IServiceProvider serviceprovider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceprovider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory servicefactory = (IOrganizationServiceFactory)serviceprovider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity ent = (Entity)context.InputParameters["Target"];
if (ent.LogicalName != "opportunity")
return;
string connstring = @"Url=https://office.crm5.dynamics.com; Username=username@office.onmicrosoft.com; Password=crmoffice; authtype=Office365";
CrmServiceClient conn = new Microsoft.Xrm.Tooling.Connector.CrmServiceClient(connstring);
service = (IOrganizationService)conn.OrganizationWebProxyClient != null ? (IOrganizationService)conn.OrganizationWebProxyClient :
(IOrganizationService)conn.OrganizationServiceProxy;
try
{
Guid fabercastel = new Guid("efd566dc-10ff-e511-80df-c4346bdcddc1");
Entity _account = new Entity("account");
_account = service.Retrieve(_account.LogicalName, fabercastel, new ColumnSet("name"));
string x = _account["name"].ToString();
throw new InvalidPluginExecutionException("Result of Query : " + x);
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException(ex.Message);
}
You should be able to connect to another CRM instance without using any assemblies that are outside Online Sandbox (so other than Microsoft.Xrm.Sdk and related). Simply use the sample from SDK from "SDK\SampleCode\CS\GeneralProgramming\Authentication\AuthenticateWithNoHelp\AuthenticateWithNoHelp.cs". Simplified version for connecting to Office365 looks like that:
class AuthenticateWithNoHelp
{
private String _discoveryServiceAddress = "https://disco.crm.dynamics.com/XRMServices/2011/Discovery.svc";
private String _organizationUniqueName = "orgname";
private String _userName = "admin@orgname.onmicrosoft.com";
private String _password = "password";
private String _domain = "domain";
public void Run()
{
IServiceManagement<IDiscoveryService> serviceManagement =
ServiceConfigurationFactory.CreateManagement<IDiscoveryService>(
new Uri(_discoveryServiceAddress));
AuthenticationProviderType endpointType = serviceManagement.AuthenticationType;
AuthenticationCredentials authCredentials = GetCredentials(serviceManagement, endpointType);
String organizationUri = String.Empty;
using (DiscoveryServiceProxy discoveryProxy =
GetProxy<IDiscoveryService, DiscoveryServiceProxy>(serviceManagement, authCredentials))
{
if (discoveryProxy != null)
{
OrganizationDetailCollection orgs = DiscoverOrganizations(discoveryProxy);
organizationUri = FindOrganization(_organizationUniqueName,
orgs.ToArray()).Endpoints[EndpointType.OrganizationService];
}
}
if (!String.IsNullOrWhiteSpace(organizationUri))
{
IServiceManagement<IOrganizationService> orgServiceManagement =
ServiceConfigurationFactory.CreateManagement<IOrganizationService>(
new Uri(organizationUri));
AuthenticationCredentials credentials = GetCredentials(orgServiceManagement, endpointType);
using (OrganizationServiceProxy organizationProxy =
GetProxy<IOrganizationService, OrganizationServiceProxy>(orgServiceManagement, credentials))
{
organizationProxy.EnableProxyTypes();
Guid userid = ((WhoAmIResponse)organizationProxy.Execute(
new WhoAmIRequest())).UserId;
}
}
}
private AuthenticationCredentials GetCredentials<TService>(IServiceManagement<TService> service, AuthenticationProviderType endpointType)
{
AuthenticationCredentials authCredentials = new AuthenticationCredentials();
authCredentials.ClientCredentials.UserName.UserName = _userName;
authCredentials.ClientCredentials.UserName.Password = _password;
return authCredentials;
}
public OrganizationDetailCollection DiscoverOrganizations(
IDiscoveryService service)
{
if (service == null) throw new ArgumentNullException("service");
RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();
RetrieveOrganizationsResponse orgResponse =
(RetrieveOrganizationsResponse)service.Execute(orgRequest);
return orgResponse.Details;
}
public OrganizationDetail FindOrganization(string orgUniqueName,
OrganizationDetail[] orgDetails)
{
if (String.IsNullOrWhiteSpace(orgUniqueName))
throw new ArgumentNullException("orgUniqueName");
if (orgDetails == null)
throw new ArgumentNullException("orgDetails");
OrganizationDetail orgDetail = null;
foreach (OrganizationDetail detail in orgDetails)
{
if (String.Compare(detail.UrlName, orgUniqueName,
StringComparison.InvariantCultureIgnoreCase) == 0)
{
orgDetail = detail;
break;
}
}
return orgDetail;
}
private TProxy GetProxy<TService, TProxy>(
IServiceManagement<TService> serviceManagement,
AuthenticationCredentials authCredentials)
where TService : class
where TProxy : ServiceProxy<TService>
{
Type classType = typeof(TProxy);
if (serviceManagement.AuthenticationType !=
AuthenticationProviderType.ActiveDirectory)
{
AuthenticationCredentials tokenCredentials =
serviceManagement.Authenticate(authCredentials);
return (TProxy)classType
.GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(SecurityTokenResponse) })
.Invoke(new object[] { serviceManagement, tokenCredentials.SecurityTokenResponse });
}
return (TProxy)classType
.GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(ClientCredentials) })
.Invoke(new object[] { serviceManagement, authCredentials.ClientCredentials });
}
static public void Main(string[] args)
{
AuthenticateWithNoHelp app = new AuthenticateWithNoHelp();
app.Run();
}
}
You can simplify it further by removing part with DiscoveryService and directly calling:
https://orgname.api.crm.dynamics.com/XRMServices/2011/Organization.svc
This should work on Sandboxed plugins as it uses only Sdk assemblies.
You already have your connection to CRM using the IOrganizationService that you've defined on the third line of your plugin. Unless you need to connect to another CRM instance in a different org, there is no login needed or required.
Basically just delete the 4 lines above your try, and you should be good.
Edit:
public void Execute(IServiceProvider serviceprovider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceprovider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory servicefactory = (IOrganizationServiceFactory)serviceprovider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = servicefactory.CreateOrganizationService(context.UserId);
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
Entity ent = (Entity)context.InputParameters["Target"];
if (ent.LogicalName != "opportunity")
return;
Guid fabercastel = new Guid("efd566dc-10ff-e511-80df-c4346bdcddc1");
Entity _account = new Entity("account");
_account = service.Retrieve(_account.LogicalName, fabercastel, new ColumnSet("name"));
string x = _account["name"].ToString();
throw new InvalidPluginExecutionException("Result of Query : " + x);
}
}
You do not need any additional libraries like Microsoft.Xrm.Tooling.Connector or others from SDK to consume CRM web services. Standard .NET mechanism related to SOAP / REST protocols will be enough (but of course this method may be little more difficult).
EDIT: I've made some additional investigation and it occurs that configuring auto-generated OrganizationServiceClient for Office365 authentication without using SDK libraries may be real pain in the ass. I'm not telling it is not possible however it is not documented by Microsoft. To add more details OAuth authentication is not supported by Visual Studio generated proxy classes.
Because of that - my second recommendation is to use facade web service communicating with CRM OnLine. You may host this web service on Windows Azure or any other cloud/hosting place in the internet. From your CRM 365 Plugin you may consume your custom web service methods and communicate with your CRM Online instance using this service. I suppose it will be much better approach that trying to run undocumented methods of connecting to CRM Online.**