Strange Behavior CRM 2011 Plugin

I registered a plugin for our product quotes. The plugin worked well in our test environment. I have tested this many times. Then registered the plugin on the main server. However, the following scenario occurs: When I create or update a quotation product, the product form is first issued with a quote:

enter image description here

After I click on the quotation mark form, an error appears. Log files are not available (as you see). I debugged the plugin, but there is no error either. After I click OK, the error will disappear and the required business will occur in the product quotes (for the tax field). It means that the plugin code has no errors and does its job well. The code looks like this:

using System; using System.Diagnostics; using System.Linq; using System.ServiceModel; using Microsoft.Xrm.Sdk; using Xrm; using System.Collections.Generic; using Microsoft.Xrm.Sdk.Deployment; public class Plugin : IPlugin { public void Execute(IServiceProvider serviceProvider) { IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); Entity entity; if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { entity = (Entity)context.InputParameters["Target"]; if (entity.LogicalName != "quotedetail") { return; } } else { return; } try { IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService( typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); if (context.MessageName == "Create") { Entity QuoteProduct = (Entity)context.InputParameters["Target"]; Guid QPID = QuoteProduct.Id; TaxCreator(service, QPID); } if (context.MessageName == "Update" && context.Depth < 3) { Entity QuoteProduct = (Entity)context.PostEntityImages["Target"]; Guid QPID = QuoteProduct.Id; TaxUpdater(service, QPID); } } catch (FaultException<OrganizationServiceFault> ex) { throw new InvalidPluginExecutionException( "An error occurred in the plug-in.", ex); } } private static void TaxCreator(IOrganizationService service, Guid QPID) { using (var crm = new XrmServiceContext(service)) { var QuoteProduct = crm.QuoteDetailSet.Where(c => c.QuoteDetailId == QPID).First(); var SaleSetting = crm.new_salessettingSet.Where(c => c.statecode == 0).First(); double TaxPercent = (Convert.ToDouble(SaleSetting.new_TaxPercent) / 100); if (QuoteProduct.IsPriceOverridden == false) { decimal Tax = (decimal)Convert.ToDecimal(Convert.ToDouble(QuoteProduct.BaseAmount - QuoteProduct.ManualDiscountAmount.GetValueOrDefault()) * TaxPercent); decimal PricePerUnit = (decimal)(QuoteProduct.PricePerUnit.GetValueOrDefault() - QuoteProduct.VolumeDiscountAmount.GetValueOrDefault()); crm.UpdateObject(QuoteProduct); crm.SaveChanges(); QuoteProduct.Attributes["tax"] = new Money(Tax); QuoteProduct.Attributes["new_result"] = new Money(PricePerUnit); crm.UpdateObject(QuoteProduct); crm.SaveChanges(); } } } private static void TaxUpdater(IOrganizationService service, Guid QPID) { using (var crm = new XrmServiceContext(service)) { var QuoteProduct = crm.QuoteDetailSet.Where(c => c.QuoteDetailId == QPID).First(); var SaleSetting = crm.new_salessettingSet.Where(c => c.statecode == 0).First(); double TaxPercent = (Convert.ToDouble(SaleSetting.new_TaxPercent) / 100); if (QuoteProduct.IsPriceOverridden == false) { decimal Tax = (decimal)Convert.ToDecimal(Convert.ToDouble(QuoteProduct.BaseAmount - QuoteProduct.ManualDiscountAmount.GetValueOrDefault()) * TaxPercent); decimal PricePerUnit = (decimal)(QuoteProduct.PricePerUnit.GetValueOrDefault() - QuoteProduct.VolumeDiscountAmount.GetValueOrDefault()); crm.UpdateObject(QuoteProduct); crm.SaveChanges(); QuoteProduct.Attributes["tax"] = new Money(Tax); QuoteProduct.Attributes["new_result"] = new Money(PricePerUnit); crm.UpdateObject(QuoteProduct); crm.SaveChanges(); } } } } 

I also checked the server event viewer for errors, and no result! I registered my plugin to create and update product quotes. Any help is appreciated.

+6
source share
2 answers

