Liste d’ebooks gratuits

Voici une liste de Ebook gratuits classés par technologie:

ASP.NET MVC

HTML / CSS

Bootstrap

JavaScript

Lire la suite

[Asp.net MVC] – Obtenir l’url complète d’une image

Voici une méthode  d’Extension qui permet d’obtenir l’url complète d’une image (ou autre fichier)

public static class UrlExtensions
{
public static string AbsoluteContent(this UrlHelper urlHelper, string contentPath)
{
Uri requestUrl = urlHelper.RequestContext.HttpContext.Request.Url;
string absolutePath = string.Format("{0}{1}",
requestUrl.GetLeftPart(UriPartial.Authority),
urlHelper.Content(contentPath));
return absolutePath;
}
}

Et son utilisation :

Url.AbsoluteContent(« ~/media/image.jpeg ») 

retourne

http://domain/media/image.jpeg

Comment ne pas simplifier la vie aux pirates sur votre site ASP.NET MVC

Voici une capture d’écran de l’en-tête de la réponse HTTP envoyée par une application ASP.NET MVC hébergée par un serveur web IIS :

Capture de réponse HTTP

Comme on le voit, avec chaque requête à laquelle l’application répond sont envoyées un certain nombre d’informations concernant :

  • Server : le type de serveur hébergeant l’application, ainsi que sa version.
  • X-AspNet-Version : la version du moteur ASP.NET utilisé par l’application.
  • X-AspNetMvc-Version : la version spécifique d’ASP.NET MVC utilisée par l’application.
  • X-Powered-By : Le langage de programmation utilisé côté serveur.

Tout cela peut s’avérer extrêmement néfaste pour votre application! En effet, ces informations ne regardent personne, et surtout pas les pirates qui ne demandent rien de mieux que d’essayer de s’infiltrer par toutes les failles de sécurité concernées par ces technologies, et auxquelles votre serveur est susceptible d’être sensible s’il n’a pas été correctement mis à jour.

Pour vous donner une idée, cela revient à donner à un cambrioleur votre adresse ainsi que la marque et le modèle de votre serrure. Tout ce qui lui manque, c’est la forme de la clef.

Malheureusement, communiquer ces informations est le comportement par défaut de toute application ASP.NET MVC. Nous allons voir néanmoins comment modifier ce comportement pour faire disparaître ces données de nos en-têtes de réponse HTTP.

Commençons par le plus simple : pour retirer l’en-tête X-AspNetMvc-Version, il suffit de rajouter la ligne suivante dans la méthode Application_Start qui se trouve dans la classe MvcApplication de votre fichier Global.asax.cs.

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    // Ajoutez cette ligne :
    MvcHandler.DisableMvcResponseHeader = true;

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

Pour ce qui est des en-têtes X-AspNet-Version et X-Powered-By, il va vous falloir effectuer quelques modifications dans le fichier web.config à la racine de votre application web.

D’abord, s’il n’est pas encore présent, ajoutez un nœud « configuration/system.web/httpRuntime ». Pour désactiver l’en-tête X-AspNet-Version, ajoutez-y un attribut « enableVersionHeader » et donnez-lui la valeur « false ».

<system.web>
    <httpRuntime enableVersionHeader="false" />
    <!-- Ici le reste de la section system.web -->
</system.web>

Ensuite, pour supprimer l’en-tête X-Powered-By, rendez-vous dans la section « configuration/system.webServer ». S’ils ne sont pas encore présents, ajoutez-y la série de nœuds « httpProtocol/customHeaders », et adjoignez-y un nœud « remove » dont l’attribut « name » devra avoir la valeur « X-Powered-By ». Notez que comme pour tout ce qui a trait à la section « configuration/system.webServer », vous pouvez directement effectuer cette manipulation dans la console d’IIS 7.x.

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
    <!-- Ici le reste de la section system.webServer -->
</system.webServer>

L’en-tête Server est le cas le plus délicat. En effet, il est impossible de supprimer cet en-tête, que ce soit dans la configuration de notre application web, ou dans celle d’IIS. Pour arriver à nos fins, nous allons donc devoir intercepter la réponse HTTP avant que celle-ci soit envoyée au client, et la modifier.

