Custom ASP.NET MVC Project Template

Publié par Fabrice Michellonet sous le(s) label(s) , , le 21 juin 2011

Récemment, Phil Haack nous présentait dans un très bon post comment ajouter un template MVC3 personnalisé.

Dans ce post il lève le voile sur l'intégration de nuget dans Visual Studio. On y apprend que malheureusement par manque de temps l'intégration n'est que minimaliste et que seul les packages présent sur la machine (%ProgramFiles%\Microsoft ASP.NET\ASP.NET MVC 3\Packages) ne peuvent être installés.

Après avoir fait un peu joujou avec, voici quelques points complémentaires :

  • Pour télécharger un package nuget (extension nupkg), vous pouvez utiliser nuget package explorer

  • Il n'y a pas de résolution de dépendance entre package. Vous devez donc les ordonner dans la section WizardData :
    <WizardData>
        <packages>
            <package id="jQuery" version="1.5.1" />
            <package id="jQuery.Validation" version="1.8.0" />
            <package id="jQuery.UI.Combined" version="1.8.11" />
        </packages>
    </WizardData>
    

  • Les template de quickstart (plusieurs projets) fonctionnent dans cette configuration et peuvent tirer parti de l'installation de packages via nuget.

  • Il m'est arrivé a plusieurs reprise de noter que la commande
    devenv /installvstemplates
    
    ne suffisait a rafraichir le cache de template de Visual Studio. Un reboot de la machine remet tout dans l'ordre.

Happy Nuget!

Quickstart & Nuget

Publié par Fabrice Michellonet sous le(s) label(s) , , le 17 mai 2011

Dans mon précédent post j’effleurais le sujet des gains de productivité que pouvais procurer les templates et autres Quickstart dans vos développement de tous les jours.

Prenons le cas d’un Quickstart, qui je le rappelle n’est autre qu’une solution templatisée. Imaginons que l’on souhaite utiliser 3 ou 4 librairies externes .NET bien sentie et pourquoi pas une ou deux librairies javascript s’il s’agit d’une solution Web.

En m’appuyant sur Nuget lors de la création des templates de projet composant le Quickstart, les dépendances pourrons être facilement être mise à jour par les développeurs à posteriori toujours grâce à Nuget. Rien de magique dans tout ça, en fait chaque projet est doté de son propre fichier 'packages.config' (repository nuget pour le projet) relatant la version des librairies référencées.

Voici ce que j’aimerais mettre en place en plus :

  • Mise à jour automatique de nuget avant toute autre opération.
  • Téléchargement et installation automatisée des dépendances référencées pour chaque projet.
  • Mise à jour automatique des dépendances lors de la première installation.

Infos complémentaires :

Microsoft depuis le MVC3 Tool Update du 12 Avril 2011 propose un nouveau template de projet MVC3 basé lui aussi sur nuget. La technique utilisée est quelque peu différente de celle que je vous présente ici, mais ne permet pas la mise à jour automatique des dépendances à l’installation.

Je reviendrais surement très rapidement sur cette façon de faire dans un prochain billet.

Pour réaliser ces différents points il nous faudra coder un Wizard custom.

La première tâche consistant à déployer nuget.exe est simplissime. Il nous suffit de l’embarquer dans les ressources de notre Wizard, puis au runtime extraire l’exécutable et le copier par exemple dans le dossier « packages » au sein de la solution. Pour info, le dossier « package » est utilisé par nuget pour y stocker les dépendances qu’il a téléchargé.

DirectoryInfo packageDirInfo = _solutionDirInfo.CreateSubdirectory("packages");
string _nugetFilePath = Path.Combine(packageDirInfo.FullName, "Nuget.exe");
File.WriteAllBytes(_nugetFilePath, Resources.NuGet);

Notez que le dossier package doit absolument se trouvé dans le même répertoire que votre fichier sln, si vous voulez pouvoir profiter de la mise à jour des packages. Il s’agit d’une restriction imposé par nuget lui-même

Nuget déployé, il est possible de le mettre à jour automatiquement en exécutant la ligne de commande suivante :

