Author Archives: Sébastien Levert

Visual Studio 2012 : En tournée !

Afin de faire la promotion de Visual Studio 2012, Microsoft part en tournée et visite les grandes villes du Canada afin de présenter de de démontrer les améliorations de la plateforme de développement.  Vous pouvez vous inscrire à l’adresse suivante : http://www.microsoft.com/canada/web/visualstudio/

Personnellement, j’y serai le 2 octobre prochain pour la session en français.  La rencontre aura lieu dans les bureaux de Microsoft Montréal, à l’adresse suivante :

Microsoft Canada Montreal Office
2000 Avenue McGill College
Suite 450 Montreal Québec H3A 3H3
Canada

Au plaisir de vous y rencontrer !

Visual Studio 2012 et SharePoint : De mieux en mieux !

Depuis les tout débuts de SharePoint, Visual Studio a toujours été d’une aide précieuse en ce qui a trait au développement de solutions personnalisées dans SharePoint.  Par contre, la communauté SharePoint s’est toujours sentie délaissée face à ses amis .NET ou Silverlight qui eux avaient un intégration complète avec les outils de l’IDE de développement.  Depuis SharePoint 2010, une forte intégration a été réalisée et on peut maintenant être réconciliés avec Visual Studio.  Que ce soit avec les gabarits de projets ou les gabarits d’artéfacts, on se retrouvait devant un nombre grandissant de possibilités.

Par contre, l’aspect qui a toujours été complexe et peu supporté par l’IDE a toujours été l’aspect du débogage et des tests.  Et même avec la sortie d’hier, celle de Visual Studio 2012, rien ne semblait combler ce vide… Eh bien… Plus maintenant !

Le modèle de livraison de Visual Studio sera accéléré, pour ajouter des fonctionnalités plus fréquemment… Et quelques unes des premières vraies améliorations sont associées directement à SharePoint !

Cet automne, nous retrouverons à même la plateforme 2012 de Visual Studio les aspects natifs suivants :

  • Tests unitaires, grâce à la confection d’un émulateur SharePoint basé sur “Fakes & Stubs”, le nouveau framework de d’isolation de .NET
  • Tests d’interface, grâce à l’implémentation des particularités à SharePoint dans le moteur d’enregistrements des tests
  • Tests de charge, grâce à l’injection des différents éléments nécessaires au bon fonctionnement des requêtes SharePoint (ex: faire des requêtes avec les bons GUID)
  • Intellitrace, grâce à un filtre qui permet de simplifier les logs récoltés et laisser place aux vraies erreurs

Pour plus d’information, je vous invite à consulter l’article suivant : http://blogs.msdn.com/b/bharry/archive/2012/09/12/visual-studio-update-this-fall.aspx

Bien hâte de tester tout ça ! Et d’ici là, bonne installation de Visual Studio 2012 !

Obtenir le nom complet d’un Assembly dans Visual Studio 2010

Je devais trouver rapidement le nom complet d’un Assembly dans Visual Studio 2010 aujourd’hui et je n’arrivais pas à trouver d’outil qui allait me permettre de le faire rapidement, et de façon répétitive.  J’ai donc pensé à créer cet outil qui sera d’une aide précieuse à l’avenir.

La démarche se fait donc en 4 étapes :

  1. Créer un script PowerShell qui aura le code suivant
    # Gets the current window
    $window = (Get-Host).UI.RawUI
    
    # Sets the buffer size
    $bufferSize = $window.BufferSize
    $bufferSize.Height = 3000
    $bufferSize.Width = 150
    $window.BufferSize = $bufferSize
    
    # Sets the viewable size
    $displaySize = $window.WindowSize
    $displaySize.Width = 120
    $window.WindowSize = $displaySize
    
    # Loads the full Assembly Name
    [System.Reflection.Assembly]::LoadFile($args[0]).FullName
    
  2. Créer un outil externe (External Tool) dans Visual Studio 2010 
  3. Nommer l’outil et définir la commande à exécuter
  4. Définir la série d’arguments à passer à powershell.exe
    -ExecutionPolicy RemoteSigned -File "Path\To\Script.ps1" $(TargetPath)
  5. Une fois le tout en place, il suffit de sélectionner un item d’un projet de Visual Studio et d’exécuter la commande

Voilà ! Un autre problème récurent de réglé !

