Archives mensuelles : septembre 2013

ASP.NET MVC : Requetes Ajax multiples et Session

Dans une des applications dont je m’occupe, nous utilisons ASP.NET MVC (dans la version 3) dans une web application ou le contenu du site est mis à jour via des requêtes AJAX. J’ai remarqué que certaines actions pourtant rapide si effectuée seule, prenait beaucoup de temps lorsque celle-ci était effectuée après avoir lancée une autre action plus longue. L’application semblait comme bloquée pour la plupart des actions nécessitant le serveur.

Après analyse, j’ai vu qu’il s’agissait d’un problème lié à Session State.

Voici ce que dit la MSDN concernant Session State et les demandes simultanées.

Demandes simultanés et état de session
L’accès à l’état de session ASP.NET s’effectue exclusivement par session, ce qui signifie que si deux utilisateurs différents effectuent des demandes simultanées, l’accès à chaque session distincte est accordé simultanément. Toutefois, si deux demandes simultanées sont faites pour la même session (en utilisant la même valeur SessionID), la première demande a l’accès exclusif aux informations sur la session. La deuxième demande s’exécute uniquement après que la première demande est terminée. (La deuxième session peut également obtenir l’accès si le verrou exclusif sur les informations est libéré parce que la première demande dépasse le délai d’attente de verrouillage.) Si EnableSessionState de la directive @ Page a la valeur ReadOnly, une demande d’informations de session en lecture seule n’entraîne pas de verrouillage exclusif des données de session. Cependant, les demandes de données de session en lecture seule risquent encore de patienter jusqu’à ce qu’un verrouillage définit par une demande de données de session en lecture-écriture soit désactivé.

Voici un exemple montrant ce problème. J’ai créé un controller qui a 2 Actions de type JsonResult. Je simule un traitement long pour la méthode accédant à une variable en Session.

[SessionState(System.Web.SessionState.SessionStateBehavior.Default)]
public class AjaxController : Controller
{
	public JsonResult GetUserName()
	{
		//Simulate long process
		System.Threading.Thread.Sleep(3000);
		return Json(Session["Name"], JsonRequestBehavior.AllowGet);
	}