Pour effectuer cette opération, nous allons altérer le pipeline de traitement de notre application web, en utilisant un HttpModule. Pour cela, il suffit de créer une classe héritant de IHttpModule. J’ai choisi d’appeler ma classe « CustomHeadersModule ». Nous devons d’ores et déjà implémenter les membres de l’interface « IHttpModule »; il s’agit des méthodes « Init » et « Dispose ». Vous pouvez laisser « Dispose » vide. Par contre dans « Init », nous allons nous abonner à l’évènement « PreSendRequestHeaders ».

public class CustomHeadersModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreSendRequestHeaders += OnPreSendRequestHeaders;
    }

    public void Dispose()
    {
    }

    private void OnPreSendRequestHeaders(object sender, EventArgs e)
    {
        HttpContext.Current.Response.Headers.Remove("Server");
        // Ou bien
        HttpContext.Current.Response.Headers.Set("Server", "Apache");
    }
}

Dans l’EventHandler qui va nous servir à nous abonner, nous allons pouvoir librement et au choix, soit supprimer complètement l’en-tête Server, soit plus sournoisement la modifier pour donner l’impression que nous utilisons en réalité une autre technologie de serveur web (ici en l’occurrence Apache, très populaire et principal concurrent d’IIS).

Il reste toutefois une action à effectuer : enregistrer ce HttpModule dans le pipeline de traitement de notre application ASP.NET MVC, ce qui se fait soit directement dans le console d’IIS, soit en modifiant à nouveau la section « configuration/system.webServer » de notre fichier web.config, cette fois-ci dans la sous-section « modules ».

<system.webServer>
    <modules>
        <add name="CustomHeadersModule" type="VotreNamespace.CustomHeadersModule" />
    </modules>
    <!-- Ici le reste de la section system.webServer -->
</system.webServer>

Toutes ces customisations vont contribuer à rendre votre application web plus sûre. Mais bien sûr, avoir un serveur web correctement mis à jour est encore le meilleur moyen de se prémunir des attaques de pirates.

Localiser la saisie utilisateur côté client dans ASP.NET MVC 3

Depuis la première version d’ASP.NET MVC, un des composants qui a subi le plus de modifications est sans doute la validation côté client. Au départ Microsoft avait développé sa propre librairie Javascript, avant de se tourner peu à peu vers jQuery, une librairie très populaire qu’ils ont choisi d’intégrer directement à leur solution.

Le contrecoup de ce revirement est que selon qu’une application est basée sur ASP.NET MVC 1, 2 ou 3, la validation côté client peut fonctionner selon des mécanismes assez différents. La localisation de cette validation en particulier peut s’avérer assez délicate à mettre en place.

La localisation de la validation dans ASP.NET MVC 3

Quand on parle de localisation de la validation, on ne fait pas seulement allusion au fait que les messages qui s’affichent soient dans la langue attendue, il s’agit aussi que les informations saisies par l’utilisateur soient validées selon les règles adéquates. Par exemple, que penser d’une application entièrement en français qui refuserait le nombre décimal « 5,5 » parce que celui-ci contient une virgule comme séparateur décimal? Ce n’est probablement pas ce à quoi s’attendraient la plupart des utilisateurs.

Avec ASP.NET MVC 3, parvenir à mettre en place cette localisation est un vrai parcours du combatant. En effet, tout repose maintenant sur le plugin jQuery Validation, qui utilise un système de « règles » pour valider la saisie utilisateur. Les règles fournies par défaut sont adaptées à la culture anglaise, et il faut les surcharger, c’est à dire les remplacer et les adapter, si l’on souhaite que notre application accepte de valider une culture différente.

Ce que fournit jQuery Validation

En standard, jQuery Validation fourni trois autres groupes de règles, pour les cultures allemande, néerlandaise et brésilienne. Mais non seulement celles-ci sont très incomplètes (la néerlandaise et la brésilienne ne surchargent que la règle de validation des dates) mais aucune ne colle à la culture française. Et voici ce que propose le fichier de règle pour la culture allemande :

/*
 * Localized default methods for the jQuery validation plugin.
 * Locale: DE
 */
jQuery.extend(jQuery.validator.methods, {
	date: function(value, element) {
		return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
	},
	number: function(value, element) {
		return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
	}
});

Les allemands utilisent bien la virgule comme séparateur décimal; en revanche ils utilisent le point comme séparateur de milliers (alors que nous utilisons un espace blanc). Bien sûr il serait facile de recopier le contenu de ce fichier avant de l’adapter, mais ce scénario n’est réaliste que si notre application n’est conçue que pour la langue française. Que faire si cette dernière est multilingue?

La librairie jQuery Globalization

