Saturday, February 22, 2014

OrganizationServiceProxy in CRM 2011/2013 Plugins to use Early binding.


CRM 2011/2013 had an option to create a plugins using Early binding or Late bindings.

If late binding is used, then the attributes values should be hardcoded or create a constant class that contains the attribute names to achieve it.

Early bound classes will contains the objects of entities in which it can be used to do the CRUD operation etc. and there is no need of hardcoding the attribute names. There are advantages and disadvantages working with Early and Late binding. But I am not going to explain in this blog. The below blogs will gives more information on overview, differences and how to use it.



To use early bound types in a CRM2011 plugin and enable this, It should either be add a ProxyTypesBeavior(), or set .EnableProxyTypes. However, both of these properties apply to an OrganizationServiceProxy class, and do not exist on the IOrganizationService interface.

So if it uses IOrganizationService and try to do the CRM transactions like the below, it fails in the highlighted red color  in the bewlow example with an error “Attribute regardingobjecttypecode must not be NULL if attribute regardingobjectid is not NULL

protected void ExecuteTestPlugin(LocalPluginContext localContext)
        {
            if (localContext == null)
            {
                throw new ArgumentNullException("localContext");
            }

            IPluginExecutionContext context = localContext.PluginExecutionContext;
            IOrganizationService service = localContext.OrganizationService;
            XrmServiceContext sContext = new XrmServiceContext (service);
            Opportunity opportunity = ((Entity)context.InputParameters["Target"]).ToEntity< XrmServiceContext >();


            try
            {
                //to do business logic
Opportunity opp = new Opportunity()
                {
                    Name = “bla  bla bla”,
                    OpportunityId = opportunityClose.OpportunityId.Id
                };
                service.Update(opp);//Fail in this part
            }
            catch (FaultException<OrganizationServiceFault> e)
            {
                new InvalidPluginExecutionException("Error Test Plugin : " + e);
                throw;
            }
            catch (Exception e)
            {
                new InvalidPluginExecutionException("Error Test Plugin : " + e);
                throw;
            }

        }


To avoid this error, there is a below work around which will work like a charm.
If the Plugin project created using Developer tool kit, then in the “Plugin.cs” class, the below highlighted code should be added.

   internal LocalPluginContext(IServiceProvider serviceProvider)
            {
                if (serviceProvider == null)
                {
                    throw new ArgumentNullException("serviceProvider");
                }

                // Obtain the execution context service from the service provider.
                this.PluginExecutionContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

                // Obtain the tracing service from the service provider.
                this.TracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

                // Obtain the Organization Service factory service from the service provider
                IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                factory.GetType().GetProperty("ProxyTypesAssembly").SetValue(factory, typeof(XrmServiceContext).Assembly, null);

                // Use the factory to generate the Organization Service.
                this.OrganizationService = factory.CreateOrganizationService(this.PluginExecutionContext.UserId);
               
            }

Happy Coding :) 

No comments:

Post a Comment