jeudi 6 août 2009

Windows Forms: Cycle de vie

Démarrage du formulaire :

System.Windows.Forms.Control.HandleCreated
System.Windows.Forms.Control.BindingContextChanged
System.Windows.Forms.Form.Load
System.Windows.Forms.Control.VisibleChanged
System.Windows.Forms.Form.Activated
System.Windows.Forms.Form.Shown


Fermeture du formulaire :

System.Windows.Forms.Form.Closing
System.Windows.Forms.Form.FormClosing
System.Windows.Forms.Form.Closed
System.Windows.Forms.Form.FormClosed
System.Windows.Forms.Form.Deactivate


Order of Events in Windows Forms
Consuming events
Events and Delegates

lundi 1 juin 2009

Ne pas déployer une application ASP.NET en production avec debug="true"

Si une application est déployée en production avec  <compilation debug="true"/> :

    1. La compilation des pages asp.net prend plus de temps (puisque certains batchs d'optimisation sont désactivés);
    2. Le code peut s'exécuter plus lentement (car des élements additionnels de debug sont activés);
    3. Utilisation d'avantage de mémoire au moment de l'exécution;
    4. Les scripts et images téléchargés depuis le handler WebResources.axd ne sont pas mis en cache.

Pour s'assurer qu'aucune application ne sera déployée en production avec <compilation debug="true"/> activé, il est possible d'utiliser l'élement <deployment> dans machine.config comme suit :

<configuration>
<
system.web>
<
deployment retail="true"/>
</
system.web>
</
configuration>

Ceci désactivera <compilation debug="true"/>, désactivera le traçage de sortie dans une page et desactivera la possibilité d'afficher le détail des messages d'erreur.

Source:

Don’t run production ASP.NET Applications with debug=”true” enabled


Plus d'infos:

http://www.aspdotnetfaq.com/Faq/What-does-deployment-retail-true-attribute-in-machine-config-file-means.aspx


http://msdn.microsoft.com/fr-fr/library/ms228298(VS.80).aspx

vendredi 8 mai 2009

Cycle de vie d'un logiciel

alpha => beta => RC (Release Candidate) => RTM (Release To Marketing) ....

http://en.wikipedia.org/wiki/Software_release_life_cycle

mardi 24 mars 2009

Formatage de la date en C#

lblMessage.Text = DateTime.Now.ToString();
Cette instruction affiche la date :

24/03/2009 12:46:54

Pour afficher cette date selon le format jj/MM/aaaa:

lblMessage.Text = DateTime.Now.ToString("dd/MM/yyyy");

Réference:
http://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo(VS.71).aspx

mercredi 18 mars 2009

Upload de fichiers avec asp.net 2.0 : taille du fichier

La taille maximale (par defaut) d'un fichier qu'on peut uploader est 4Mo. Il est cepandant possible d'augmenter cette taille si necessaire.

Le processus de travail (process worker) de asp.net dispose d'un espace virtuel de 2Go. Le processus de travail n'utilise que 1 Go.

La disponibilité de la mémoire, l'espace disponible sur le disque dur, la vitesse du processeur, le trafic réseau etc sont des facteurs qui définissent la taille maximale du fichier à uploader.

Avec un trafic réseau régulier, Microsoft recommande que la taille maximale du fichier à uploader soit de 10 à 20 Mo. Si l'upload se fait rarement, la taille maximale recommandée peut aller jusqu'à 100 Mo.

Comment changer la taille limite ?

Il y a 2 façons de procéder:

- effectuer des modifications dans le fichier web.config.comments (situé dans le dossier ASP.NET 2.0 configuration C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG);

- effectuer des modifications dans web.config de l'application.

Les modifications dans web.config.comments s'appliqueront sur toutes les applications d'upload, tandis que celles de web.config s'appliqueront à l'application seulement.

Dans le fichier web.config.comments, situez le noeud <httpRuntime> :

<httpRuntime 
executionTimeout="110"
maxRequestLength="4096"
requestLengthDiskThreshold="80"
useFullyQualifiedRedirectUrl="false"
minFreeThreads="8"
minLocalRequestFreeThreads="4"
appRequestQueueLimit="5000"
enableKernelOutputCache="true"
enableVersionHeader="true"
requireRootedSaveAsPath="true"
enable="true"
shutdownTimeout="90"
delayNotificationTimeout="5"
waitChangeNotification="0"
maxWaitChangeNotification="0"
enableHeaderChecking="true"
sendCacheControlHeader="true"
apartmentThreading="false" />





L'attribut maxRequestLength a la valeur 4096 octet: les 4 Mo par defaut. Il suffit de changer cette valeur pour augmenter la taille du fichier à uploader.



Pour augmenter la taille dans une application spéficique, il suffit de mettre ce noeud httpRuntime dans web.config de l'application, dans <system.web>.



L'augmentation de la taille peut augmenter l'impact des attaques sur le server en cas d'envoi d'un nombre massif de requêtes en même temps. Il est nécessaire de manipuler la taille max avec prudence au risque de trouver des milliers de requêtes de 10 Mo affluant sur le serveur.



References:



http://msdn.microsoft.com/en-us/kb/kb00323245.aspx



http://msdn.microsoft.com/en-us/library/aa479405.aspx

lundi 26 janvier 2009

Appeler une fonction JavaScript depuis code behind

Dans cet exemple, je montre de façon simple comment vérifier une valeur saisie par l'utilisateur en utilisant une fonction JavaScript exécutée du côté client.

Les contrôles de validation asp.net remplissent la même fonction, mais l'avantage d'utiliser JavaScript est la réduction de la taille de la page. Personnellement je préfère de loin les contrôles de validation puisqu'ils sont faciles à utiliser, à moins que de vouloir personnaliser votre validation, là il faut creuser un peu. Toutefois, je présente cette méthode car je pense qu'elle peut être utile dans certains cas...

Exemple :

image

L'utilisateur entre une valeur puis clique sur "Valider", une fonction JavaScript commée "ValiderSaisie" est alors appelée. La valeur "0" (zero) est considérée comme incorrecte.

La fonction "ValiderSaisie" est placée dans un fichier .js, celui-ci est appelé dans la page Validation.aspx. Voici la structure du projet (ne faites pas attention à la page Default.aspx):

image

La page Validation.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Validation.aspx.cs" Inherits="Validation" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<
script src="Control.js" type="text/javascript"></script>

<
html xmlns="http://www.w3.org/1999/xhtml">
<
head runat="server">
<
title>Test Validation</title>
</
head>
<
body>
<
form id="form1" runat="server">
<
table>
<
tr>
<
td>
<
asp:Label ID="Label1" runat="server" Text="Entrer une valeur :"></asp:Label>
</
td>
<
td>
<
asp:TextBox ID="txt1" runat="server" Width="120px" ></asp:TextBox>
</
td>
</
tr>
<
tr>
<
td>
&nbsp;
</td>
<
td>
<
asp:Button ID="cmdValider" runat="server" Height="26px" Text="Valider" Width="120px" />
</
td>
</
tr>
</
table>
</
form>
</
body>
</
html>

Notez l'appel du fichier "Control.js" en haut de la page. Dans ce fichier js, je place la fonction "ValiderSaisie" qui affiche toute valeur saisie, sauf pour zero où elle retourne le message "Valeur incorrecte" :

 function ValiderSaisie(MonTexte)
{
if (MonTexte.value == 0)
{
alert("Valeur incorrecte");
}
else
{
alert(MonTexte.value);
}
}

Appel de la fonction JavaScript:

Cet appel se fait en ajoutant un attribut au bouton "Valider" comme suit:

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
this.cmdValider.Attributes.Add("onclick", "javascript:return ValiderSaisie(document.getElementById('" + txt1.ClientID + "'));");
}