	public JsonResult GetUserCulture()
	{
		return Json(this.Request.UserLanguages", JsonRequestBehavior.AllowGet);
	}
}

Pour le test, Voici le code JavaScript qui utilise jQuery pour faire 2 requête AJAX (donc asynchrones). J’utilise console.time et console.timeEnd pour afficher dans la console de la barre d’outils, le temps d’exécution des appels AJAX.

console.time('GetUserName');
$.ajax({
    url: '/Home/GetUserName',
    success: function (response) {
        console.log(response);
        console.timeEnd('GetUserName');
    }
});

console.time('GetUserCulture');
$.ajax({
    url: '/Home/GetUserCulture',
    success: function (response) {
        console.log(response);
        console.timeEnd('GetUserCulture');
    }
});

Et voici le résultat par défaut. On peut voir que le résultat de l’appel à la méthode GetUserCulture prends pratiquement 3,5s !
SessionState Default

Nous allons modifier l’attribut SessionState du controller afin de lui indiquer que nous n’accédons qu’en lecture seule à la session. Ainsi les données de session ne seront plus verrouillées pour les méthodes du controler.

[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public class AjaxController : Controller

Le temps d’exécution de la méthode est de 540ms. Nous avons gagnés 3s qui était liées au traitement de la méthode GetUserName qui verrouillait la session.
SessionState ReadOnly

Comme vous pouvez le voir, cet attribut se positionne sur les classes (controller) et non sur les méthodes, ce que je ne trouve pas forcément optimal. Voici un lien qui permet de définir un attribut personnalisé permettant la configuration par action.

Chrome : Deboger votre android à distance

Le déclin du PC et la popularité croissante des tablettes / smartphones implique que les sites web doivent prendre en compte ce nouveau type de devices et leur contraintes (résolution, puissance, …). Le développement et le debogage pour ce type de device n’est pas aussi simple que cela ne peut l’être sur PC.

Voyons comment faire du débogage de site web sur un Android équipé de Chrome connecté en USB à un PC. (J’ai pu tester sous Windows 7 avec une tablette Samsumg Galaxy Tab 3 et sous Linux Ubuntu avec mon Samsung Nexus S, et cela fonctionne sans problème)

Installer ADB

ADB est l’extension Chrome qui permet de débugger votre appareil Android à distance.

Installer le driver de votre Android sous Windows

Sous windows, il faut installer le driver suivant le constructeur de votre android. Voici la page concernant l’installation d’un driver pour Android sous Windows.

Pour ma part, j’ai eu à installer le driver Samsung que l’on peut trouver ici.

Cela n’est pas nécessaire pour Linux ou Mac.

Activer le débogage USB sur votre android

Il faut ensuite activer le débogage via USB de votre téléphone ou tablette.

Pour cela, cela dépend de la version d’Android :

  • Pur les Android 3.2 et plus anciens, vous pouvez trouver l’option sous Paramètres > Applications > Développement.
  • Pour Android 4.0 et plus récent, Paramètres > Développeur.
  • A partir d’Android 4.2, les options développeurs sont cachés par défaut. Pour les rendre visible, il faut aller dans Paramètres > A propos du téléphone et tapper 7 fois sur le numéro de build. Retourner à l’écran précédent pour trouver les options Développeurs.

Il faut cocher l’option Débogage USB.

Activation du débogage USB

Activer le débogage USB dans Chrome

Il faut ensuite activer l’option dans Chrome (à partir de la version 28 ) via Paramètres > Avancés > Outils de développement et cocher Activer débogage USB pour le Web.

Activation debogage USB dans Chrome Android

Brancher votre Android en USB

Au branchement de votre appareil, il vous est demander d’autoriser votre machine à déboguer votre téléphone ou tablette. Cliquer sur OK.

Deboguer avec ADB

I l faut ensuite lancer ADB en cliquant sur Start ADB dans le menu d’ADB.

Lancement d'ADB

L’icone d’ADB indique alors le nombre de device connectés.

ADB : Device Connecté

Il faut ensuite cliquer sur View Inspection Targets pour afficher les éléments pour lesquels on peut effectuer un débogage à distance, dont les pages ouvertes dans Chrome de votre Android.

ADB : View Inspection Targets

Il suffit de cliquer sur inspect pour lancer le débogage d’une page.

ADB: Inspection Targets

La barre d’outils de développement sur le PC :

Developper Toolbar avec ADBChrome sous Android en mode débogage :

Debug dans Chrome Android

Référence

La page d’explication (en anglais) sur le portail développeurs de google.

Outils CSS3 – HTML5 – JavaScript : Episode 6

Une petite liste d’outils/librairies/… pour les développeurs web trouvés ici et là …

JavaScript

CSS

  • CSS3 Flexible Box Layout Explorer : Comprendre le layout flexbox de CSS3
  • Preboot : une collection de fonctions utiles (mixins, variables) pour less
  • CSS3 Click Chart : Exemple d’utilisation des propriétés CSS3
  • Stylify Me : Affichez facilement les couleurs, police, dimensions d’un site web.
  • Tridiv : Un éditeur CSS pour créer des formes 3D
  • CSSLisible : CSSLisible va réindenter vos blocks de code, ordonner vos propriétés, afin de fournir un code CSS Lisible et plus maintenable. Attention, les commentaires internes aux sélecteurs sont retirés !

HTML

Tout ce qu’il faut savoir les favicons

Font

Fontello : Un Générateur de police d’icône.

Divers

Une liste de points à vérifier lors de vos développements web :

DevDocs : un site regroupant la documentation pour HTML/CSS/JavaScript/DOM/JQuery/… bien fait avec la compatibilité par navigateur.

CSS : Tuile Responsive

J’ai dans un article précedent parler de responsive design afin d’adapter un site en fonction des devices des visiteurs. Nous allons voir comment faire des tuiles responsive.
Nous allons repartir de l’exemple d’un article précédent montrant comment tronquer du texte en CSS. L’exemple montrait des tuiles carrées. Nous allons adpater le design pour avoir des tuiles rectangulaire si la largeur est inférieure à 480px.

Une tuile est définie par un titre, une description et une image.
Le code html d’une tuile est le suivant :

<li>
<a class="tile" title="Partager avec un Ami" href="#">
<h1>Partager avec un Ami</h1>
<img src="share.png" alt="">
<p>Partager sur Twitter, Facebook, ...</p>
</a>
</li>

Voici le code CSS qui permet d’afficher les tuiles sous formes d’un carré.

div#home[role="main"] ul#tiles-panel li {
	display: inline-block;
	list-style: none outside none;
	margin: 0 8px 8px 0;
	vertical-align: top;
}

.tile {
	-moz-box-sizing: border-box;
	background: none repeat scroll 0 0 #F0F1F4;
	border-bottom: 3px solid #7B4F9D;
	display: inline-block;
	height: 176px;
	text-decoration: none;
	vertical-align: top;
	width: 176px;
}

.tile h1 {
	color: #253340;
	display: block;
	font-family: "Segoe UI",Segoe,"Trebuchet MS",Tahoma,Geneva,sans-serif;
	font-size: 20px;
	font-weight: 500;
	line-height: 148%;
	margin: 0;
	padding: 10px;
	text-decoration: none;
	white-space: nowrap;
	text-overflow : ellipsis;
	overflow : hidden;
	text-align : center;
}

.tile img {
	left: 50%;
	margin: 5px 0 10px -25px;
	position: relative;
}

.tile p {
	color: #6A747E;
	font-family: "Segoe UI",Segoe,"Trebuchet MS",Tahoma,Geneva,sans-serif;
	font-size: 13px;
	font-weight: 500;
	line-height: 148%;
	margin: 0;
	padding: 0 10px;
	text-align: center;
}

Voici la démo de cet écran sans adaptation.

On peut voir qu’avec un petit écran, cet affichage n’est pas du tout adapté. Nous allons le modifier afin d’optimiser l’affichage sur les petites résolutions. Pour cela, nous allons :

