Inclure JQuery 2.x pour les fureteurs récents et 1.x pour les récalcitrants

L’équipe derrière JQuery a pris la décision de laisser tomber le support pour Internet Explorer 6, 7 et 8 dans la branche 2.x.

Pour l’explication officielle, veuillez consulter jQuery Core: Version 1.9 and Beyond. En voici un extrait:

There’s just one thing interfering with our vision of the future, and that’s the ghost of browsers past. Internet Explorer 6, 7, and 8–collectively, oldIE–have been a thorn in the side of web developers for a decade.

L’API de la branche 2.x est compatible avec l’API de la branche JQuery 1.9+ qui supporte toujours les vielles versions.

Our goal is for 1.9 and 2.0 to be interchangeable as far as the API set they support. When 2.0 comes out, your decision on which version to choose should be as simple as this: If you need IE 6/7/8 support, choose 1.9; otherwise you can use either 1.9 or 2.0.

Cependant, pour y arriver, cette branche doit faire plusieurs pirouettes et tours de magie et cela complique le code et rend plus difficile son évolution. Ou encore mieux formulé (par l’équipe de JQuery):

If jQuery 1.9 and 2.0 are basically the same API, what makes 2.0 compelling?

Smaller size, better performance, and the lack of problems introduced by the need for oldIE support. We expect that we can improve error handling in the $.Deferred implementation in 2.0, for example, whereas we can’t do that as long as oldIE is supported.

En tant que développeur, on veut souvent profiter des dernières améliorations nous permettant d’écrire du code concis, efficace et avec le moins de défaut possible. On veut aussi minimiser le nombre de tests à effectuer. Tester un site pour IE 11, IE 10, IE 9 et Chrome est déjà beaucoup. Si en plus il faut tester avec IE 8, IE7 et IE6, cela rend les choses encore plus compliquées.

Même les grosses compagnies avec de gros comptes de banque et beaucoup d’employés préfèrent supporter les fureteurs récents. Par exemple, Google a abandonné le support pour IE9 quelque temps après la sortie de IE 11:

Google Drops Support for IE9

Alors si vous souhaitez travailler avec les dernières versions des fureteurs et la dernière version de JQuery lors du développement mais garder une porte ouverte pour supporter les vieux fureteurs si on client l’exige, voici un petite recette.