Résultat:

Si j'entre 0 j'obtiens ceci :

image

Autrement, la valeur entrée par l'utilisateur est affichée :

  image

vendredi 23 janvier 2009

Vérifier l'existance d'un QueryString

Si on essaie d'appeler un QueryString dans une page comme ceci:

Response.Write("id = " + Request.QueryString["id"].ToString());

... alors que celui-ci n'existe pas, on obtient l'erreur suivante:

La référence d'objet n'est pas définie à une instance d'un objet.



image



Il est nécessaire de contrôler l'existance d'un QueryString avant de l'utiliser:

Méthode 1: utiliser string.IsNullOrEmpty

if (string.IsNullOrEmpty(Request.QueryString["id"]))
{
Response.Write("id n'existe pas");
}
else
{
Response.Write("id = " + Request.QueryString["id"].ToString());
}



Méthode 2: contrôler manuellement si le QueryString existe

if (Request.QueryString["id"]!="" && Request.QueryString["id"]!=null)
{
Response.Write("id n'existe pas");
}
else
{
Response.Write("id = " + Request.QueryString["id"].ToString());
}

mercredi 21 janvier 2009

Executer le code d'un Bouton en pressant la touche Entrer

Petit exemple simple:

<div id="divTest" runat="server">
<
asp:TextBox ID="txtTest" runat="server"></asp:TextBox>
<
asp:Button ID="cmdGo" runat="server" Text="Go" OnClick="cmdGo_Click" />
</
div>