L’intérêt récent de Microsoft pour jQuery les a amené à proposer leurs propres plugins : jQuery DataLink pour la liaison de données, jQuery Templates pour le templating et jQuery Globalization pour la localisation. Jusqu’à il y a peu, ces trois plugins, encore à l’état de béta version, étaient considérés par l’équipe jQuery comme des plugins « officiels ». Ce n’est plus le cas, toutefois les deux premiers plugins ont vu leur existence prolongée par leur créateur, sous la forme de JsRender et JsViews. Ils devraient être à terme inclus dans la librairie jQuery UI. Quand à jQuery Globalization, il était déjà très complet et parfaitement utilisable en production, et c’est heureux puisque nous allons nous en servir pour rendre notre application multilingue.

jQuery Globalization est composé de très nombreux fichiers correspondant à autant de cultures. Ces fichiers exposent les caractéristiques de chacune de ces cultures, ainsi que des fonctions permettant de traduire aussi bien les dates que les nombres décimaux, et bien plus encore.

Pour implémenter ce plugin dans une application web ASP.NET MVC 3, rien de plus simple. Après l’avoir téléchargé et placé dans notre solution, nous devons tout d’abord le référencer :

<script type="text/javascript" src="@Url.Content("~/Scripts/jquery/plugins/glob/jquery.global.js")"></script>

Ensuite nous devons charger dynamiquement le fichier de localisation correspondant à la culture de l’utilisateur, et configurer le plugin pour utiliser celui-ci :

<script type="text/javascript" src="@Url.Content("~/Scripts/jquery/plugins/glob/globinfo/jquery.glob." + Request.UserLanguages[0] + ".js")"></script>
<script type="text/javascript">
    jQuery.global.preferCulture("@Request.UserLanguages.ToCorrectCase()");
</script>

Request.UserLanguages est un tableau permettant d’obtenir côté serveur la liste des cultures configurées (par ordre de préférence) dans le navigateur de l’utilisateur. Vous vous demandez sans doute à quoi sert la fonction ToCorrectCase(). Malheureusement certain navigateurs comme Firefox renvoient « fr-fr » pour la langue française quand ils devraient renvoyer « fr-FR » (notez la différence de casse), et jQuery Globalization est sensible à ce détail; il faut donc s’y adapter et c’est à ça que sert cette fonction.

N’oubliez pas que les fichiers source de jQuery sont disponibles sur le CDN de Microsoft, tout comme de nombreux plugins.

Tout le nécessaire est maintenant en place pour permettre la localisation multilingue de notre application.

Comment relier jQuery Validation et jQuery Globalization

La dernière étape va consister à relier jQueryValidation, qui s’occupe de la mécanique de validation côté client de l’application, à jQuery Globalization, qui s’occupe exclusivement de la localisation.

Pour cela, nous devons faire référencer un nouveau fichier Javascript par notre application, et y ajouter le code suivant :

jQuery.extend(jQuery.validator.methods, {
    date: function (value, element) {
        return this.optional(element) || jQuery.global.parseDate(value) != null;
    },
    number: function (value, element) {
        return this.optional(element) || !isNaN(jQuery.global.parseFloat(value));
    },
    range: function (value, element, param) {
        value = jQuery.global.parseFloat(value);
        return this.optional(element) || (value &gt;= param[0] &amp;&amp; value &lt;= param[1]);
    }
});

Par le biais de ce code nous surchargeons trois règles de validation de jQuery Validation : la validation de la date, des nombres décimaux, et des intervalles. D’autres règles pourraient potentiellement être également surchargées.

Grâce à ce « pont » établi entre les deux plugins, jQuery Validation va maintenant se servir des fonctions de jQuery Globalization pour valider la saisie de l’utilisateur. Supposons que celui-ci doive indiquer quel sera le pourcentage de TVA sur un produit quelconque. La propriété correspondante dans le modèle de la vue ressemblerait à ceci :

/// <summary>
/// TVA applicable sur le produit
/// </summary>
[Range(0.0, 100.0)]
public double TVA { get; set; }

Notez que la règle de validation de nombre décimal est implicite dès lors qu’il s’agit d’un type « double » (nombre décimal à double précision).

Maintenant si par exemple l’utilisateur a son navigateur configuré dans la culture française, et qu’il saisit « 5,5 », nous serons en mesure de valider que ce nombre est dans un format décimal correct, et qu’il est compris dans une intervalle allant de 0 à 100. Notre application web est donc bien multilingue.