nuget update

Dans notre Wizard on pourra utiliser le code suivant :

Process nugetProc = new Process
            {
                StartInfo = new ProcessStartInfo(_nugetFilePath)
                {
                    Arguments = "update",
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                },
            };
            nugetProc.Start();
            StreamReader output = nugetProc.StandardOutput;
            StreamReader error = nugetProc.StandardError;
            nugetProc.WaitForExit();

Concernant l’installation des dépendances de chaque projet se fera simplement en utilisant une fois de plus une ligne de commande ; que l’on créera en C# de la manière suivante :

Process nugetProc = new Process
            {
                StartInfo = new ProcessStartInfo(_nugetFilePath)
                {
                    Arguments = string.Format("install {0}", _packageFilePath),
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    WorkingDirectory = new FileInfo(_nugetFilePath).DirectoryName
                 },
            };
            nugetProc.Start();

L’idée ici est en fait d’exécuter 1 fois pour chacun de vos projets la commande suivante :

nuget install %path/to%/packages.config

Reste encore la tache de mettre à jour toutes les dépendances. Malheureusement, pour l’instant nuget.exe ne propose pas encore de commande permettant la mise à jour des dépendances. Cependant un récent post, Phil Haack annonce la disponibilité de cette option pour la version de 1.4 de nuget.

En attendant cette fonctionnalité, nous pouvons nous en sortir en installant par default le package NuGetPackageUpdater. Ce dernier vous offre la possibilité d’exécuter la commande 'Update-Package' qui se chargera d’effectuer la mise à jour de toutes les dépendances de la solution.

J’espère qu’en suivant ces instructions vous pourrez construire des Templates qui se mettrons à jour tout seul.

Pour ceux qui souhaiteraient jeter un coup d’œil plus approfondi au code que je viens de présenter, il est disponible sur Codeplex avec l’ensemble des briques du Quikstart Obsidian sur lequel je travaille actuellement.

Project Template, Quickstart et VSIX

Publié par Fabrice Michellonet sous le(s) label(s) le 13 mai 2011

Dernièrement j’ai fait mumuse avec les template de fichiers et projets que l’on peut créer dans Visual Studio.

coccinelle

Pour ceux qui ne connaissent pas, les template de fichier vous permettent de définir l’ossature d’un type de fichier que vous utilisez souvent. Une fois créé vous retrouverez votre template dans le menu de Visual Studio « Add new Item ».

Par extension les projects template vous permettent de définir la structure d’un type projet, afin de prendre en compte les conventions de votre équipe par exemple. Vous y définissez l’ensemble des fichiers présent dès la création du projet.

Ce qui est très intéressant, c'est que cela permet d'avoir des projets prêts à l'emploi dans votre environnement, avec par exemple NLog et votre conteneur DI préféré. Si vous êtes expérimenté cela vous évitera quelques copier-coller, si par contre vous ne connaissez pas bien une des briques technique cela vous évitera un tas de problématique.