code du boutton: renvoie le texte tapé par l'utilisateur:

protected void cmdGo_Click(object sender, EventArgs e)
{
Response.Write(txtTest.Text);
}

Pour exécuter le code du bouton en pressant entrer, j'ai utilisé un Div à qui j'ai ajouté un id dans la page aspx. Dans Page_Load, ajouter un attribut à ce div: sur l'evenement onkeydown verifier le code de la touche pressée et lancer l'evenement click du boutton s'il s'agit de la touche entrer dont le code est 13 :

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
this.divTest.Attributes.Add("onkeydown", "if(event.which || event.keyCode){if ((event.which==13) || (event.keyCode==13)) {document.getElementById('" + cmdGo.UniqueID + "').click();return false;}} else {return true};");

}


Resultat :

image



Le div peut etre replacé par un table aussi. Il est preferable que le div ou table soit dans le niveau le plus haut possible de la page afin que son contenu "reconnaisse" que le boutton est lancé lorsque la touche Entrer est préssée.

Div avec ScrollBar (ascenseur)

Le bon vieux Div est toujours utile, mais peut l'être particulièrement lorsqu'on a par exemple un contrôle relié aux données qui peut s'étaler sur une bonne partie de la page.

Voici un exemple avec un contrôle CheckBoxList relié aux données, que je place dans un Div avec ascenseur afin de limiter l'espace occupé dans la page.

La propriété overflow permet de doter Div d'un ascenceur. Ici je lui affecte la valeur auto qui ajoute un ascenceur seulement si c'est necessaire:

<div style="width:150px; height: 200px; overflow: auto;">
<
asp:CheckBoxList ID="CheckBoxListFruits" runat="server" DataSourceID="SqlDataSourceFruits"
DataTextField="NomFrancais" DataValueField="IDFruit" Font-Names="Tahoma"
Font-Size="9pt" ForeColor="#000099">
</
asp:CheckBoxList>
</
div>

Le resultat est le suivant : image

jeudi 8 janvier 2009

Ajax UpdatePanel et l'Upload de fichiers

Le saviez-vous ? Certains contrôles ne sont pas compatibles avec UpdatePanel:

- TreeView et les contrôles Menu;
- Les contrôles Web Parts;
- FileUpload s'ils sont utilisés pour faire un upload de fichiers avec un PostBack asynchrone;
- GridView et DetailsView lorsque la propriété EnableSortingAndPagingCallbacks est true;
- Login, PasswordRecovery, ChangePassword et CreateUserWizard dont le Content n'a pas été converti en modèles éditables;
- Le contrôle Substitution;
- Les contrôles de validation.

En tout cas, je ne le savais pas avant de passer des heures à me tirer les cheveux pour comprendre ce qui n'allait pas dans ma page :) J'ai un WebForm avec des zones de saisie et un espace pour Upload de photos, tout marchait bien, mais dès que j'ai utilisé UpdatePanel j'ai obtenu l'erreur suivante:

Sys.WebForms.PageRequestManagerServerErrorException: Object reference not set to an instance of an object

erreur upload et updatepanel

La solution est la suivante: ajouter un PostBackTrigger sur le boutton qui déclenche l'Upload afin que ce boutton provoque un PostBack

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<
ContentTemplate>
<
asp:FileUpload ID="fileUpload" runat="server" />
<
br />
<
asp:Button ID="cmdUpload" runat="server" Height="25px" OnClick="cmdUpload_Click" Text="Upload"
Width="128px" />
</
ContentTemplate>

<
Triggers>
<
asp:PostBackTrigger ControlID
="cmdUpload" />
</
Triggers
>
</
asp:UpdatePanel>



L'Upload ensuite fonctionne correctement:

fileUpload.PostedFile.SaveAs(@"c:\test\" + System.IO.Path.GetFileName(fileUpload.PostedFile.FileName));


Response.Write n'est pas non plus compatible avec UpdatePanel, j'en parlerai dans un prochain post.