2017-09-27 8 views
0

Je suis en train d'écrire un plugin pour valider un devis avant qu'elle ne sauve. Nous voulons faire valoir qu'il doit y avoir une ligne de produits de devisCitation de validation Plugin Non Prévention Clôture de citation sur InvalidPluginExecutionException

article sur un devis avant un devis peut être activé, gagné ou perdu. Le mode brouillon n'a pas cette exigence.

J'ai écrit le code suivant et en appuyant sur le bouton "Close Quote" sur le ruban et en sélectionnant Won comme raison, une boîte d'erreur de processus métier apparaît avec le message d'erreur.

Cependant, lors de la fermeture du message d'erreur et de rafraîchir la page, la citation est réglé sur fermé. Pourquoi le devis se ferme-t-il même si l'exception a été levée?

Pour votre information, la phase de plug-in est réglé sur pré-opération.

Voici mon code source (Mise à jour 02/10/2017):

using Microsoft.Xrm.Sdk; 
using Microsoft.Xrm.Sdk.Query; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ValbrunaPlugins 
{ 
    public class QuoteValidation : IPlugin 
    { 
     private ITracingService tracingService; 

     public void Execute(IServiceProvider serviceProvider) 
     { 

      // retrieve the context, factory, and service 
      IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); 
      IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); 
      IOrganizationService service = factory.CreateOrganizationService(context.UserId); 

      bool isCorrectEvent = context.MessageName == "SetStateDynamicEntity" || context.MessageName == "SetState" || context.MessageName == "Win" || context.MessageName == "Close"; 
      bool hasEnityMoniker = context.InputParameters.Contains("EntityMoniker"); 

      // ensure we are handling the correct event and we were passed an entity from the context 
      if (!isCorrectEvent || !hasEnityMoniker) return; 
      // get the reference to the quote entity 
      EntityReference quoteEntityReference = (EntityReference)context.InputParameters["EntityMoniker"]; 

      Entity quoteEntity = null; 
      try 
      { 
       // get the quote entity from the entity reference 
       quoteEntity = ActualEntity.GetActualEntity(quoteEntityReference, service); 
      } catch (Exception ex) 
      { 
       throw new InvalidPluginExecutionException("Quote with id " + quoteEntityReference.Id + " not found."); 
      } 

      // ensure that we have the correct entity 
      if (quoteEntity.LogicalName != "quote") return; 

      // write query to retrieve all the details for this quote 
      QueryExpression retrieveQuoteDetailsQuery = new QueryExpression 
      { 
       EntityName = "quotedetail", 
       ColumnSet = new ColumnSet(), 
       Criteria = new FilterExpression 
       { 
        Conditions = 
         { 
          new ConditionExpression 
          { 
          AttributeName = "quoteid", 
          Operator = ConditionOperator.Equal, 
          Values = { (Guid)quoteEntity.Id } 
          } 
         } 
       } 
      }; 

      // execute the query to retrieve the details for this quote 
      EntityCollection quoteDetails = service.RetrieveMultiple(retrieveQuoteDetailsQuery); 

      // retrieve the current status of the quote 
      // 0 - Draft 
      // 1 - Active 
      // 2 - Won 
      // 3 - Closed 
      int quoteStatus = ((OptionSetValue)(quoteEntity.Attributes["statecode"])).Value; 

      // if not in draft mode 
      if (quoteStatus != 0) 
      { 
       // if the amount of details for the quote is less than 1 
       if (quoteDetails.Entities.Count < 1) 
       { 
        throw new InvalidPluginExecutionException("There must be a quote product line item on a quote before a quote can be activated, won, or lost while not in draft mode."); 
       } 
      } 
     } 

    } 
} 

Mise à jour 02/10/2017:

J'ai créé une étape distincte pour SetState et mis à jour mon code source.

SetState

Cependant, j'ai toujours le même problème. Lorsque je ferme la citation, j'obtiens l'erreur, mais lorsque je rafraîchis la page, la citation a été fermée.

Close Quote

AVIS: Quote est actif, il n'y a aucun détail de devis, de sorte que le devis ne peut être gagnée.

Exception is successfully shown.

Une erreur de processus d'affaires est affiché comme il devrait être. Toutefois, lorsque j'actualise la page, l'état du devis a été défini sur "Fermé". Pourquoi l'a-t-il fait si l'exception a été levée?

Quote is closed.

Répondre

1

Vous devez vous enregistrer les étapes de plug-in pour les messages SetState et SetStateDynamicEntity.

reference

Pourquoi dois-je inscrire sur SetState et SetStateDynamicEntity séparément?
Comme je l'ai mentionné plus tôt, il y a plusieurs messages qui effectuent la même action dans le CRM. Un tel exemple est SetStateRequest et SetStateDyanmicEntityRequest. Si vous voulez écrire un plug-in sur SetState, vous devez l'enregistrer sur les deux messages.

Read more

+0

merci pour votre réponse! S'il vous plaît jeter un oeil à ma question mise à jour ci-dessus. J'ai ajouté l'étape setstate mais j'ai toujours le même problème. – MasterProgrammer200

+1

Avez-vous essayé de vérifier "Ne pas réviser la citation" et voir le comportement?Bcoz CRM continuera à créer de nouvelles versions si vous dites "Créer un devis révisé" –

+1

Ce n'est pas parce que la citation révisée a été sélectionnée ... qu'après un débogage, j'ai pu réaliser que lors de la fermeture d'un devis le message envoyé au le plugin est proche. Le message Close contient une entité QuoteClose plutôt que EntityMoniker EntityReference. Par conséquent, if (! IsCorrectEvent ||! HasEnityMoniker) renvoie; quitté le plugin car il n'y avait pas EntityMoniker. Je mettrai à jour mon code une fois que j'aurai fini de le nettoyer mais le problème a été résolu. Merci beaucoup! – MasterProgrammer200