Recette pour inclure automatiquement la dernière version de JQuery dans un application ASP.Net MVC

  1. Ajoutez la dernière version de JQuery 2.x à votre projet ainsi que la dernière version de JQuery 1.ximage
  2. Dans la classe BundleConfig, ajoutez deux bundles:
    public static void RegisterBundles(BundleCollection bundles)
    {
    bundles.Add(new ScriptBundle(« ~/bundles/jquery1 »).Include(« ~/Scripts/jquery-1* »));
    bundles.Add(new ScriptBundle(« ~/bundles/jquery2 »).Include(« ~/Scripts/jquery-2* »));
    (…)
  3. Définissez une vue partielle nommée _JQueryInclude.cshtml et contenant les 5 lignes suivantes:<!– Conditionally include jQuery version based on IE version –>
    <!–[if lt IE 9]>
    @Scripts.Render(« ~/bundles/jquery1 ») <![endif]–>
    <!–[if gte IE 9]><!–>
    @Scripts.Render(« ~/bundles/jquery2 ») <!–<![endif]—>
  4. Dans votre layout page ou à l’endroit où vous désirez inclure JQuery, utilisez:@Html.Partial(« _JQueryInclude »)

Et voilà! Si vos utilisateurs utilisent IE 6, IE 7 ou IE 8, les pages HTML utiliseront la branche 1.x de JQuery. Autrement, la version moderne de la branche 2.x sera utilisée.

Quelques nouveautés MVC 4

Je suis en train de lire le livre Programming ASP.NET MVC 4 de O’Reilly. Il y a vraiment beaucoup de nouveautés vis-à-vis MVC 3 mais ce que vous savez n’est pas perdu. Vous pouvez commencer par intégrer les nouvelles capacités à votre rhytme. Cet article vise à énumérer certains ajouts, il ne vise par à décrire toutes les nouveautés.

Razor V2

Les développeurs de Microsoft ont mis l’engin Razor à jour. Il faut l’activer dans le Web.Config

<appSettings>
<add key= »webpages:Version » value= »2.0.0.0″ />
<add key= »webpages:Enabled » value= »true » />

Razor V2: Résolution d’URL

Il n’y a pas tant d’ajouts mais ils sont pratiques. Par exemple, vous pouvez dire bye bye à @Url.Content ou @Href

<script src=”@Url.Content(“~/Scripts/myscript.js”)”></script>

devient:

<script src=”~/Scripts/myscript.js”></script>

Cela fonctionne pour tous les attributs, pas de traitement spécial!

<html data-root=”~/”>
$(document).data(‘root’)
en JQuery

Et avec une expression complexe:

<a href=”~/MySite/@Foo/Bar/@Baz”>Something!</a>

Razor v2: Simplifier le code fréquent

Mettre un attribut ou non selon une condition

<input type=”checkbox” checked=”@isChecked”>

Si isChecked est true:

<input type=”checkbox” checked=”checked”>

Sinon:

<input type=”checkbox”>

Mettre un attribut ou non si non null

@{ string foo = null; string bar = “bar” }
<div id=”foo” class=”@foo @bar”>

devient:

<div id=”foo” class=”bar”>

car foo est null (l’espace entre foo et bar est même enlevé!)

Exceptions:

  1. Les attributs data-<nom> car ceux-ci sont utilisés avec JQuery et doivent garder la notion de null
  2. Si la variable vaut String.Empty au lieu de null

Bundles

Ils ont ajouté la capacité de donner un nom à un ensemble de fichiers Scripts ou CSS et de les inclure au HTML en utilisant le nom. Cela crée une indirection et facilite la maintenance en permettant d’ajouter ou enlever des scripts à un seul endroit.

Objectifs

  1. Simplifier l’inclusion de scripts
  2. Combiner des fichiers pour réduire le nombre de connexions au serveur Web
  3. Minifier le contenu pour réduire la taille

Terminologie

  1. Bundling : Process of combining all the different JavaScript and CSS files into one file (one for JavaScript and one for CSS).
  2. Minification : Process of shrinking the JavaScript  and CSS content (removing all of the carriage returns,empty spaces,line feeds & shortening the variables  without changing actual functionality).

Fonctionnement

  1. Il y a un nouveau fichier pour configurer les bundles sous App_Start:

image

  • Pour déclarer un bundle de scripts:bundles.Add(new ScriptBundle(« ~/bundles/jquerylib« ).Include(« ~/Scripts/jquery-ui-{version}.js », « ~/Scripts/jquery.unobtrusive* », « ~/Scripts/jquery.validate.js », « ~/Scripts/additional-methods.js »));
  • Facilitants pour utiliser la dernière version{version} ou pattern matching (*) – détails plus loin
  • Pour inclure un bundle de scripts:@Scripts.Render(« ~/bundles/jquerylib »)
  • Pour déclarer un bundle de styles:bundles.Add(new StyleBundle(« ~/Content/themes/base/css »).Include(« ~/Content/themes/base/jquery.ui.core.css »,
    « ~/Content/themes/base/jquery.ui.resizable.css »,
    « ~/Content/themes/base/jquery.ui.tabs.css »,
    « ~/Content/themes/base/jquery.ui.theme.css »));
  • Pour inclure un bundle de styles:@Styles.Render(« ~/Content/themes/base/css »)

 

Notes sur le path virtuel (nom du bundle)

  1. Il est arbitraire mais ceux par défaut sont bizarres

You can also use, new StyleBundle(« ~/css ») and new ScriptBundle(« ~/script ») provided that you also need to change your Layout/Master file to match the new key(css/script) as Scripts.Render(« ~/script ») and Styles.Render(« ~/css », « ~/Content/css »). The fact is that the name must need to match.

  • Le path virtuel ne doit pas référer à un nom d’un fichier existant

    You also need to make sure that there is no file/directory exist with this new key(css/script).
  • Il fera partie de l’URL virtuel qui retourne le contenu du bundle

 

Facilitants: {version}

~/Scripts/jquery-ui-{version}.js

  1. Sélectionne la dernière version de JQuery du projet
  2. Prend la version complète en debug et la version .min autrement<system.web>
    <compilation debug= »true » targetFramework= »4.0″ />
  3. Fonctionne uniquement sur le nom des fichiers et fonctionne via une expression régulière. Je pensais qu’il dépendant du fichier packages.config géré par NuGet, mais cet article semble dire qu’il ne s’agit que d’une expression régulière sur les fichiers du projet ASP.Net.

Facilitants: *

~/Scripts/jquery.validate*

  1. Préfixe ou suffixe de la dernière partie du path
  2. Marche avec .Include et .IncludeDirectory
  3. Case-Insensitive

Exemple du HTML en release

<link href= »/Site/Content/css?v=-ag4GKGu1OPL0-OcBskTm1_ir8lgMDmnaLJg6M00Q-A1″ rel= »stylesheet »/>

<link href= »/Site/Content/themes/base/css?v=58KZ5iata6ouERaCYSZC3XN4JTpS9kDRB9t3LBZ1Ue81″ rel= »stylesheet »/>

<script src= »/Site/bundles/modernizr?v=rGcoDow97GYrNMSwHq7xCCjlcB3UIY4_OhPRc6BBSQA1″></script>

<link href= »/Site/Content/tablesorter/syntell/css?v=Gwg660DZtJBqCmEKqEhqrVLIAnDqfWVy95qmBX5OGCk1″ rel= »stylesheet »/>

Autres fonctionnalités

  1. Les contrôleurs peuvent être dans des répertoires différents
  2. Support pour les méthodes asynchrones du .NET 4.5
  3. Authentification via Oauth et OpenID (ex. Facebook)
  4. Séparation des classes dans App_Start (BundleConfig, FilterConfig, RouteConfig, WebApiConfig)
  5. Mode d’affichage: des vues différentes seront sélectionnées selon le fureteur faisant la requête
  6. Support le Azure SDK 1.6+
  7. MVC 4 inclus Entity Framework
  8. Projet de type Web APIimage
  9. Projet de type mobile (JQuery Mobile)image
  10. Le projet vide est maintenant vide, l’ancien s’appelle Basic
  11. Les gabarits par défaut ont un nouveau look et utilisent le rendu adaptif

Références

Bundling and Minification in ASP.NET MVC 4
http://theshravan.net/blog/bundling-and-minification-in-asp-net-mvc-4/

What’s new in Razor v2
http://vibrantcode.com/blog/2012/4/10/whats-new-in-razor-v2.html

What else is new in Razor v2?
http://vibrantcode.com/blog/2012/4/13/what-else-is-new-in-razor-v2.html

{version} wildcard in MVC 4 Bundle
http://stackoverflow.com/questions/12029161/version-wildcard-in-mvc4-bundle

ASP.NET 4.5, ASP.NET MVC 4, ASP.NET Web Pages 2, and Visual Studio 2012 for web developers: Part 1
http://weblogs.asp.net/jgalloway/archive/2012/08/16/asp-net-4-5-asp-net-mvc-4-asp-net-web-pages-2-and-visual-studio-2012-web-developer-features.aspx

Caractères accentués, ASP.Net MVC Razor et boutons de dialogue JQuery UI

Développeurs MVC francophones: avez-vous déjà eu des problèmes avec des caractères accentués dans les boutons d’un dialogue JQuery UI?

Afin de développer l’application Web en anglais et français, les libellés des boutons sont stockés dans des fichiers de ressources (*.resx).

Tout fonctionnait avec des boutons comme Sauvegarder, Annuler, OK etc. Mais tout à coup, la technique habituelle échoue avec un bouton Générer …

image

Et s’il n’y avait pas de guillement pour la clé (Gén&/233;rer: function() { … ), c’est pire car cela fera planter votre script.

La solution est d’utiliser la méthode @Html.Raw et d’entourer le résultat avec des guillements:

$(« #dlgGenerator »).dialog({
  autoOpen: false,
  width: 800,
  height: 600,
  resizable: false,
  modal: true,
  open: function(event, ui) {
    // Initialization
  },
  buttons: {
    « @Html.Raw(Global.LblGenerate) »: function() {
      $(« #cmdGenerateAssignments »).click();
    },
    « @Html.Raw(Global.LblCancel) »: function() {
      $(this).dialog(« close »);
    }
  }
});

image

Il est peut-être sage de vous protéger tout de suite d’un changement de libellé éventuel! L’utilisation de Html.Raw vous protège des caractères accentués tandis que l’utilisation des guillemets empêchera les erreurs de script dûes à la présence d’un espace ou caractère illégal.

À la prochaine fois,

Recette améliorée: Intégrer une application ASP.Net MVC sous un site Web IIS hébergeant WSS 3.0 / SharePoint 2007

L’avantage de la recette précédente c’est qu’elle était simple et exigeait peu de modification au Web.Config des applications ASP.Net MVC. Mais elle avait l’inconvénient majeur de faire échouer plusieurs soutions (ex. solution qui ajoute des Safe Controls) car l’API de SharePoint ne semble pas supporter les clauses <location path= ». »> d’IIS. Il fallait donc enlever les location du web.config, procéder à l’installation puis les remettre.

Voici donc la nouvelle recette (l’étape 5 est enlevée et l’étape 7 a été ajoutée):

  1. Vous devez créer un « Application Pool” utilisant le “.NET Framework 4.0” et empruntant la même identité (le même compte de service) que l’ “Application Pool” de SharePoint.Puisque le site IIS a un SPN unique (ex. HTTP/nomgentil.domaine.com), celui-ci est déjà défini sur le compte de service en question. Ainsi, il suffira d’ajouter la déléguation vers SQL Server ou SSAS à ce compte selon ce que fait l’application ASP.Net.
  2. Vous devez copier le répertoire de votre application ASP.Net sous le répertoire contenant SharePoint. Ex. C:\Inetpub\wss\nomgentil.domain.com\ApplicationMVC
  3. Les permissions par défaut ne sont pas les même que pour les sites placés directement sous C:\Inetpub alors assurez-vous de donner les permissions Windows à Users ou autre au répertoire de votre application MVC.
  4. Il faut convertir le virtual directory en application dans IIS en prenant bien soin d’utiliser le pool d’application défini précédemment.
  5. Une application ASP.Net utilise un fichier Web.Config afin de configurer différents éléments propres à .Net. Ce qu’il faut savoir c’est qu’il y a un lien d’héritage entre les Web.Config des applications Web. Ainsi si l’application B est placée sous l’application A dans IIS, elle hérite du Web.Config.Le problème c’est qu’en étant sous SharePoint, on hérite de certains éléments incompatibles avec une application utilisant le “.NET Framework 4.0”.

    On n’ajoute plus de clause <location> autour des noeuds SharePoint.

  6. On hérite aussi des “Handler Mappings” du site SharePoint et il y en a beaucoup. Il faut au moins enlever (dans l’application ASP.Net MVC) celui qui intercepte * et qui porte le nom AboMapperCustom-<numéro> pointant vers ASP.Net 2.0 (aspnet_isapi.dll). Autrement les images, CSS et autres fichiers statiques ne fonctionneront pas.image

    Cela aura pour effet d’ajouter ceci au web.config de votre application:

    <handlers>
    < remove name= »AboMapperCustom-3515455823″ />
    < /handlers>

  7. Les permissions du site MVC sont maintenant héritées du site SharePoint ce qui provoque une erreur dans l’application MVC. Il faut donc ajouter les permissions nécessaires en ajoutant l’élément <trust> dans le web.config de l’application. Ex. :

    <system.web>
    <trust level="Full" originUrl="" />
    </system.web>
  8. IIS Reset
  9. Si vous avez une erreur qui dit que le fichier de configuration n’est pas accessible, donnez temporairement les droits en lecture au groupe local IIS_IUSRS sur ce fichier (l’erreur indique le chemin d’accès).Quand IIS n’arrive pas à déterminer l’authentification utilisée (ex. il y a un nœud dupliqué dans les web.config parent et enfant), il doit avoir accès en mode anonyme. Après l’erreur qui sera affichée sera détaillée (ex. le nœud qui ne peut être redéfini etc.)
  10. Si vous avez une erreur HTTP 500 ou une page blanche, même avec customErrors à OFF, vous pouvez utiliser la fonctionnalité des Failed Request Tracing (FREB). Voici comment l’activer pour un site / application.

    Request Diagnostics HTTP 500

Si vous ne souhaitez pas donner FullTrust à l’application ASP.Net, vous devez:

  1. Ajouter:

    using System.Security;
    [assembly: AllowPartiallyTrustedCallers()]

    dans le fichier AssemblyInfo.cs des Dlls utilisés par votre application afin qu’ils acceptent d’être appelés dans un contexte limité ne permissions.

  2. Définir un fichier de policy listant toutes les permissions nécessaires à votre application (vous pouvez partir d’un fichier utilisé par SharePoint).
  3. Inclure le fichier spécifique en lui donnant un nom et y référer:

    <system.web>
      <securityPolicy>
        <trustLevel name= »MVCTrustLevel » policyFile= »<fullpath> » />
      </securityPolicy>
      <trust level= »MVCTrustLevel » originUrl= » » />
    </system.web>

Bonne chance et à la prochaine …

Références
Troubleshooting HTTP 500.19 Errors in IIS 7
http://blogs.iis.net/webtopics/archive/2010/03/08/troubleshooting-http-500-19-errors-in-iis-7.aspx

Recette améliorée: Intégrer une application ASP.Net MVC 3 sous un site Web IIS hébergeant SharePoint Server 2010

L’avantage de la recette précédente c’est qu’elle était simple et exigeait peu de modification au Web.Config des applications ASP.Net MVC. Mais elle avait l’inconvénient majeur de faire échouer plusieurs soutions (ex. solution qui ajoute des Safe Controls) car l’API de SharePoint ne semble pas supporter les clauses <location path= ». »> d’IIS. Il fallait donc enlever les location du web.config, procéder à l’installation puis les remettre.

Voici donc la nouvelle recette (l’étape 5 est enlevée et l’étape 8 a été ajoutée):

  1. Vous devez créer un “Application Pool” utilisant le “.NET Framework 4.0” et empruntant la même identité (le même compte de service) que l’ “Application Pool” de SharePoint.Puisque le site IIS a un SPN unique (ex. HTTP/nomgentil.domaine.com), celui-ci est déjà défini sur le compte de service en question. Ainsi, il suffira d’ajouter la déléguation vers SQL Server ou SSAS à ce compte selon ce que fait l’application ASP.Net.
  2. Vous pouvez copier le répertoire de votre application ASP.Net sous le répertoire contenant SharePoint. Ex. C:\Inetpub\wss\nomgentil.domain.com\ApplicationMVCNote: Vous pouvez le mettre ailleurs mais cela fonctionne très bien à cet endroit.
  3. Les permissions par défaut ne sont pas les même que pour les sites placés directement sous C:\Inetpub alors assurez-vous de donner les permissions Windows à Users ou autre au répertoire de votre application MVC.
  4. Il faut convertir le virtual directory en application dans IIS en prenant bien soin d’utiliser le pool d’application défini précédemment.
  5. Une application ASP.Net utilise un fichier Web.Config afin de configurer différents éléments propres à .Net. Ce qu’il faut savoir c’est qu’il y a un lien d’héritage entre les Web.Config des applications Web. Ainsi si l’application B est placée sous l’application A dans IIS, elle hérite du Web.Config.Le problème c’est qu’en étant sous SharePoint, on hérite de certains éléments incompatibles avec une application utilisant le “.NET Framework 4.0”. Les étapes 6, 7 et 8 vont travailler dans ce sens.

    On n’ajoute plus de clause <location> autour des noeuds SharePoint.

  6. Il faut déplacer l’élément Xml <sectionGroup> nommé “system.web.extensions” du Web.Config de SharePoint vers le Web.Config qui se trouve à cet endroit: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\Web.Config.

    On doit le mettre sous le noeud <configSections> directement sous <configuration>:

    <configuration>
    < configSections>
    <sectionGroup name= »system.web.extensions » …

    La raison est que le site ASP.Net MVC 3 .NET 4 hérite du Web.Config de SharePoint et ce sectionGroup cause une erreur. On ne peut pas utiliser l’élément <location> à cet endroit. En déplaçant la déclaration directement dans le Web.Config du .NET Framework 2.0, SharePoint en héritera mais pas notre application ASP.Net.

    Vous pouvez obtenir plus d’information ici. Un extrait:

    Move the configSections definition in the Web.config file of the parent application (the application that runs ASP.NET 2.0 or ASP.NET 3.5) into the root Web.config file for the.NET Framework 2.0. The IIS 7 and IIS 7.5 native configuration system scans the configSections element when it merges the hierarchy of configuration files. Moving the configSections definition from the parent Web application’s Web.config file to the root Web.config file effectively hides the element from the configuration merge process that occurs for the child ASP.NET 4 application.

  7. On hérite aussi des Modules du site SharePoint et ceux-ci causent une erreur (en particulier SharePoint14Module). La solution est d’utiliser ce noeud <modules> dans votre application ASP.Net:

    <modules runAllManagedModulesForAllRequests= »true »>
    < remove name= »SPRequestModule » />
    < remove name= »PublishingHttpModule » />
    < remove name= »RSRedirectModule » />
    < remove name= »StateServiceModule » />
    < remove name= »SharePoint14Module » />
    < add name= »Session » type= »System.Web.SessionState.SessionStateModule » />
    < /modules>

    Notez qu’en plus d’enlever les modules spécifiques à SharePoint, on réactive la gestion des Session. Si vous ne le faites pas, vous ne pourrez pas utiliser l’objet Session.

    En fait, comme on ne peut pas utiliser la clause <location> pour <system.webServer>, il faut défaire ce qui est fait par SharePoint. Il se peut que votre implantation nécessite d’activer / désactiver certains modules / “Http Handlers”. Voici un extrait de ce que SharePoint active / désactive:

    <modules runAllManagedModulesForAllRequests= »true »>
    < remove name= »AnonymousIdentification » />
    < remove name= »FileAuthorization » />
    < remove name= »Profile » />
    < remove name= »WebDAVModule » />
    < remove name= »Session » />
    < add name= »SPRequestModule » … />
    < add name= »ScriptModule »  … />
    < add name= »SharePoint14Module » … />
    < add name= »StateServiceModule » … />
    < add name= »RSRedirectModule » … />
    < add name= »PublishingHttpModule » … />
    < /modules>
    < handlers>
    < remove name= »OPTIONSVerbHandler » />
    < remove name= »WebServiceHandlerFactory-Integrated » />
    < remove name= »svc-Integrated » />
    < remove name= »WebDAV » />
    < add name= »svc-Integrated » … />
    < add name= »OwssvrHandler » … />
    < add name= »ScriptHandlerFactory » … />
    < add name= »ScriptHandlerFactoryAppServices » … />
    < add name= »ScriptResource » …  />
    < add name= »JSONHandlerFactory » … />
    < add name= »ReportViewerWebPart » … />
    < add name= »ReportViewerWebControl » … />
    < /handlers>

  8. Les permissions du site MVC sont maintenant héritées du site SharePoint ce qui provoque une erreur dans l’application MVC. Il faut donc ajouter les permissions nécessaires en ajoutant l’élément <trust> dans le web.config de l’application. Ex. :

    <system.web>
    <trust level="Full" originUrl="" />
    </system.web>
  9. IIS Reset
  10. Si vous avez une erreur qui dit que le fichier de configuration n’est pas accessible, donnez temporairement les droits en lecture au groupe local IIS_IUSRS sur ce fichier (l’erreur indique le chemin d’accès).

    Quand IIS n’arrive pas à déterminer l’authentification utilisée (ex. il y a un nœud dupliqué dans les web.config parent et enfant), il doit avoir accès en mode anonyme. Après l’erreur qui sera affichée sera détaillée (ex. le nœud qui ne peut être redéfini etc.)

  11. Si vous avez une erreur HTTP 500 ou une page blanche, même avec customErrors à OFF, vous pouvez utiliser la fonctionnalité des Failed Request Tracing (FREB). Voici comment l’activer pour un site / application.

    C’est ainsi que j’ai su qu’il me fallait désactiver le module SharePoint14Module:

    Request Diagnostics HTTP 500

Bref, oui c’est possible de mettre une application ASP.Net MVC 3 sous SharePoint 2010 mais il faut quand même effectuer un certain nombre de manipulations …

Si vous ne souhaitez pas donner FullTrust à l’application ASP.Net, vous devez:

  1. Ajouter:

    using System.Security;
    [assembly: AllowPartiallyTrustedCallers()]

    dans le fichier AssemblyInfo.cs des Dlls utilisés par votre application afin qu’ils acceptent d’être appelés dans un contexte limité ne permissions.

  2. Définir un fichier de policy listant toutes les permissions nécessaires à votre application (vous pouvez partir d’un fichier utilisé par SharePoint).
  3. Inclure le fichier spécifique en lui donnant un nom et y référer:

    <system.web>
      <securityPolicy>
        <trustLevel name= »MVCTrustLevel » policyFile= »<fullpath> » />
      </securityPolicy>
      <trust level= »MVCTrustLevel » originUrl= » » />
    </system.web>

Bonne chance et à la prochaine …

Comment impersonifier temporairement l’identité du AppPool en ASP.Net

Il est fréquent d’impersonifier l’identité du l’utilisateur dans une application ASP.Net MVC. L’application est personnalisée ou sécuritée par utilisateur ce qui nous empêche d’impersonifier un compte de service précis.

Normalement, avec une connaissance de Kerberos, il est facile de faire en sorte que l’identité de l’utilisateur voyage jusqu’aux différents serveurs de données (SQL Server, Analysis Services etc.).

Mais dans certains cas, la délégation Kerberos n’est pas envisageable. C’est en autre le cas pour l’API qui se trouve dans System.DirectoryServices. Cet API permet d’interroger Active Directory afin d’obtenir les groupes dont un utilisateur fait partie ou d’aller chercher des propriétés etc.

Même si cet API est en .NET, ça semble utiliser des fonctonnalités COM et il semblerait que la délégation Kerberos n’est pas supportée dans ce scénario. En effet, lors d’un Double Hop, l’erreur suivante est obtenue lors de l’utilisation des classes de System.DirectoryServices:

[COMException (0x80072020): An operations error occurred. ]

Le KB329986propose des solutions mais aucune ne nous semblait acceptable pour notre besoin (ex. utiliser l’authentification basique).

Heureusement, nos applications ASP.Net MVC s’exécutent sous un AppPool ayant une identité d’un compte de domaine (le même que pour SharePoint lorsque l’application MVC est hébergée sous SharePoint). Il est possible d’exécuter un bloc de code sous l’identité du compte de service du AppPool en utilisant:

using (HostingEnvironment.Impersonate()) {

// Ce code s’exécute avec l’identité
// assignée au pool d’application (AppPool)

DirectorySearcher searcher …
}

Il faut ajouter une référence àSystem.Web.dll et faire un usingSystem.Web.Hosting.

Cette technique a l’avantage de contrôler les lignes de code devant s’exécuter sous le compte du AppPool. Tout le reste peut continuer de s’exécuter sous l’identité de l’utilisateur du fureteur.

Dans le cas précis de l’accès à Active Directory, cette technique offre un autre avantage. Plutôt que d’avoir à donner accès en lecture à Active Directory à tous vos utilisateurs, vous pouvez accorder ce droit uniquement au compte de domaine assigné au AppPool.

Références

How to use the System.DirectoryServices namespace in ASP.NET

Quelles sont les compétences nécessaires pour être un bon développeur ASP.Net MVC?

Vous avez un projet pour une application Web incluant de la saisie de données? Vous cherchez des ressources internes ou externes pour réaliser la solution? Quelles sont les aptitudes techniques qui doivent être maîtrisées et du moins à apprendre par les ressources identifiées?

Plutôt que de créer une couche d’abstraction par dessus le DHTML, Microsoft a plutôt créé un environnement qui facilite sa génération. Ainsi, comme les technologies Web évoluent vite, les projets ASP.Net MVC peuvent en profiter immédiatement plutôt que d’attendre que la couche d’abstraction soit mise à jour.

Ainsi, il faut d’abord maîtriser les éléments suivants avant de se lancer dans le développement ASP.Net MVC:

Technologie Raisonnemment
HTML Le contenu des pages, une partie de la structure ainsi que les formulaires sont tous définis en HTML.
CSS Idéalement le formatage est défini dans des fichiers de styles externes afin de faciliter la maintenance et les changements importants de look.
JavaScript Peu de sites Web en 2012 n’ont pas besoin du JavaScript pour effectuer des validations, de la logique applicative ou de la transformation d’éléments HTML simples en contrôles interactifs.Ce code s’exécute sur le poste client (fureteur).
C# ou VB.Net Un projet ASP.Net est bâti en utilisant un language du .Net Framework. Il s’agit du code qui s’exécute sur le serveur et non sur le poste client.
SQL et base de données La plupart des projets ASP.Net se connectent sur des bases de données afin d’obtenir ou modifier de l’information. Un développeur doit connaître ces éléments.

Ensuite, il faudra prendre le temps d’apprendre les éléments suivants:

Technologie Raisonnemment
MVC Il s’agit d’une manière de structurer le projet, la logique applicative et le traitement des Urls.En bref:- Les modèles devraient contenir les classes qui représentent les données et la logique d’affaires de l’application à créer.

– Les vues savent comment afficher un modèle donné. Il peut s’agir de générer du HTML, du Xml, du JSON + JavaScript (ex. Sencha Charts). La vue connaît le modèle et sait comment référer aux controlleurs via des hyperliens.

– Les controlleurs sont appelés à partir des règles de “Routing”. La plomberie ASP.Net MVC va transformer un hyperlien en un appel de méthode dans une classe de controlleur avec une correspondance automatique des paramètres (et même leur conversion). Le rôle des controlleurs est d’obtenir tous les paramètres de la requête, d’aller chercher/ créer le modèle et de retourner une vue en lui passant le modèle.

Razor Avant “Razor”, on utilisait les “Web Form” et c’était difficile de distinguer le contenu HTML du code. Ce language permet de mixer du HTML et du code de manière optimale avec des @if, @switch, @foreach etc. On aime tout de suite ce langage en l’utilisant …
LINQ To SQL Microsoft a fait un excellent travail en créant LINQ qui évite d’avoir à concaténer des chaînes de caractères pour créer des requêtes SQL. Avec les “Nullable Types” (ex. int?, double?), le C# devient un langage de premier niveau pour du développement utilisant des bases de données.LINQ To SQL permet de créer une couche d’accès aux données simplement en important la définition des tables à partir de la base de données. Souvent le développeur ajoutera des méthodes à la classe DataContext (vive les classes partielles) qui seront des facilitants pour l’obtention, l’ajout et surtout la destruction des différentes entités. Mais on est loin de l’époque où il fallait écrire les couches de données à partir de zéro …

Cela fait déjà beaucoup de chose à apprendre. Mais ce n’est pas tout. En 2012, on ne peut plus afficher de simples contrôles Html (ListBox, TextBox etc.)

Les utilisateurs s’attendent à avoir des contrôles évolués tels que:

ListBox à sélection multiple:
image
http://www.quasipartikel.at/multiselect/

Calendrier avec l’heure:
image
http://trentrichardson.com/examples/timepicker/

Et c’est pourquoi je me dois d’ajouter JQuery à la liste des compétences nécessaires. Cette librairie permet de laisser le HTML le plus près possible de “ce qu’il représente” (ex. un ListBox à sélection multiple) et d’utiliser du JavaScript pour venir le transformer directement en un contrôle évolué. Souvent une seule ligne peut suffire:

$(‘#example1’).datetimepicker();

Bonne chance dans votre apprentissage ou votre recherche de candidats!

Intégrer une application ASP.Net MVC 3 sous un site Web IIS hébergeant SharePoint Server 2010

SharePoint Foundation / Server 2010 utilisent le .NET Framework 3.5. Même si le pool d’application indique 2.0, SharePoint charge la version 3.5.

image

Les projets de développement Web récents utilisent souvent ASP.Net MVC 3 avec le .NET Framework 4.0. J’avais donné la recette pour intégrer ce type de projet sous WSS 3.0 / SharePoint 2007 mais il y a quelques étapes qui sont différentes avec 2010. En bleu j’ai mis les nouveaux éléments et en orange ceux qui sont un peu différents. Les étapes qui ne sont pas nécesaires ont été enlevées tout simplement.

  1. Vous devez créer un “Application Pool” utilisant le “.NET Framework 4.0” et empruntant la même identité (le même compte de service) que l’ “Application Pool” de SharePoint.Puisque le site IIS a un SPN unique (ex. HTTP/nomgentil.domaine.com), celui-ci est déjà défini sur le compte de service en question. Ainsi, il suffira d’ajouter la déléguation vers SQL Server ou SSAS à ce compte selon ce que fait l’application ASP.Net.
  2. Vouspouvezcopier le répertoire de votre application ASP.Net sous le répertoire contenant SharePoint. Ex. C:\Inetpub\wss\nomgentil.domain.com\ApplicationMVCNote: Vous pouvez le mettre ailleurs mais cela fonctionne très bien à cet endroit.
  3. Les permissions par défaut ne sont pas les même que pour les sites placés directement sous C:\Inetpub alors assurez-vous de donner les permissions Windows à Users ou autre au répertoire de votre application MVC.
  4. Il faut convertir le virtual directory en application dans IIS en prenant bien soin d’utiliser le pool d’application défini précédemment.
  5. Une application ASP.Net utilise un fichier Web.Config afin de configurer différents éléments propres à .Net. Ce qu’il faut savoir c’est qu’il y a un lien d’héritage entre les Web.Config des applications Web. Ainsi si l’application B est placée sous l’application A dans IIS, elle hérite du Web.Config.Le problème c’est qu’en étant sous SharePoint, on hérite de certains éléments incompatibles avec une application utilisant le “.NET Framework 4.0”.

    Il faut donc modifier le web.config de SHAREPOINT pour indiquer qu’on ne souhaite pas hériter de certaines sections dans les sites enfants. Plus spécifiquement, il faut entourer les noeuds <microsoft.sharepoint.client>, <SharePoint>,  <system.web>, <System.Workflow.ComponentModel.WorkflowCompiler>, <ReportingServices>, <system.web.extensions>, <Bpm> et <reportserver> d’un noeud <location path=”.” inheritInChildApplications=”false”>. Par exemple:

    <location inheritinchildapplications= »false » path= ». »>
    <system.web>…</system.web>
    </location>

     

  6. Il faut maintenant déplacer l’élément Xml <sectionGroup> nommé “system.web.extensions” du Web.Config de SharePoint vers le Web.Config qui se trouve à cet endroit: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\Web.Config.

    On doit le mettre sous le noeud <configSections> directement sous <configuration>:

    <configuration>
    <configSections>
    <sectionGroup name= »system.web.extensions » …

    La raison est que le site ASP.Net MVC 3 .NET 4 hérite du Web.Config de SharePoint et ce sectionGroup cause une erreur. On ne peut pas utiliser l’élément <location> à cet endroit. En déplaçant la déclaration directement dans le Web.Config du .NET Framework 2.0, SharePoint en héritera mais pas notre application ASP.Net.

    Vous pouvez obtenir plus d’information ici. Un extrait:

    Move the configSections definition in the Web.config file of the parent application (the application that runs ASP.NET 2.0 or ASP.NET 3.5) into the root Web.config file for the.NET Framework 2.0. The IIS 7 and IIS 7.5 native configuration system scans the configSections element when it merges the hierarchy of configuration files. Moving the configSections definition from the parent Web application’s Web.config file to the root Web.config file effectively hides the element from the configuration merge process that occurs for the child ASP.NET 4 application.

  7. On hérite aussi des Modules du site SharePoint et ceux-ci causent une erreur (en particulier SharePoint14Module). La solution est d’utiliser ce noeud <modules> dans votre application ASP.Net:

    <modules runAllManagedModulesForAllRequests= »true »>
    <remove name= »SPRequestModule » />
    <remove name= »PublishingHttpModule » />
    <remove name= »RSRedirectModule » />
    <remove name= »StateServiceModule » />
    <remove name= »SharePoint14Module » />
    <add name= »Session » type= »System.Web.SessionState.SessionStateModule » />
    </modules>

    Notez qu’en plus d’enlever les modules spécifiques à SharePoint, on réactive la gestion des Session. Si vous ne le faites pas, vous ne pourrez pas utiliser l’objet Session.

    En fait, comme on ne peut pas utiliser la clause <location> pour <system.webServer>, il faut défaire ce qui est fait par SharePoint. Il se peut que votre implantation nécessite d’activer / désactiver certains modules / “Http Handlers”. Voici un extrait de ce que SharePoint active / désactive:

    <modules runAllManagedModulesForAllRequests= »true »>
    <remove name= »AnonymousIdentification » />
    <remove name= »FileAuthorization » />
    <remove name= »Profile » />
    <remove name= »WebDAVModule » />
    <remove name= »Session » />
    <add name= »SPRequestModule » … />
    <add name= »ScriptModule »  … />
    <add name= »SharePoint14Module » … />
    <add name= »StateServiceModule » … />
    <add name= »RSRedirectModule » … />
    <add name= »PublishingHttpModule » … />
    </modules>
    <handlers>
    <remove name= »OPTIONSVerbHandler » />
    <remove name= »WebServiceHandlerFactory-Integrated » />
    <remove name= »svc-Integrated » />
    <remove name= »WebDAV » />
    <add name= »svc-Integrated » … />
    <add name= »OwssvrHandler » … />
    <add name= »ScriptHandlerFactory » … />
    <add name= »ScriptHandlerFactoryAppServices » … />
    <add name= »ScriptResource » …  />
    <add name= »JSONHandlerFactory » … />
    <add name= »ReportViewerWebPart » … />
    <add name= »ReportViewerWebControl » … />
    </handlers>

     

  8. IIS Reset
  9. Si vous avez une erreur qui dit que le fichier de configuration n’est pas accessible, donnez temporairement les droits en lecture au groupe local IIS_IUSRS sur ce fichier (l’erreur indique le chemin d’accès).

    Quand IIS n’arrive pas à déterminer l’authentification utilisée (ex. il y a un nœud dupliqué dans les web.config parent et enfant), il doit avoir accès en mode anonyme. Après l’erreur qui sera affichée sera détaillée (ex. le nœud qui ne peut être redéfini etc.)

  10. Si vous avez une erreur HTTP 500 ou une page blanche, même avec customErrors à OFF, vous pouvez utiliser la fonctionnalité des Failed Request Tracing (FREB). Voici comment l’activer pour un site / application.

    C’est ainsi que j’ai su qu’il me fallait désactiver le module SharePoint14Module:

    Request Diagnostics HTTP 500

Bref, oui c’est possible de mettre une application ASP.Net MVC 3 sous SharePoint 2010 mais il faut quand même effectuer un certain nombre de manipulations …

Bonne chance et à la prochaine …

Comment désactiver AboMapperCustom-xxxxxxxxxx lors du déploiement d’une application ASP.Net MVC 3 sous SharePoint?

Dans mon billet “Intégrer une application ASP.Net MVC sous un site Web IIS hébergeant WSS 3.0 / SharePoint 2007” j’indiquais les étapes nécessaires au déploiement d’une application ASP.Net MVC 3 sous SharePoint. L’une d’entre elle était d’enlever manuellement une entrée des “Handler Mappings”. Le problème c’est que lorsqu’on redéploie l’application (ex. via le Publish de Visual Studio 2010), cette modification manuelle est perdue et il faut se rappeler de l’appliquer.

En cherchant une solution au problème j’ai trouvé une fonctionnalité qui ouvre la porte à d’autre possibilités: on peut appliquer une transformation au fichier web.config à partir d’un fichier de transformation (syntaxe xml). Cette configuration est appliquée au fichier web.config lors du déploiement.

Dès lors qu’on ajoute des configurations (par défaut nous avons Debug et Release) :

image

image

image

il est possible d’utiliser la commande “Add Config Transforms”:

image

Ce qui ajoute automatiquement un fichier de configuration qu’on peut ajuster à nos besoins.

image

On peut s’en servir pour changer les chaînes de connexion.

<connectionStrings>
<add
name= »TPMSDataEntryConnectionString »
providerName= »System.Data.SqlClient »
connectionString= »<Configuration Specific ConnStr> »
xdt:Transform= »SetAttributes »
xdt:Locator= »Match(name) »/>
</connectionStrings>

Mais on peut aussi s’en servir pour enlever le détestable AboMapperCustom-xxxxxxxxxx:

<system.webServer xdt:Transform= »Replace »>
<validation validateIntegratedModeConfiguration= »false »/>
<modules runAllManagedModulesForAllRequests= »true »/>
<handlers>
<remove name= »AboMapperCustom-3515455823″ />
</handlers>
</system.webServer>

Lorsque vous êtes prêt à publier votre application, il faut simplement vous souvenir de sélectionner la bonne configuration avant d’utiliser “Publish” ou “Build Deployment Package”

Allez consulter les articles dans mes références pour une introduction plus complète sur les fichiers de transformation ou pour obtenir la documentation du schéma.

Références

How to: Transform Web.config When Deploying a Web Application Project
http://msdn.microsoft.com/en-us/library/dd465318.aspx

Web.config Transformation Syntax for Web Application Project Deployment
http://msdn.microsoft.com/en-us/library/dd465326.aspx

Transforming Web.config For Different Environments
http://maperry2009.blogspot.ca/2010/03/transforming-webconfig-for-different.html

Intégrer une application ASP.Net MVC sous un site Web IIS hébergeant WSS 3.0 / SharePoint 2007

WSS 3.0 et MOSS 2007 utilisent le .NET Framework 2.0. Les projets de développement Web récents utilisent souvent ASP.Net MVC avec le .NET Framework 4.0. Il y a quelques éléments à configurer pour faire fonctionner une application ASP.Net 4.0 sous SharePoint. Voici la recette:

  1. Vous devez créer un « Application Pool” utilisant le “.NET Framework 4.0” et empruntant la même identité (le même compte de service) que l’ “Application Pool” de SharePoint.Puisque le site IIS a un SPN unique (ex. HTTP/nomgentil.domaine.com), celui-ci est déjà défini sur le compte de service en question. Ainsi, il suffira d’ajouter la déléguation vers SQL Server ou SSAS à ce compte selon ce que fait l’application ASP.Net.
  2. Vous devez copier le répertoire de votre application ASP.Net sous le répertoire contenant SharePoint. Ex. C:\Inetpub\wss\nomgentil.domain.com\ApplicationMVC
  3. Les permissions par défaut ne sont pas les même que pour les sites placés directement sous C:\Inetpub alors assurez-vous de donner les permissions Windows à Users ou autre au répertoire de votre application MVC.
  4. Il faut convertir le virtual directory en application dans IIS en prenant bien soin d’utiliser le pool d’application défini précédemment.
  5. Une application ASP.Net utilise un fichier Web.Config afin de configurer différents éléments propres à .Net. Ce qu’il faut savoir c’est qu’il y a un lien d’héritage entre les Web.Config des applications Web. Ainsi si l’application B est placée sous l’application A dans IIS, elle hérite du Web.Config.Le problème c’est qu’en étant sous SharePoint, on hérite de certains éléments incompatibles avec une application utilisant le “.NET Framework 4.0”.

    Il faut donc modifier le web.config de SHAREPOINT pour indiquer qu’on ne souhaite pas hériter de certaines sections dans les sites enfants. Plus spécifiquement, il faut entourer les noeuds <system.web> et <System.Workflow.ComponentModel.WorkflowCompiler> d’un noeud <location path= ». » inheritInChildApplications= »false »>. Par exemple:

    <location path= ». » inheritInChildApplications= »false »>
    <system.web>

    </system.web>
    </location>

  6. On hérite aussi des “Handler Mappings” du site SharePoint et il y en a beaucoup. Il faut au moins enlever (dans l’application ASP.Net MVC) celui qui intercepte * et qui porte le nom AboMapperCustom-<numéro> pointant vers ASP.Net 2.0 (aspnet_isapi.dll). Autrement les images, CSS et autres fichiers statiques ne fonctionneront pas.image

    Cela aura pour effet d’ajouter ceci au web.config de votre application:

    <handlers>
    <remove name= »AboMapperCustom-3515455823″ />
    </handlers>

  7. IIS Reset
  8. Si vous avez une erreur qui dit que le fichier de configuration n’est pas accessible, donnez temporairement les droits en lecture au groupe local IIS_IUSRS sur ce fichier (l’erreur indique le chemin d’accès).Quand IIS n’arrive pas à déterminer l’authentification utilisée (ex. il y a un nœud dupliqué dans les web.config parent et enfant), il doit avoir accès en mode anonyme. Après l’erreur qui sera affichée sera détaillée (ex. le nœud qui ne peut être redéfini etc.)

Références
Troubleshooting HTTP 500.19 Errors in IIS 7
http://blogs.iis.net/webtopics/archive/2010/03/08/troubleshooting-http-500-19-errors-in-iis-7.aspx