PowerShell : Utiliser le résultat d’une fonction comme colonne d’affichage

Après des heures de recherche et de problèmes, j’ai finalement trouvé réponse à ma question, et j’ai pensé la partagé ici.

Le problème

Je devais sortir la liste complète des fonctionnalités SharePoint dans un format X. Par contre, l’information qui m’intéressait le plus était le titre affiché par SharePoint de chacune des fonctionnalités. Évidemment, cette information est retracée par la méthode GetTitle de l’objet SPFeatureDefinition.

Le cheminement

J’ai passé par plusieurs chemins pour tenter d’y arriver.

  1. L’utilisation d’un PSObject pour générer un objet transitoire. L’idée était bonne, mais je n’aimais pas le fait que je n’avais plus accès aux autres propriétés de l’objet de base.
  2. L’utilisation d’un Write-Host pour affiché seulement l’information intéressante.
  3. La création d’un HashTable qui allait m’être utilie pour afficher le résultat final

Finalement, et par toute évidence, je savais que ma façon de faire était plus ou moins, disons, correcte…  La réponse à ma question était dans la question elle-même.  L’affichage ne pourrait-il par s’occuper d’appeller cette méthode lors de son exécution ? Et bien… oui !

La solution

L’utilisation d’un objet anonyme utilisé par le Cmdlet Select-Object s’est finalement avéré la bonne chose à faire.  Si un objet anonyme avec la structure suivante est transmis à Select-Object, il la gérera comme étant un appel, et ainsi s’occupera de retracer le résultat de celui-ci.

Donc dans mon cas bien précis, mon appel était le suivant :

Get-SPFeature | Select *,  @{ Name = "Title"; Expression = {$_.GetTitle(1036)} } | Out-GridView

En conservant l’ensemble des propriétés de mes objets, il est m’beaucoup plus utile maintenant pour affiner ma recherche, et toujours m’assurer de voir mon titre affiché dans mon résultat final!

Bon PowerShell !

Déploiement des webparts de type XsltListViewWebpart

Dans la majorité de nos projets, nous avons souvent l’enjeu que nous devons déployer sur une page une instance de webpart de type XsltListViewWebpart personnalisé avec une vue particulière.  De plus, on nous demande de changer l’URL de destination, le titre, son type de Chrome, etc.  Jusqu’à récemment, ce travail se complétait avec du code qui devait exécuter certaines opérations pour arriver au but final.

Avec certains projets déployés dans un mode SandBox pour Office 365, nous avons dû revoir notre fonctionnement, et avons finalement trouvé une solution parfaite à notre problème de déploiement.

Tout d’abord, il est essentiel de créer une définition de liste comprenant la vue que nous voulons utiliser et exposer à travers de notre webpart.  Ensuite, nous devons utiliser la syntaxe suivante afin de personnaliser certaines des propriétés du webpart.  C’est cette opération qui nous était impossible jusqu’à maintenant.

Dans le module qui déploie la page désirée, on spécifie la personnalisation suivante :

<File Url="default.aspx" NavBarHome="True" Path="PageModule\default.aspx">
    <View List="Lists/MaListe" BaseViewID="11" WebPartZoneID="Left" WebPartOrder="1">
        <![CDATA[
			<webParts>
				<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
					<metaData>
						<type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
						<importErrorMessage>$Resources:spscore,WPImportErrorMessage</importErrorMessage>
					</metaData>
					<data>
						<properties>
							<property name="Title" type="string">Titre du webpart redéfini</property>
							<property name="TitleUrl" type="string">Lists/MaListe/Forms/FormulairePersonnalise.aspx</property>
							<!-- Ajoutez les autres propriétés que vous désirez redéfinir --> 
						</properties>
					</data>
				</webPart>
			</webParts> 
        ]]>
	</View>
</File>

Dans le cas actuel, le BaseViewID est un identifiant qui réfère à une vue personnalisée définie dans la définition de liste.

Cette façon de faire permet alors de faciliter le déploiement et réduire le code personnalisé d’une solution. De plus, elle reste valide avec les solutions déployées dans Office 365!

Bon déploiement !

SharePoint Summit 2012 – Mes présentations

Bonjour !

Suite à mes deux présentations d’hier dans le cadre du SharePoint Summit 2012 de Québec, voici un lien vers mes présentations ainsi que vers le code de ma présentation sur les tests unitaires.

