Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Enze Winneris

Bien coder c'est comme jouer,
suffit de savoir faire les bonnes macros !



Abonnements

Développement CRM : Modifier les JavaScripts d'un formulaire facilement
Une grande partie des personnalisations CRM repose sur l'inclusion de code JavaScript au sein des formulaire de l'application. Malheureusement, pour inclure du JavaScript, il faut passer par un grand nombre d'écrans ( Paramètres Personnalisation Personnaliser les entités Entité Formulaires et vues Formulaire Propriétés du formulaire Modifier

Autant dire que lorsque l'on doit tester un code et faire de fréquentes modifications, cela peut devenir très vite laborieux.

 

La solution pour pouvoir modifier son code JavaScript rapidement consiste à l'inclure dynamiquement dans la page. Il faut d'abord créer un fichier .js dans un répertoire virtuel du serveur (par exemple "C:\Inetpub\wwwroot\test.js") et s'assurer qu'il est bien disponible via un navigateur (pour notre exemple : http://srv-crm/test.js).

Maintenant il faut aller dans le code JavaScript du formulaire qu'on souhaite modifier et y inclure ce code qui permet de charger une référence vers un fichier JavaScript externe dans la page :

var script = document.createElement('script'); 
script.type = 'text/javascript';
script.src = 'http://srv-crm/test.js'; 
document.getElementsByTagName('head')[0].appendChild(script);

 

Une publication et le code qu'on aura mis dans le fichier JavaScript deviendra actif sur le formulaire modifié. On peut maintenant ouvrir ce fichier dans notre éditeur JavaScript préféré, le modifier et le sauvegarder pour le tester rapidement.

 

Par contre une fois que le code n'a plus besoin d'être testé, il ne faut pas oublier de le recopier dans le formulaire afin qu'il soit disponible aussi en mode déconnecté.

par Enze | 0 commentaire(s)

Classé sous : ,

Dynamics CRM : Récupérer les couples valeur/texte des Picklist

Voici une astuce concernant les Picklist et la récupération dynamique des valeurs et textes qu'elles peuvent avoir. Lorsqu'on veut renseigner la Picklist d'une entité en code, il faut obligatoirement fixer la valeur de la Picklist, le texte ne suffit pas.

Ceci ne fonctionnera pas :

Public Sub updateAccountCategoryCode(ByVal accountid As String, ByVal CategoryCode As String)
    Dim a As account = CType(CRMHelper.Retrieve(GetType(account), accountid), account)
    Dim acc As Picklist
    acc = New Picklist
    acc.name = CategoryCode
    a.accountcategorycode = acc
    CRMHelper.Update(a)
End Sub 

Pour que cela fonctionne, il faudrait définir la valeur associée à ce texte de cette manière :

Public Sub updateAccountCategoryCode(ByVal accountid As String, ByVal CategoryCode As String)
    Dim a As account = CType(CRMHelper.Retrieve(GetType(account), accountid), account)
    Dim acc As Picklist
    acc = New Picklist
    acc.name = CategoryCode
    Select Case CategoryCode
        Case "Prospect"
            acc.Value = 1
        Case "Client"
            acc.Value = 2
    End Select
    a.accountcategorycode = acc
    CRMHelper.Update(a)
End Sub 

Seulement on est obligé d'aller chercher dans l'interface de CRM les valeurs associées aux textes possibles pour la Picklist, autant dire que cela peut vite devenir chronophage si l'on travaille avec beaucoup de Picklist.

Heureusement, de la même manière que l'on a le WebService principal de l'application (~/MSCRMServices/2006/CRMService.asmx) pour la lecture, mise à jour et suppression d'entités, il existe un 2ème WebService (~/MSCRMServices/2006/MetaDataService.asmx) qui nous permet d'obtenir les méta-données de l'application, dont les PicklistAttributeMetadata (A noter qu'en V4, ce WebService permet aussi de créer, modifier et supprimer les méta-données des entités).

Une fois le WebService ajouté comme référence Web dans Visual Studio, on peut maintenant récupérer les informations de la Picklist qui nous intéresse :

Private Shared Function retrievePicklistAttributeMetadata(ByVal entityName As String, ByVal column As String) As PicklistAttributeMetadata
    Dim MetaDataService As New MetadataService
    MetaDataService.Credentials = System.Net.CredentialCache.DefaultCredentials
    Dim attMetaData As AttributeMetadata = MetaDataService.RetrieveAttributeMetadata(entityName, column)
    Dim plAttMetaData As PicklistAttributeMetadata = CType(attMetaData, PicklistAttributeMetadata)
    Return plAttMetaData
End Function 