Quoi qu'il en soit voici quelques astuces sur ces templates :


  1. Bien que le SDK de Visual Studio vous propose des projets de type Item Template et Project Template, le plus simple reste d’utiliser le menu File -> Export Template de Viual Studio pour générer votre précieux template.

  2. Pour créer un quickstart, qui n’est autre qu’un template de solution (plusieurs projets), je vous conseille de :

    1. Exporter vos différents projets template et extraire les archives zip correspondante dans un même dossier.

    2. Ajouter dans ce dossier de travail un fichier .vstemplate reprenant cette structure

    3. <VSTemplate Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="ProjectGroup">
        <TemplateData>
          <Name>Ma solution</Name>
          <Description>Ma description</Description>
          <ProjectType>CSharp</ProjectType>
          <ProjectSubType></ProjectSubType>
          <SortOrder>1000</SortOrder>
          <CreateNewFolder>false</CreateNewFolder>
          <LocationField>Enabled</LocationField>
          <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
          <Icon>monicone_100x100.ico</Icon>
        </TemplateData>
        <TemplateContent>
          <ProjectCollection>
            <ProjectTemplateLink ProjectName="Web">
              Web\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="Domain">
              Domain\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="DAL">
              DAL\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="IServices">
              IServices\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="Services">
              Services\MyTemplate.vstemplate
            </ProjectTemplateLink>
          </ProjectCollection>
        </TemplateContent>
      </VSTemplate>
      

      Vous pouvez y mettre autant de référence a des projects que vous le souhaitez en ajoutant des balises ProjectTemplateLink.

    4. Créez une archive zip du dossier de travail et placez la dans le dossier %VSInstallDir%\Common7\IDE\ProjectTemplates\. Après redémarrage de Visual Studio le nouveau template sera dispo.

  3. Dans le fichier vstemplate de votre Quickstart, la première occurrence à un projet sera par convention le startup project.

  4. Pour étendre avec du code custom vos project template il vous faudra :

    1. Créer une assembly et implémenter l’interface Microsoft.VisualStudio.TemplateWizard.IWizard

    2. Ajouter la balise WizardExtension dans le fichier .vstemplate de votre project template

    3. <VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
        …
        <WizardExtension>
          <Assembly>MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=952e5fc020f3b126</Assembly>
          <FullClassName>MyAssembly.Wizard</FullClassName>
        </WizardExtension>
      </VSTemplate>
      
  5. Il est possible de faire appel à une assembly custom dans un template de type quickstart, mais attention, la plupart des appels que vous ferez sur les objects EnvDTE et plus particulièrement EnvDTE.Project fréquemment utilisés dans la méthode IWizard. ProjectFinishedGenerating vous renverront des valeurs nulles.

  6. La façon la plus simple de créer un VSIX de déploiement est d’utiliser le projet de type VSIX Project (Visual C# -> Extensibility -> VSIX Project). Le SDK doit être installé.

  7. Dans le designer de VSIX, le champ ID comporte un GUID… n’y touchez surtout pas !

  8. Il est possible de définir dans quelle catégorie de template se trouvera l’élément que vous déployez via votre VSIX en renseignant le champ Add to subfolder.

  9. subfolder

Quickstart Telerik Extensions for ASP.NET MVC via Nuget

Publié par Fabrice Michellonet sous le(s) label(s) , le 31 mars 2011

Sans nul doute Nuget a grandement amélioré le process de déploiement/configuration/utilisation de bibliothèques tierces dans l'écosystème .NET.

Malheureusement, certain package ne sont pas parfait, et nécessite que l'on trifouille encore un peu dans la config pour que tout soit fonctionnel.
J'en ai personnellement fait l'expérience lorsque j'ai tenté d'utiliser les MVC Extensions de Telerik via Nuget, une excellente librairie de composants graphiques soit dit en passant.

Vous l'aurez compris, l'idée de ce post est de présenter les manipulations à faire pour pouvoir finaliser l'installation de la librairie de Telerik.

nuget  telerik mvc extensions

On commence par demander l'installation du package :

Install-Package TelerikMvcExtensions

Pas d'inquiétude, si cela prend un peu de temps, c'est normal; il y a un paquet de fichier a rapatrier puis à ajouter dans la solution.

Une fois que c'est fait, si vous ouvrez une vue, vous vous rendrez compte que malheureusement, l'intellisense ne vous propose rien de nouveau. Pire, s'il vous prenait l'envie de copier coller un exemple de code issue du site de Telerik, vous auriez un joli plantage.

Pour corriger tout ça, on va trifouiller dans le web.config. Ci-dessous les élèments à ajouter :


<configuration>
  <configSections>
    <sectionGroup name="telerik">
      <section name="webAssets" type="Telerik.Web.Mvc.Configuration.WebAssetConfigurationSection, Telerik.Web.Mvc" requirePermission="false" />
    </sectionGroup>

    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web>
    <pages>
      <namespaces>
        <add namespace="Telerik.Web.Mvc.UI" />
      </namespaces>
    </pages>

    <httpHandlers>
      <add verb="GET,HEAD" path="asset.axd" validate="false" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc" />
    </httpHandlers>
  </system.web>

  <system.webServer>

    <handlers>
      <remove name="asset" />
      <add name="asset" preCondition="integratedMode" verb="GET,HEAD" path="asset.axd" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc" />
    </handlers>

  </system.webServer>

  <telerik>
    <webAssets useTelerikContentDeliveryNetwork="false" />
  </telerik>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="Telerik.Web.Mvc.UI" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

</configuration>

Ouf! ca y est on a rajouté tout ce qu'il nous manquait.

En ouvrant de nouveau une vue, l'intellisense devrait se mettre a vous proposer de nouvelles choses dans le namespace Telerik. Parfois, l'intellisense reste muet et je n'ai pas trouvé d'autres alternatives que de redemarrer mon Visual Studio 2010.

Edit -- 18/04
Evidemment, il nous faut également modifier la master page afin d'y ajouter les styles et les scripts de Telerik.

<head>
    ...
    @(Html.Telerik().StyleSheetRegistrar().DefaultGroup(group => group.Add("telerik.common.css").Add("telerik.windows7.css").Add("telerik.rtl.css").Combined(true).Compress(true)))
</head>

</body>
@(Html.Telerik().ScriptRegistrar().Globalization(true).DefaultGroup(group => group.Combined(true).Compress(true)))
</html>

Ok, ok m'sieur Michellonet c'est bien beau tout ça, mais pourquoi j'irais utiliser la librairie de Telerik... en deux mots!

Tout simplement parce que la grille est géniale, elle a toutes les fonctionnalités que l'on peut attendre d'une grille Web 3.0 :p

Mercurial : Régler les problèmes de certificats SSL.

Publié par Fabrice Michellonet sous le(s) label(s) le 22 mars 2011

Ce n'est pas dans mon habitude de poster des conseils sur des outils et leur configuration, mais cette fois je vais faire une petite entorse au règlement; tout simplement car j'ai pas mal galéré pour résoudre ce soucis, et si ce post permet d'aider une seule personne alors cela en aura valu le coup.

Bref, depuis la version 1.7 le niveau de sécurité de Mercurial à été revu à la hausse, et donc évidement des petits tracas pour nous utilisateurs de Tortoise HG & Visual HG sous Windows. En résumé, les connexions HTTPS utilisant des certificats auto signés (Self-signed certificates) ne sont plus acceptés par le controleur de code source.

La documentation stipule qu'il est possible de rajouter dans le fichier cacert.pem de Tortoise le certificat que vous souhaitez autoriser; Le problème est qu'il va vous falloir utiliser openssl, non présent en standard sur un Windows. Je vous avouerais que je n'ai même pas tenté de le télécharger et de l'utiliser; Alors peut-être est-ce facilement faisable sous Windows... personnellement j'avais peur de me lancer dans une galère de plus.

Par contre, laissez-moi vous montrer une façon de faire beaucoup plus simple, pour nous Windowsien de base et tout aussi sécurisée.

L'idée est d'ajouter l'empreinte numérique du serveur hébergeant le repository dans la configuration de Tortoise; la doc étant un peu légère sur ce point, voici les étapes pour y arriver.

Bon, tout d'abord ouvrez votre navigateur préféré et rendez-vous sur la home page de votre repository. En cliquant sur le petit cadenas en bas de votre fenêtre vous devriez avoir une fenêtre comme celle-ci qui s'ouvre :

Certificat

Le bouton "afficher certifat" ouvre une nouvelle fenêtre dans laquelle vous copierez l'empreinte numérique SHA1. Cette empreinte identifie de manière unique le serveur hebergeant votre repository Mercurial.

Ensuite, ouvrez Tortoise hg Workbench, puis dans la fenêtre de configuration, éditez le fichier de configuration mercurial.ini.

Config

Il ne reste plus qu'à ajouter une section hostfingerprints reprenant l'adresse de votre server ainsi que son empreinte.

[hostfingerprints]
mercurial.devolis.com = ..:..:..:..:02:76:B5:29:65:47:A1:43:8E:0F:F5:13:03:AC:9D:0A

Voilà enregistrez le fichier et tout devrait désormais fonctionner comme avant.