Présentations

Code

En espérant que ces présentations sauront vous inspirer dans vos prochaines activités de développement SharePoint !

L’exportation de gabarits de sites et l’affichage multilingue

Avez-vous déjà tenté d’utiliser les principes du ALM de Microsoft quant au développement dans la plateforme SharePoint 2010 ? Évidemment, plusieurs éléments facilitent le travail de transfert de requis entre l’analyste et le développeur.  Par exemple, le développeur n’a plus à créer les différents schémas XML permettant de publier les types de contenu ainsi que les colonnes de sites.  Bien que fort pratique, cette façon de faire amène un problème néfaste à la réalisation de sites multilingues.

Le principe est fort simple.  Il suffit d’utiliser le menu de sauvegarde d’un gabarit de site offert par SharePoint 2010!  Le menu suivant permet de sauvegarder la structure du site actuel et génère un .wsp qui peut être utilisé plus tard dans Visual Studio afin d’importer un gabarit et de ne pas avoir à tout refaire les éléments simples (colonnes, types de contenu, pages, définitions de listes, etc.)

Le problème

Dans le cas simple d’un site unilingue, ce principe semble fonctionner à la perfection. Par contre, lorsqu’on veut permettre à l’usager de changer de langue dans le même site, quelques problèmes se posent. Les titres (autant des types de contenus que des colonnes de site) et descriptions ne sont jamais traduits. Ils prennent la valeur de la langue par défaut du site dans lequel ils apparaissent. Comme dans l’exemple ci-dessous :

En français :

En anglais :

Ce problème se pose aussi dans les définitions de listes. Les colonnes ainsi que les types de contenu imbriqués directement dans les types de contenu (sans l’utilisation de ContentTypeRef) ne changent pas d’une langue à l’autre.

La solution

L’exportation des sites (et donc de tous ses archétypes) injecte une propriétés dans les types de contenu et dans les colonnes de site qui semble totalement inoffensive, mais qui empêche quelconque changement dynamique de langue dans un site.

Voici un schéma généré par une exportation d’un site via l’outil d’exportation de SharePoint 2010 :

  <Field     
    ID="{14F74BA9-3AD9-4F68-8387-ADA4F6F866C3}"     
    Name="TestLocalizationField1"
    StaticName="TestLocalizationField1"     
    DisplayName="$Resources:TestLocalization,Field1Name"
    Description="$Resources:TestLocalization,Field1Description"
    Group="$Resources:TestLocalization,Field1Group"
    Type="Text"
    Overwrite="TRUE" />

L’attribut “Overwrite=’TRUE’” (voir sa définition ici) permet d’écraser un type de contenu (ou une colonne de site) avec le même identifiant que celui spécifié.  Malheureusement, cet attribut empêche aussi d’avoir un dynamisme quant à l’interface multilingue de SharePoint 2010.  En retirant cet attribut, les types de contenu et les colonnes de site reprennent leur comportement normal.

Le schéma qui fonctionne et qui permet d’afficher les éléments dans les bonnes langues est le suivant :

  <Field
    ID="{278BBA30-1D02-42DC-A5DE-5618C236D2D7}"
    Name="TestLocalizationField1NoOverwrite"
    StaticName="TestLocalizationField1NoOverwrite"
    DisplayName="$Resources:TestLocalization,Field1NameNoOverwrite"
    Description="$Resources:TestLocalization,Field1DescriptionNoOverwrite"
    Group="$Resources:TestLocalization,Field1GroupNoOverwrite"
    Type="Text" />

Le résultat final devient donc fonctionnel et beaucoup plus efficace que celui généré par les outils d’exportation de base de SharePoint 2010.

En français :

En anglais :

Conclusion

Veuillez toujours valider que vos archétypes ne contiennent pas l’attribut “Overwrite=’TRUE’” dans le cas où vous voulez utiliser les interfaces multilingues de SharePoint 2010!  Et espérons, qu’un jour, les groupes de catégories de champs et de types de contenu seront, eux aussi, localisables…

Pour télécharger la solution de test de localisation, utilisez le lien suivant :

Erreur commune du Just-In-Time Debugger

À chaque nouvelle installation d’un environnement de développement pour SharePoint 2010, j’ai quelques fois par jour un message d’erreur lancé par Visual Studio 2010. Ce message d’erreur me demande de déboguer le processus OWSTIMER.exe, puisque celui-ci a lancé l’erreur “System.Secyrity.Cryptography.CryptographicException”.