Et à partir de là, rien de plus facile que de retrouver le couple de valeur/texte qui nous intéresse dans la propriété Options :

Public Shared Function getPicklistFromText(ByVal entityName As String, ByVal column As String, ByVal text As String) As Picklist
    Dim pam As PicklistAttributeMetadata = retrievePicklistAttributeMetadata(entityName, column)
    For Each o As [Option] In pam.Options
        If (o.Description = text) Then
            Dim pl As New Picklist
            pl.Value = o.OptionValue
            pl.name = o.Description
            Return pl
        End If
    Next
End Function 

Ce qui au final réduit considérablement la complexité de la mise à jour de la société de mon exemple initial et supprime la maintenance nécessaire en cas de mise à jour de la Picklist.

Public Sub updateAccountCategoryCode(ByVal accountid As String, ByVal CategoryCode As String)
    Dim a As account = CType(CRMHelper.Retrieve(GetType(account), accountid), account)
    a.accountcategorycode = getPicklistFromText("account", "accountcategorycode", CategoryCode)
    CRMHelper.Update(a)
End Sub 

Ça peut toujours servir ;)

par Enze | 0 commentaire(s)

CRM 4 : Migration des Callouts depuis la V3

Ca faisait longtemps que je n' avais plus posté mais maintenant je m'y remet. J'ai eu l'occasion de m'intéresser de près aux développements personnalisés sous Dynamics CRM et je vais tacher de vous faire partager mes expériences sur le sujet.

Mon premier post sur le sujet traitera de la migration puisque j'ai eu à en réaliser une sur un projet comportant des Callouts, c'est à dire des événements levés automatiquement en .NET lors de certaines actions : création/modification/suppression d'entité, changement d'état ou de propriétaire, ...

Si on regarde le SDK de la V4, on peut trouver cette phrase sur la migration des Callouts :

"Microsoft Dynamics CRM 3.0 custom extensions such as callouts and workflow assemblies that use the Microsoft Dynamics CRM 3.0 Web services can be seamlessly upgraded to Microsoft Dynamics CRM On-premise without having to recompile."

Bien évidement, cela n'a pas été aussi simple pour moi. J'ai rencontré quelques erreurs que je vais décrire ici ainsi que les solutions que j'y ai trouvé.

 

1. Erreur déclenchée dès qu'un événement Callout aurait du être levé

Optimiste, je place mon fichier XML ainsi que mes DDLs dans le dossier approprié et je teste : A chaque création d'entité, j'ai un message d'erreur type. En activant le traçage de logs sur le serveur, j'ai pu avoir un message d'erreur un peu plus explicite que le traditionnel "Veuillez contacter votre administrateur CRM". L'exception déclenchée était :

FileNotFoundException: Impossible de charger le fichier ou l'assembly 'Microsoft.Crm.Platform.Callout.Base, Version=3.0.5300.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' ou une de ses dépendances. Le fichier spécifié est introuvable.

C'est dans cette librairie que l'on trouve les prototypes des méthodes à implémenter pour en faire des Callouts donc il est normal qu'une erreur soit levée si elle n'est pas présente. Après avoir tenté d'ajouter cette assembly partout où je le pouvais, il s'est avéré que la solution était une "simple réparation" du serveur CRM à l'aide du CD d'installation de CRM.

 

2. Récupération du ColumnSet

Dans la version .NET 1, j'avais une petite méthode qui utilisait la réflexion pour obtenir la liste des attributs par type d'entités pour le paramètre du WebService.

Public Shared Function GetColumnSet(ByVal entityType As Type) As ColumnSet
    Dim cols As New ColumnSet
    Dim fields As FieldInfo() = entityType.GetFields
    Dim colNames(fields.Length - 1) As String
    For i As Integer = 0 To fields.Length - 1
        colNames(i) = fields(i).Name
    Next
    cols.Attributes = colNames
    Return cols
End Function 

Avec le .NET Framework 2 (et donc le 3 aussi), la méthode GetFields ne fonctionne plus, il faut utiliser GetProperties.

Public Shared Function GetColumnSet(ByVal entityType As Type) As ColumnSet
    Dim cols As New ColumnSet
    Dim pis As PropertyInfo() = entityType.GetProperties
    Dim colNames(pis.Length - 1) As String
    For i As Integer = 0 To pis.Length - 1
        colNames(i) = pis(i).Name
    Next
    cols.Attributes = colNames
    Return cols
End Function 

Ce n'est pas un gros changements mais l'erreur est difficile à diagnostiquer puisqu'il faut passer en debug pour voir qu'aucun attribut n'est listé par la méthode GetFields.

 