  • afficher les tuiles sous formes rectangulaires les unes à la suite des autres
  • réduire l’image et la placer à la gauche de la tuile

Voici le code qui permet d’adapter le résultat pour une utilisation pour petits écrans avec l’utilisation d’une média queries ciblant les écrans ayant une largeur maximum de 480px :

@media only screen and (max-width: 480px) {
    h1 {
	font-size : 24px;    
    }
	
    div[role=main]#home   ul#tiles-panel  li {
	display: block; /*passage en block pour affichage les uns en dessous des autres */
	position : relative;        
    }
	
    /*Tiles*/
    ul {
        padding : 0;   
    }
    
    .tile {
        width : 100%;
        height : 55px;    
        display : block;
        border-bottom : 0px;
        border-left: 3px solid #7B4F9D;
    }
	
    .tile  h1 {
        padding : 0;    
    }

    .tile  h1, .tile p {
        margin-left : 50px;    
    }
	
    .tile img {
        position: absolute;
        top : 5px;
        left : 5px;
        width : 45px;
        height : 45px;
        margin : 0 1px; 
    }
}

Et voici le résultat avant/après (utilisation de la vue adaptative de Firefox pour tester) :

Tuile non Responsive

Tuile Responsive

La page de démo

Dans cet exemple, j’utilise les mêmes images pour les 2 versions alors qu’il serait mieux d’avoir des images adaptées en fonction de la résolution, ce qu’on appelle responsive images. Il faut savoir qu’il sera bientôt possible de définir plusieurs sources d’image afin de gérer ce cas (via l’attribut srcset de la balise image ou via l’élément picture) et qu’il existe déjà des polyfills comme srcset-polyfill. Pour en savoir plus, je vous conseille responsiveimages.org.

ASP.NET : Augmentez la taille maximale des fichiers uploadés

J’ai rencontré un problème récemment concernant l’upload de gros fichier jusqu’au point d’avoir des erreurs 404 sur les plus gros alors que cela fonctionnait très bien pour des petits fichiers (Explications sur les erreurs 404 liés au limites de requêtes sur le site de IIS).

Il faut savoir qu’il y a 2 paramètres qui entre en compte dans la configuration de la taille maximale autorisée d’un fichier en ASP.NET. Cette configuration se fait dans le fichier de configuration de l’application web.config.

  • maxRequestLength (attribut de l’élément httpRunTime) qui indique la taille maximale de l’upload d’un fichier supporté par ASP.NET. La valeur par défaut est 4 096 Ko (soit 4 Mo)
  • maxAllowedContentLength qui spécifie la taille maximale du contenu d’une requête supporté par IIS. La valeur par défaut est 30000000 bytes (soit 28.6 Mo)

Il faut donc modifier ces 2 paramètres pour uploader des fichiers volumineux.

Attention : maxRequestLength est en ko alors que maxAllowedContentLength est en octet.