0
votes

I have a Plugin that updates a field on the Entity which triggers the update also. I am trying to check if Status is changed to 'Scheduled' and saved, then certain document types must exist in Sharepoint. The data from Sharepoint is retrieve without any delay. The prob is Plugin takes too long OR throws an error : UnhandledException:System.ServiceModel.FaultException: Need to start a transaction before commitDetail: ErrorCode:-2147220911

Please see the code provided and help me...

void IPlugin.Execute(IServiceProvider serviceProvider) { IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); if(context.MessageName != "Update") return;

        Entity targetEntity = context.InputParameters["Target"] as Entity;
        if(targetEntity.LogicalName != "new_Smiley")
            return;

        //if(context.Depth > 1)
        //    return;

        ITracingService _TracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
        IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

        try {
            _TracingService.Trace("About to Retrieve Smiley entity");
            Entity _Smiley = service.Retrieve("new_Smiley", targetEntity.Id, new ColumnSet(
                            "new_applicationtonew_Smileyid",
                            "new_new_Smileyidnumber",
                            "new_status",
                            "new_ppoSmileyid"
                        ));

            var Smiley_AppId = _Smiley.GetAttributeValue<EntityReference>("new_applicationtonew_Smileyid");
            if(Smiley_AppId == null)
                return;
            var SmileyId = _Smiley.GetAttributeValue<string>("new_new_Smileyidnumber");
            var SmileyStatus = _Smiley.GetAttributeValue<OptionSetValue>("new_status").Value;
            //if(!(SmileyStatus == 649770001 || new_SmileyStatus == 649770000)) {
            //    return;
            //}
            //var PPOId = _Smiley.GetAttributeValue<EntityReference>("new_ppoSmileyid").Name;
            var PPOGuid = _Smiley.GetAttributeValue<EntityReference>("new_ppoSmileyid").Id;
            _TracingService.Trace("About to Retrieve entity");
            Entity _PPO = service.Retrieve("new_ppo", PPOGuid, new ColumnSet("new_pathwayselected"));
            var PPOPathway = _PPO.GetAttributeValue<OptionSetValue>("new_pathwayselected").Value;

            _TracingService.Trace("Retrieved Smiley entity {0}...", SmileyId);
            GetSPList spList = new GetSPList();
            var liSPDocTypes = spList.GetList(SmileyId);
            foreach(var item in liSPDocTypes) {
                _TracingService.Trace(item + " ;");
            }

            Entity PreImage = (Entity)context.PreEntityImages["PreUpdateImage"];
            //Entity PostImage = (Entity)context.PostEntityImages["PostEntityImage"];
            //if(PostImage.Contains("new_status")) {
                //throw new InvalidPluginExecutionException(PreImage.GetAttributeValue<OptionSetValue>("new_status").Value.ToString() + "_" + PostImage.GetAttributeValue<OptionSetValue>("new_status").Value.ToString());
            //}

            var liJODocTypes = new List<string>() { "Type1", "Type2", "Type3", "Type4" };
            var liScopeDocTypes = new List<string>() { "Type5", "Type6", "Type7", "Type8" };

            if(SmileyStatus == 649770001) {
                foreach(var doctype in liJODocTypes) {
                    //if(liSPDocTypes.Contains(doctype) && (PPOPathway == 100000000 || PPOPathway == 649770000 || PPOPathway == 100000001)) {
                    if(liSPDocTypes.Contains(doctype)) {
                        service.Update(_Smiley);
                    }
                    else {
                        throw new InvalidPluginExecutionException();
                    }
                }
            }

            //if(context.Depth > 1)
            //    return;
        }

        catch(InvalidPluginExecutionException ex) {
            _TracingService.Trace("{0}", ex.ToString() + "_" + ex.StackTrace + " Error by Tracing Service");
            throw new InvalidPluginExecutionException("Please upload all required documents...");
        }
        catch(FaultException<OrganizationServiceFault> ex) {
            _TracingService.Trace("The application terminated with an error.");
            _TracingService.Trace("Timestamp: {0}", ex.Detail.Timestamp);
            _TracingService.Trace("Code: {0}", ex.Detail.ErrorCode);
            _TracingService.Trace("Message: {0}", ex.Detail.Message);
            _TracingService.Trace("Inner Fault: {0}",
                null == ex.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault");
        }
        catch(TimeoutException ex) {
            _TracingService.Trace("The application terminated with an error.");
            _TracingService.Trace("Message: {0}", ex.Message);
            _TracingService.Trace("Stack Trace: {0}", ex.StackTrace);
            _TracingService.Trace("Inner Fault: {0}",
                null == ex.InnerException.Message ? "No Inner Fault" : ex.InnerException.Message);
        }
        catch(Exception ex) {
            _TracingService.Trace("Update: {0}", ex.ToString() + ex.StackTrace);
        }
    }
}

In Plugin registration tool, i have registered the Plugin for Event: Pre-operation(CRM 2011), Synchronous.

I might be doing something wrong.Please suggest if i have to use PreImages or incorrectly registering the plugin. Let me know if more info is needed... Thank you!

1
What kind of object is GetSPList ? Does it access CRM or remote resources?Henk van Boeijen
GetSPList is getting doc types(ex: Lease agreement, Contract, ...) as a list from a column in Sharepoint using it's web services.hungryjackers
Could it be it times out on that operation? (B.t.w. does your plugin maintain state, i.e. does it have fields?)Henk van Boeijen
I used a console app and it is fast when retrieving from Sharepoint. Plugin works as long it is not hitting service.update. I have solved the prob and it is more on the logical side. I am using a PostImage to check the status value and if required doc types are uploaded then do nothing(no service.update.. let the service call pass) and if req docs are missing then throw new InvalidPluginExecutionException("Please check some docs are missing..."); Thank you Henk.. you always show up for CRM questions :)hungryjackers

1 Answers

0
votes

In a plugin this is going to be problematic code:

catch(FaultException<OrganizationServiceFault> ex) {
        _TracingService.Trace("The application terminated with an error.");
        _TracingService.Trace("Timestamp: {0}", ex.Detail.Timestamp);
        _TracingService.Trace("Code: {0}", ex.Detail.ErrorCode);
        _TracingService.Trace("Message: {0}", ex.Detail.Message);
        _TracingService.Trace("Inner Fault: {0}",
            null == ex.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault");
    }

When your code swallows a FaultException it breaks the transaction and will usually - I would say always - result in that error.

You need to look at the tracing detail you are capturing to see what is causing the initial FaultException.

In my generic error handling code that I use for plugins I always throw an InvalidPluginExecutionException after catching a FaultException since once it has occurred there is little chance of the transaction completing successfully.