Le problème est causé par une clé d’encryption mal gérée lors du recyclage du processus OWSTIMER.exe.

Afin de régler la situation, il suffit de supprimer 2 (ou 4 sur un système x64) clés de registre qui indiquent à Visual Studio 2010 de déboguer les exceptions non géréees par les systèmes .NET.

Les clés à supprimer sont les suivantes :

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DbgManagedDebugger

Pour un système x64, les clés supplémentaires à supprimer sont les suivantes :

  • HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger
  • HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\DbgManagedDebugger

Pour télécharger les fichiers de gestion du registre, utilisez les liens suivants :

Le singleton générique

Dans la série des articles sur le singleton, je trouvais primordial de discuter de généricité.

Lorsqu’un programme, une application, un module, etc., est développé de façon professionnelle et durable, celui-ci se doit d’avoir une généricité optimale. Celle-ci aura comme résultat de réduire le nombre de ligne de code, de simplifier l’implémentation d’une fonctionnalité et permettra de réutiliser certains concepts dans un autre but, sans avoir à modifier quoi que ce soit. Le singleton ne fait pas exception et peut être gérer au maximum de la généricité.

Prenons un cas concret, le cas d’une application qui doit utiliser de la journalisation (logging). Trois types de journalisations sont disponibles : Journal d’événement, Fichier .txt et Base de données. Chacun de ces types de journalisation héritent de certains comportements du parent, soit l’objet Journalisation.

Notre hiérarchie est donc la suivante :

Hiérarchie

Sachant que nous ne voulons qu’une seule instance de chacun des types de journalisation, il serait intéressant d’implémenter le singleton dans chacune des classe concrète de journalisation. Nous aurions donc le schéma suivant :

Singleton

Cette implémentation est bien, mais peut être encore améliorée.  Pourquoi ? L’action d’instancier un singleton est toujours la même.  Il serait donc intéressant de généraliser le comportement dans la classe parent en lui ajoutant l’instanciation unique d’un type de journalisation.  Le schéma obtenu serait donc :

Singleton générique

Maintenant toute cette belle réalisation théorique effectuée, il est temps de le coder… et de s’arracher les cheveux de la tête parce qu’on se rend compte bien vite que la création d’objet concret dans un objet abstrait est beaucoup plus complexe qu’on puisse le penser.  En détails, voici le problème : dans les technologies .NET, une instanciation doit être explicite, c’est-à-dire qu’on ne peux faire que des nouvelles instances de types connus, ou de types génériques ayant le marqueur d’instanciation.  On ne peut donc pas faire une instanciation d’un type enfant générique sans passer par l’utilisation de la réflexion.  Dans le cas qui nous intéresse, la classe Journalisation ne peut pas instancier aucun de ses enfants, puisqu’elle ne les connait pas du tout.

Ici-bas, on trouve la classe parent, qui gère l’instanciation du singleton :

public abstract class Journalisation<T> : where T : Journalisation
{
    #region Membres prives
    /// <summary>
    /// Singleton private member
    /// </summary>
    private T singleton;
    #endregion

    #region Singleton
    /// <summary>
    /// Implementation d'un singleton generique de journalisation
    /// </summary>
    public static T Instance
    {
        get
        {
            if (singleton == null)
            {
                singleton = (T)Activator.CreateInstance(typeof(T));
            }

            return singleton;
        }
    }
    #endregion

    #region Constructeurs
    /// <summary>
    /// Constructeur prive
    /// </summary>
    private Journalisation() { }
    #endregion
}

Et on trouve la classe enfant, qui se fait instanciée par le comportement hérité de son parent :

public class FichierTxt : Journalisation<FichierTxt>
{
    #region Constructeurs
    /// <summary>
    /// Constructeur prive
    /// </summary>
    private FichierTxt() : base() { }
    #endregion
}

De cette façon, tous les enfants pourront être des enfants de type singleton, sans avoir à gérer le comportement d’instanciation unique d’eux-même.

La généricité de cette solution permet d’isoler les responsabilités et assure une continuité et une facilité dans la maintenance d’une base de code.

Dans le prochain article, on améliorera le concept présent lors de son utilisation dans le contexte d’une requête HTTP.