3. Distinction du type d'entité à l'aide du paramètre postImageEntityXml

Pour savoir quel type d'entité est crée/modifié/supprimé, on avait recours à un code de ce type (je rappelle qu'on ne peut toujours pas utiliser entityContext.EntityTypeCode à cause du problème des énumérations qui sont numérotées depuis 0 et par ordre alphabétique dans la référence en VB alors que les numéros CRM ne suivent pas la même logique) :

Public Overrides Sub PostCreate(ByVal userContext As CalloutUserContext, ByVal entityContext As CalloutEntityContext, ByVal postImageEntityXml As String)
    Dim de As DynamicEntity = CRMHelper.Deserialize(postImageEntityXml, GetType(DynamicEntity))
    Select Case de.Name
        Case "account"
            'Traitement pour les sociétés
        Case "contact"
            'Traitement pour les contacts
    End Select
End Sub 

Depuis le passage en version 4, j'ai pu voir en passant en debug dans la méthode que le paramètre postImageEntityXml était null, ce qui peut s'avérer gênant pour dé-sérialiser l'entité et récupérer son type. La solution est donc de faire une classe par type d'entité et de distinguer les classes à appeler au niveau du fichier XML callout.config.xml de cette façon :

<?xml version="1.0" encoding="utf-8" ?>
<callout.config version="2.0">
    <callout entity="account" event="PostCreate">
        <subscription assembly="MyCallouts.dll" class="MyCallouts.AccountCallouts"></subscription>
    </callout>
    <callout entity="contact" event="PostCreate">
        <subscription assembly="MyCallouts.dll" class="MyCallouts.ContactCallouts"></subscription>
    </callout>
</callout.config>

 

4. Récupération de l'utilisateur connecté : Utilisation du WhoAmI

Ce dernier point sort un peu du contexte des Callouts, puisqu'il s'agit d'un JavaScript permettant de récupérer l'identifiant de l'utilisateur connecté.

En CRM v3, on aurait fait comme ça :

function getUserId()
{
    try
    {
        var command = new RemoteCommand("SystemUser", "WhoAmI", "/MSCRMServices/");
        var oResult = command.Execute();
        if (oResult.Success)
            return oResult.ReturnValue.UserId;
    }
    catch(e)
    {
        alert("Error while retrieving userid.");
    }
    return null;
}

Mais en CRM v4, comme l'objet RemoteCommand n'est plus accessible, on ferait plutôt comme ça (exemple inspiré des Walkthrough du SDK) :

function getUserId()
{
    try
    {
        var serverUrl;
        if(IsOnline())
            serverUrl = "http://SRVCRM:5555";
        else
            serverUrl = "http://localhost:2525";
        var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
        xmlhttp.open("POST", serverUrl  + "/mscrmservices/2007/crmservice.asmx", false);
        xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
        xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
        var soapBody = "<soap:Body>"+
            "<Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+
            "<Request xsi:type='WhoAmIRequest' />"+
            "</Execute></soap:Body>";
        var soapXml = "<soap:Envelope " +
            "xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' "+
            "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "+
            "xmlns:xsd='http://www.w3.org/2001/XMLSchema'>";
        soapXml += GenerateAuthenticationHeader();
        soapXml += soapBody;
        soapXml += "</soap:Envelope>";
        xmlhttp.send(soapXml);
        xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async=false;
        xmlDoc.loadXML(xmlhttp.responseXML.xml);
        var userid = xmlDoc.getElementsByTagName("UserId")[0].childNodes[0].nodeValue;
        return userid;
    }
    catch(e)
    {
        alert("Error while retrieving userid.");
    }
    return null;
}

NB : N'oubliez pas de distinguer le cas Online et Offline, puisqu'en v4 on peut se servir des WebService du client comme de ceux du serveur.

 

Enze
Member of Wygteam
www.wygwam.com

par Enze | 0 commentaire(s)

Monsieur tatouage de Zune invité à Redmond

Vous avez surement entendu parler de cet américain, qui aime tellement le Zune qu'il se l'est fait tatoué :

Avec ces tatouages et le buzz qu'ils ont crées, il a réussi à attirer l'attention de Microsoft Corp et s'est fait invité à Redmond le 5 Juillet. Il tournera même une interview pour Channel 10.

 

Vous croyez que si je me tatoue "I Love ASP.NET" sur la fesse droite, je serais invité à rencontrer Scott Guthrie ?

 

 

Via Engadget.

par Enze | 4 commentaire(s)

Classé sous : ,

Quand Bill rencontre Steve ...

Vous l'aurez compris, je vous parle de Bill Gates et Steve Jobs réunis lors de la conférence All Things Digital organisée par le Wall Street Journal.