I would debug a shotgun. Implement the following trace. Usually I place a tracer declaration as a member of the class (therefore it is visible to all my help methods in the class) and writes to it (when it is desperate and disappointed) after each operation (more or less). Then, when the program crashes on its own (or when I intentionally turn it around to see the trace log), I can usually indicate the problem area.

 public class MyPlugin _ IPlugin { private ITracingService _trace; public void Execute(IServiceProvider service) { _trace = (ITracingService)service.GetService(typeof(ITracingService)); _trace.Trace("Commencing."); ... _trace.Trace("Right before an operation. " + someValue); PerformAnOperation(); _trace.Trace("Right before an other operation. " + someOtherValue); PerformAnOtherOperation(); ... throw new Exception("Intentional!"); } } 

You can keep track of exactly where the problem arises. In my experience, when someone knows where it hurts, you can easily suggest how to fix the problem.

EDIT:

Since the OP requested more detailed information, I take its code and insert the tracing algorithm into it. A bit redundant, but apparently CRM can be very confusing. I was there myself.

 public class Plugin : IPlugin { // Here we declare our tracer. private ITracingService _trace; public void Execute(IServiceProvider serviceProvider) { // Here we create it. _trace = (ITracingService)serviceProvider .GetService(typeof(ITracingService)); _trace.Trace("Commencing."); // Here we crash our plugin just to make sure that we can see the logs // with trace information. This statement should be gradually moved down // the code to discover where exactly the plugin brakes. throw new Exception("Intentional!"); IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider .GetService(typeof(IPluginExecutionContext)); Entity entity; ... try { ... } catch (FaultException<OrganizationServiceFault> ex) { throw new InvalidPluginExecutionException( "An error occurred in the plug-in.", ex); } // Here we catch all other kinds of bad things that can happen. catch(Exception exception) { throw exception; } } private static void TaxCreator(IOrganizationService service, Guid QPID) { // Here we add a line to the trace hoping that the execution gets here. _trace.Trace("Entered TaxCreator."); using (var crm = new XrmServiceContext(service)) { var QuoteProduct = crm.QuoteDetailSet.Where(...).First(); var SaleSetting = crm.new_salessettingSet.Where(...).First(); double TaxPercent = (Convert.ToDouble(...) / 100); // Here we add a line to the trace to see if we get past this point. _trace.Trace("Approaching if statement."); if (QuoteProduct.IsPriceOverridden == false) { ... } } } private static void TaxUpdater(IOrganizationService service, Guid QPID) { // Here we add a line to the trace hoping that the execution gets here. _trace.Trace("Entered TaxUpdater."); ... } } 
+2
source
  public void Execute(IServiceProvider serviceProvider) { IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); Entity entity; if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { entity = (Entity)context.InputParameters["Target"]; if (entity.LogicalName != "quotedetail") { return; } } else { return; } try { IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); QuoteDetail QuoteProduct = ((Entity)context.InputParameters["Target"]).ToEntity<QuoteDetail>(); if (context.MessageName == "Create" || context.MessageName == "Update") // && context.Depth < 3) //try to avoid depth unless you have to have it { TaxSetter(service, QuoteProduct); } } catch (FaultException<OrganizationServiceFault> ex) { throw new InvalidPluginExecutionException( "An error occurred in the plug-in.", ex); } } private static void TaxSetter(IOrganizationService service, QuoteDetail product) { using (var crm = new TrainingContext(service)) { var QuoteProduct = product.ToEntity<QuoteDetail>(); if (QuoteProduct.IsPriceOverridden == false) { double TaxPercent = Convert.ToDouble(50 / 100); decimal Tax = (decimal)Convert.ToDecimal(Convert.ToDouble(QuoteProduct.BaseAmount - QuoteProduct.ManualDiscountAmount.GetValueOrDefault()) * TaxPercent); decimal PricePerUnit = (decimal)(QuoteProduct.PricePerUnit.GetValueOrDefault() - QuoteProduct.VolumeDiscountAmount.GetValueOrDefault()); QuoteProduct.Tax = Tax; //depending on how you the parameters passed into CrmSvcUtil QuoteProduct.Attributes["new_result"] = new Money(PricePerUnit); //same deal here //crm.UpdateObject(QuoteProduct); //crm.SaveChanges(); //code not needed, the Plugin context will take care of this for you } } } 

The idea is that you want your plugin context to work for you; and you want to openly do as little as possible. I changed the tax calculation because I do not have your attributes; You will want to change them. If I still misunderstood your problem, I would be happy to delete my post (or try).

+2
source

All Articles