C'est assez marrant de les voir se jeter des fleurs sur leur passé respectif :)

Retrouvez les photos et un compte-rendu conplet de leur intervention sur endaget.

par Enze | 0 commentaire(s)

Classé sous : , ,

Google IG devient iGoogle ! (ou comment créer ses propres gadgets en cliquant ...)

Après plusieurs années de bon et loyaux services, Google IG (la page personnalisée de Google personnalisable par l'ajout de gadgets) vient de changer de nom pour iGoogle. L'intérêt de ce changement de nom consiste surtout à mieux identifier le service pour pouvoir le positionner plus efficacement vis à vis d'autres services de personnalisation tels que LiveNetvibes ou WebWag.

 

Mais ce ne sont pas les seuls changements qui apparaissent en ce moment...

On peut voir apparaitre une fonctionnalité en version française permettant de skinner son iGoogle.

Ici le théme "Ville" qui change les couleurs des fenêtres en fonction de l'heure.

 

L'autre grande nouveauté et la possibilité de créer soi-même ses gadgets et de les faire partager à ses amis/contacts. Le service est disponible sur cette page (service uniquement en anglais donc pensez à changer la langue préférée de vos pages dans votre navigateur).

Une gadget permettant d'indiquer ce que l'on fait et ce qui nous intéresse actuellement.

 

Le traditionnel compte à rebours.

 

Une galerie de photos.

 

Une liste personnalisable à souhait.

 

Le résultat sur une page iGoogle.

 

M'est d'avis que ça va inspirer plus d'un fournisseur de pages gadgetisés et gadgetisables ;)

 

Sources et ressources.

par Enze | 0 commentaire(s)

Classé sous : , ,

Vous êtes plutôt Wii ou PS3 ?

Vous vous souvenez surement des publicités GetAMac© dont Renaud nous avait parlé ?

 

Et bien après le remake version Dell XPS (publicité 1, publicité 2) voici la version PS3 vs Wii :

 

Je n'ai pas encore réussi à savoir si c'était une publicité officielle ou non, mais si c'en est une je trouve cela osé de la part de Nintendo de lister ce que la PS3 peut faire et de n'y opposer que les formes d'une jolie blonde.

Remarquez que ça marche plutôt bien, puisque que j'ai du regarder la publicité plusieurs fois avant de pouvoir m'intéresser à ce que la PS3 disait ;)

par Enze | 4 commentaire(s)

Classé sous : ,

Liens pour ajouter un contact Windows Live Messenger dans Internet Explorer

Il est possible depuis la version 7.5 de MSN Messenger (devenu Windows Live Messenger) d'ajouter des contacts à sa liste directement depuis un lien dans un internet Explorer.

A ma connaissance il existe 4 types de liens pris en charge par WLM. Il suffit de les mettre dans le href de la balise a et Internet Explorer se charge du reste, testez donc avec le CodyxBot :

Ces liens sont toutefois soumis à 3 contraintes :

  • Le "protocole" n'est reconnu que sous Internet Explorer.
  • Cela ne marche que sur les versions postérieures à MSN Messenger 7.5 (inclus)
  • Il ne faut pas avoir décoché l'option correspondante dans Windows Live Writer.

Options de Windows Live Messenger

 

C'est pas grand chose mais ça peut servir quand on travaille avec les Live Agent par exemple.

par Enze | 3 commentaire(s)

Classé sous : ,

Peut-on être chez Wygwam sans avoir un blog ?

Bonjour à tous,

 

A la question du titre, la réponse est évidemment que non. C'est le Wygwam Spririt qui vous y pousse.

Donc me voila : Enze Winneris (cherchez le jeu de mot) alias Cédric Helle, développeur anonyme chez Wygwam depuis maintenant un peu plus d'un an. J'ouvre mon blog maintenant (seulement) parce que j'estimais que pour avoir un blog il fallait avoir quelque chose à dire, et que grace à la WygTeam j'éstime que c'est le cas.

Ce blog s'orientera principalement vers le .NET et l'ASP.NET et j'espére résister à la tentation de bloger sur Dark Age of Camelot (MMORPG) ce qui n'est pas le but de cet espace.

En parlant d'espace, je remercie Nix pour avoir crée ce blog un lendemain de jour férié et un jour de Newsletter :p

 

Cordialement,

par Enze | 14 commentaire(s)



Les 10 derniers blogs postés

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01

- SharePoint Online: Script PowerShell pour supprimer une colonne dans tous les sites d’une collection par Blog Technique de Romelard Fabrice le 11-27-2018, 18:01


Propulsé par Community Server (Personal Edition), par Telligent Systems