Mon monde en .NET - ASP.NET2023-01-02T14:25:42+01:00Thierry Thouaurn:md5:feacb53e7f5d22db05e2d6025a495e81DotclearEvent avec arguments sous JQueryurn:md5:44830e50413ba0c2e77abc57e590d6032013-05-03T21:00:00+02:002013-05-03T21:00:00+02:00Thierry ThouaASP.NET<p>Il est parfois utile de pouvoir ajouter des arguments dans un event JQuery ... Voici comment le réaliser simplement ....</p> La première chose a réaliser et même la seule est d'avoir notre objet que l'on passera en premier argument de notre event Click. Dans ce cas-ci, nous avons une propriété "myValue" renvoyant un "Hello World"! ... Il suffit ensuite d'utiliser la propriété e.data.myValue pour récupérer notre valeur passée en argument. Voici l'exemple ....<div><pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;"><</span><span style="color:maroon;">html</span> <span style="color:red;">xmlns</span><span style="color:blue;">=</span><span style="color:blue;">"http://www.w3.org/1999/xhtml"</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">head</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">title</span><span style="color:blue;">>Hello world!</</span><span style="color:maroon;">title</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">script</span> <span style="color:red;">src</span><span style="color:blue;">=</span><span style="color:blue;">"Scripts/jquery-2.0.0.min.js"</span> <span style="color:red;">type</span><span style="color:blue;">=</span><span style="color:blue;">"text/javascript"</span><span style="color:blue;">></</span><span style="color:maroon;">script</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">script</span> <span style="color:red;">type</span><span style="color:blue;">=</span><span style="color:blue;">"text/javascript"</span><span style="color:blue;">></span>
$(<span style="color:blue;">function</span> () {
<span style="color:blue;">var</span> value = <span style="color:maroon;">"Hello World!"</span>;
$(<span style="color:maroon;">'#btn'</span>).click({ myValue: value }, HelloWorld);
});
<span style="color:blue;">function</span> HelloWorld(event) {
alert(event.data.myValue);
}
<span style="color:blue;"></</span><span style="color:maroon;">script</span><span style="color:blue;">></span>
<span style="color:blue;"></</span><span style="color:maroon;">head</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">body</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">input</span> <span style="color:red;">type</span><span style="color:blue;">=</span><span style="color:blue;">"button"</span> <span style="color:red;">id</span><span style="color:blue;">=</span><span style="color:blue;">"btn"</span> <span style="color:red;">value</span><span style="color:blue;">=</span><span style="color:blue;">"Hello"</span> <span style="color:blue;">/></span>
<span style="color:blue;"></</span><span style="color:maroon;">body</span><span style="color:blue;">></span>
<span style="color:blue;"></</span><span style="color:maroon;">html</span><span style="color:blue;">></span></pre></div>Tableau de 2000 lignes avec un bouton ... et la c'est le drame en ASP.NET ... Optimisons le tout !urn:md5:e3e501bf767e9103f99d3ad694cc7cf82013-04-10T22:33:00+02:002013-04-11T21:03:19+02:00Thierry ThouaASP.NETBeaucoup de personnes disent toujours que ASP.NET est lourd et ne génère pas de beau code HTML... Je reste persuadé que la mauvaise utilisation que l'on fait de ASP.NET pousse à ce genre de problème ... Voici un exemple simple ... Nous avons un cache objet à un certain endroit et nous avons une grille de 2000 lignes. Chaque ligne contient un simple libellé et un bouton qui exécutera une action sur cette ligne ... Nous pensons directement à Repeater / Label et Button ... Et la c'est le drame .... Nous avons un ViewState énorme et une page de très mauvaise qualité ... Il est donc temps de "penser" ... alors voici une autre idée ... <br /> Pourquoi ne pas créer un contrôle Web sans partir sur des CompositeControl mais plutôt sur un simple WebControl. Nous utilisons donc un div pour l'exemple .... <br /><div><pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">CustomWebControl</span> : <span style="color:#2b91af;">WebControl</span>
{
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:#2b91af;">HtmlTextWriterTag</span> TagKey
{
<span style="color:blue;">get</span> { <span style="color:blue;">return</span> <span style="color:#2b91af;">HtmlTextWriterTag</span>.Div; }
}
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> RenderContents(<span style="color:#2b91af;">HtmlTextWriter</span> writer)
{
<span style="color:blue;">base</span>.RenderContents(writer);
}
}</pre></div><div>La seconde étape est de générer notre code HTML.</div><div><pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">CustomWebControl</span> : <span style="color:#2b91af;">WebControl</span>
{
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:#2b91af;">HtmlTextWriterTag</span> TagKey
{
<span style="color:blue;">get</span> { <span style="color:blue;">return</span> <span style="color:#2b91af;">HtmlTextWriterTag</span>.Div; }
}
<span style="color:blue;">public</span> <span style="color:#2b91af;">MySource</span> DataSource
{
<span style="color:blue;">get</span> { <span style="color:blue;">return</span> (<span style="color:#2b91af;">MySource</span>)<span style="color:blue;">this</span>.ViewState[<span style="color:#a31515;">"DataSource"</span>]; }
<span style="color:blue;">set</span> { <span style="color:blue;">this</span>.ViewState[<span style="color:#a31515;">"DataSource"</span>] = <span style="color:blue;">value</span>; }
}
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> RenderContents(<span style="color:#2b91af;">HtmlTextWriter</span> writer)
{
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Type, <span style="color:#a31515;">"text"</span>);
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Value, <span style="color:blue;">this</span>.DataSource.Name);
writer.RenderBeginTag(<span style="color:#a31515;">"input"</span>);
writer.RenderEndTag();
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Type, <span style="color:#a31515;">"button"</span>);
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Value, <span style="color:#a31515;">"Hello!"</span>);
writer.RenderBeginTag(<span style="color:#a31515;">"input"</span>);
writer.RenderEndTag();
<span style="color:blue;">base</span>.RenderContents(writer);
}
}</pre></div><div>La dernière étape revient a utiliser l'interface IPostbackEventHandler. Celle-ci nous offre la gestion du PostBack.<br style="color: rgb(43, 145, 175); font-family: 'Courier New', Courier, monospace; font-size: 1.1em; background-color: white;" /></div><div><pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;">public</span> <span style="color:blue;">class</span> <span style="color:#2b91af;">CustomWebControl</span> : <span style="color:#2b91af;">WebControl</span>, <span style="color:#2b91af;">IPostBackEventHandler</span>
{
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:#2b91af;">HtmlTextWriterTag</span> TagKey
{
<span style="color:blue;">get</span> { <span style="color:blue;">return</span> <span style="color:#2b91af;">HtmlTextWriterTag</span>.Div; }
}
<span style="color:blue;">public</span> <span style="color:#2b91af;">MySource</span> DataSource
{
<span style="color:blue;">get</span> { <span style="color:blue;">return</span> (<span style="color:#2b91af;">MySource</span>)<span style="color:blue;">this</span>.ViewState[<span style="color:#a31515;">"DataSource"</span>]; }
<span style="color:blue;">set</span> { <span style="color:blue;">this</span>.ViewState[<span style="color:#a31515;">"DataSource"</span>] = <span style="color:blue;">value</span>; }
}
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> OnPreRender(<span style="color:#2b91af;">EventArgs</span> e)
{
<span style="color:blue;">base</span>.OnPreRender(e);
<span style="color:blue;">this</span>.Page.RegisterRequiresRaiseEvent(<span style="color:blue;">this</span>);
}
<span style="color:blue;">protected</span> <span style="color:blue;">override</span> <span style="color:blue;">void</span> RenderContents(<span style="color:#2b91af;">HtmlTextWriter</span> writer)
{
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Type, <span style="color:#a31515;">"text"</span>);
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Value, <span style="color:blue;">this</span>.DataSource.Name);
writer.RenderBeginTag(<span style="color:#a31515;">"input"</span>);
writer.RenderEndTag();
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Type, <span style="color:#a31515;">"button"</span>);
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Value, <span style="color:#a31515;">"Edit!"</span>);
writer.AddAttribute(<span style="color:#2b91af;">HtmlTextWriterAttribute</span>.Onclick,
<span style="color:blue;">this</span>.Page.ClientScript.GetPostBackEventReference(<span style="color:blue;">this</span>, <span style="color:#a31515;">"Edit;"</span> + <span style="color:blue;">this</span>.DataSource.Id));
writer.RenderBeginTag(<span style="color:#a31515;">"input"</span>);
writer.RenderEndTag();
<span style="color:blue;">base</span>.RenderContents(writer);
}
<span style="color:blue;">public</span> <span style="color:blue;">void</span> RaisePostBackEvent(<span style="color:blue;">string</span> eventArgument)
{
}
}</pre></div><div>Il est dès lors possible d'ajouter sur notre contrôle un event et de le lancer dans la méthode RaisePostBackEvent. N'ayant pas besoin de ViewState, on peut très bien au Load de la page remplir le Datasource d'un Repeater ... Le rendu sera parfait et on supportera la fonctionnalité ...</div><div><pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;"><</span><span style="color:maroon;">asp</span><span style="color:blue;">:</span><span style="color:maroon;">Repeater</span> <span style="color:red;">runat</span><span style="color:blue;">=</span><span style="color:blue;">"server"</span> <span style="color:red;">ID</span><span style="color:blue;">=</span><span style="color:blue;">"repeater"</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">ItemTemplate</span><span style="color:blue;">></span>
<span style="color:blue;"><</span><span style="color:maroon;">cc1</span><span style="color:blue;">:</span><span style="color:maroon;">CustomWebControl</span> <span style="color:red;">ID</span><span style="color:blue;">=</span><span style="color:blue;">"control"</span> <span style="color:red;">runat</span><span style="color:blue;">=</span><span style="color:blue;">"server"</span> <span style="color:red;">EnableViewState</span><span style="color:blue;">=</span><span style="color:blue;">"False"</span> <span style="color:blue;">/></span>
<span style="color:blue;"></</span><span style="color:maroon;">ItemTemplate</span><span style="color:blue;">></span>
<span style="color:blue;"></</span><span style="color:maroon;">asp</span><span style="color:blue;">:</span><span style="color:maroon;">Repeater</span><span style="color:blue;">></span></pre></div><div>Ceci termine ce petit article... Il offre la possibilité si le contrôle est un affichage de données sans modification de s'abstraire facilement du ViewState,de réduire le code HTML généré et d'éviter une profusion de contrôle ASP.NET sur une page ... En effet, il ne faut pas oublier qu'il y a par défaut une limite (modifiable dans la config mais si ce n'est pas indispensable ...) ...</div>Custom WebControl avec des events en Javascripturn:md5:07663034892d904f93b56c527b8656fd2013-02-25T19:30:00+01:002013-02-25T19:37:29+01:00Thierry ThouaASP.NET<p>Après avoir expliqué comment réaliser un contrôle custom ASP.NET dans un précédent post, nous allons expliquer comment ajouter des "events" dans nos classes. Cela nous permettra de nous abonner et de réaliser des actions en conséquence.</p> <p>Pour ce faire, il faut rajouter un event dans notre code embedded JavaScript.</p>
<pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;">_onchange: <span style="color:blue;">function</span> (e) {
<span style="color:blue;">var</span> value = parseFloat(e.target.value);
<span style="color:blue;">var</span> isIncorrect = <span style="color:blue;">false</span>;
<span style="color:blue;">if</span> (isNaN(value) || !isFinite(value)) {
isIncorrect = <span style="color:blue;">true</span>;
}
isIncorrect = isIncorrect || value > 100 || value < 0;
<span style="color:blue;">if</span> (isIncorrect) {
<span style="color:blue;">if</span> (<span style="color:blue;">this</span>._errorCssClass !== <span style="color:blue;">null</span> && <span style="color:blue;">this</span>._errorCssClass !== <span style="color:maroon;">''</span>) {
<span style="color:blue;">this</span>.addCssClass(<span style="color:blue;">this</span>._errorCssClass);
}
}
<span style="color:blue;">else</span> {
<span style="color:blue;">this</span>.removeCssClass(<span style="color:blue;">this</span>._errorCssClass);
}
<span style="color:blue;">this</span>._throw_change(isIncorrect);
},</pre>
<pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;">add_change: <span style="color:blue;">function</span> (handler) {
<span style="color:blue;">this</span>.get_events().addHandler(<span style="color:maroon;">'change'</span>, handler);
},
remove_change: <span style="color:blue;">function</span> (handler) {
<span style="color:blue;">this</span>.get_events().removeHandler(<span style="color:maroon;">'change'</span>, handler);
},</pre>
<p><pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;">_throw_change: <span style="color:blue;">function</span> (eventArgs) {
<span style="color:blue;">var</span> handler = <span style="color:blue;">this</span>.get_events().getHandler(<span style="color:maroon;">'change'</span>);
<span style="color:blue;">if</span> (handler) handler(<span style="color:blue;">this</span>, eventArgs);
}</pre></p>
<p>Ensuite, nous allons enregistrer une action à exécuter au load. Ce code JavaScript doit se situer obligatoirement en dessous du ScriptManager. </p>
<pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;"><</span><span style="color:maroon;">asp</span><span style="color:blue;">:</span><span style="color:maroon;">ScriptManager</span> <span style="color:red;">ID</span><span style="color:blue;">=</span><span style="color:blue;">"ScriptManager1"</span> <span style="color:red;">runat</span><span style="color:blue;">=</span><span style="color:blue;">"server"</span> <span style="color:blue;">/></span>
<span style="color:blue;"><</span><span style="color:maroon;">script</span> <span style="color:red;">type</span><span style="color:blue;">=</span><span style="color:blue;">"text/javascript"</span> <span style="color:red;">language</span><span style="color:blue;">=</span><span style="color:blue;">"javascript"</span><span style="color:blue;">></span>
Sys.Application.add_load(LoadEvents);
<span style="color:blue;"></</span><span style="color:maroon;">script</span><span style="color:blue;">></span></pre>
<pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;">function</span> LoadEvents() {
<span style="color:blue;">var</span> elt = $find(<span style="color:maroon;">"UserControlTest1_PercentageControl1"</span>);
elt.add_change(OnChange);
}</pre>
<p>Nous pouvons maintenant au load nous abonner à l'event et réaliser une action. Ici nous souhaitons par exemple désactiver le bouton si la valeur de la textbox est invalide. Cela évite tout click (et donc retour serveur etc) en cas d'erreur d'input. </p>
<pre style="font-family: Consolas; font-size: 13px; background-color: white; background-position: initial initial; background-repeat: initial initial;"><span style="color:blue;">function</span> OnChange(source, eventArgs) {
<span style="color:blue;">var</span> elt = $get(<span style="color:maroon;">"UserControlTest1_Button1"</span>);
elt.disabled = eventArgs === <span style="color:blue;">true</span> ? <span style="color:blue;">true</span> : <span style="color:blue;">false</span>;
}</pre>
<p>Nous pouvons tester et nous voyons bien notre bouton se désactiver lorsque l'on encode une lettre de l'alphabet ou un pourcentage qui n'entre pas dans le range supporté (à savoir entre 0 et 100).</p>Création d'un Custom WebControl avec du JavaScript embeddedurn:md5:73ea0518a477f33e5446bd87879da8782012-06-23T23:37:00+02:002012-06-25T12:08:24+02:00Thierry ThouaASP.NET<p>Mon précédent article expliquait comment réaliser simplement un contrôle en prenant un peu la main sur ce qui se faisait en ASP.NET et en simplifiant les propriétés pour coller plus au besoin réel. Nous continuons dans cette direction mais en offrant maintenant à notre contrôle de nouvelles options. Nous ne voulons pas toujours exécuter toutes les validations côté serveur... En effet, certaines sont simples et peuvent s'effectuer sur le poste client. Par exemple ici, un pourcentage est toujours compris entre 0 et 100. Nous devons donc changer notre classe pour lui ajouter un "support" du JavaScript. Ce support permettra d'avoir une classe JavaScript de définie et instanciée pour chaque contrôle de ce type rendu à l'écran. Nous mettrons le border en rouge si la valeur encodée dans la textbox est incorrecte.<br _moz_editor_blogus_node="TRUE" _moz_dirty="" /></p> <p>La première étape est d'ajouter l'interface IScriptControl (qui se trouve dans la dll System.Web.Extensions) sur notre classe pourcentage.</p>
<p>[<span style="COLOR: #2b91af">DefaultProperty</span>(<span style="COLOR: #a31515">"Value"</span>)]<br />[<span style="COLOR: #2b91af">ToolboxData</span>(<span style="COLOR: #a31515">"<{0}:PercentageControl runat=server></{0}:PercentageControl>"</span>)]<br />[<span style="COLOR: #2b91af">ToolboxBitmap</span>(<span style="COLOR: blue">typeof</span>(<span style="COLOR: #2b91af">PercentageControl</span>), <span style="COLOR: #a31515">"Percentage.bmp"</span>)]<br /><span style="COLOR: blue">public</span> <span style="COLOR: blue">class</span> <span style="COLOR: #2b91af">PercentageControl</span> : <span style="COLOR: #2b91af">WebControl</span>, <span style="COLOR: #2b91af">IPostBackDataHandler</span>, <span style="COLOR: #2b91af">IScriptControl</span></p>
<p>Nous devons ensuite enregistrer cette classe dans le ScriptManager comme nous avons dû le faire pour enregistrer celle-ci dans le support du PostBack.</p>
<p><span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> OnPreRender(System.<span style="COLOR: #2b91af">EventArgs</span> e)<br />{<br /> <span style="COLOR: blue">if</span> (!<span style="COLOR: blue">this</span>.DesignMode)<br /> {<br /> <span style="COLOR: #2b91af">ScriptManager</span> sm = <span style="COLOR: #2b91af">ScriptManager</span>.GetCurrent(Page);<br /> <span style="COLOR: blue">if</span> (sm == <span style="COLOR: blue">null</span>)<br /> {<br /> <span style="COLOR: blue">throw</span> <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">HttpException</span>(<span style="COLOR: #a31515">"A ScriptManager control must exist on the page."</span>);<br /> }<br /> sm.RegisterScriptControl(<span style="COLOR: blue">this</span>);<br /> }<br /> <span style="COLOR: blue">base</span>.OnPreRender(e);<br /> <span style="COLOR: blue">this</span>.Page.RegisterRequiresPostBack(<span style="COLOR: blue">this</span>);<br />}<br /><span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> Render(<span style="COLOR: #2b91af">HtmlTextWriter</span> writer)<br />{<br /> <span style="COLOR: blue">if</span> (!<span style="COLOR: blue">this</span>.DesignMode)<br /> {<br /> <span style="COLOR: #2b91af">ScriptManager</span> sm = <span style="COLOR: #2b91af">ScriptManager</span>.GetCurrent(Page);<br /> sm.RegisterScriptDescriptors(<span style="COLOR: blue">this</span>);<br /> }<br /> <span style="COLOR: blue">base</span>.Render(writer);<br />}</p>
<p>Il est temps de passer à l'implémentation de l'interface IScriptControl. Il faut donner le nom de la classe JavaScript liée au contrôle C# ainsi que les propriétés que l'on envoie à la classe JavaScript. Cela se passe dans la méthode GetScriptDescriptors. De l'autre côté, il faut spécifier le chemin pour accéder au fichier JavaScript où se trouve ma (future) classe JavaScript. Cela se passe dans la méthode GetScriptReferences.</p>
<p><span style="COLOR: blue">public</span> <span style="COLOR: #2b91af">IEnumerable</span><<span style="COLOR: #2b91af">ScriptDescriptor</span>> GetScriptDescriptors()<br />{<br /> <span style="COLOR: #2b91af">ScriptControlDescriptor</span> descriptor = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">ScriptControlDescriptor</span>(<span style="COLOR: #a31515">"MyCustomControls.PercentageControl"</span>, <span style="COLOR: blue">this</span>.ClientID);<br /> descriptor.AddProperty(<span style="COLOR: #a31515">"errorCssClass"</span>, <span style="COLOR: blue">this</span>.ErrorCssClass);<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">ScriptDescriptor</span>[] { descriptor };<br />}<br /><span style="COLOR: blue">public</span> <span style="COLOR: #2b91af">IEnumerable</span><<span style="COLOR: #2b91af">ScriptReference</span>> GetScriptReferences()<br />{<br /> <span style="COLOR: #2b91af">ScriptReference</span> reference = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">ScriptReference</span>();<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">this</span>.Page != <span style="COLOR: blue">null</span>)<br /> {<br /> reference.Path = <span style="COLOR: blue">this</span>.Page.ClientScript.GetWebResourceUrl(<br /> <span style="COLOR: blue">this</span>.GetType(),<br /> <span style="COLOR: #a31515">"MyCustomControls.PercentageControl.js"</span>);<br /> }<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">new</span>[] { reference };<br />}</p>
<p>Nous pouvons démarrer notre classe JavaScript. Nous décidons de la placer dans une ressource "embedded" de notre dll. Nous ajoutons notre fichier PercentageControl.js et nous l'enregistrons comme ressource dans notre assembly via cet déclaration ci-dessous.</p>
<p>[<span style="COLOR: blue">assembly</span>: <span style="COLOR: #2b91af">WebResource</span>(<span style="COLOR: #a31515">"MyCustomControls.PercentageControl.js"</span>, <span style="COLOR: #a31515">"text/javascript"</span>)]</p>
<p>La prochaine étape est l'implémentation de celle-ci.</p>
<p><ins>1) Nous enregistrons notre namespace</ins></p>
<p>Type.registerNamespace(<span style="COLOR: maroon">'MyCustomControls'</span>);</p>
<p><br /><ins>2) Nous allons initialiser les valeurs par défauts etc</ins></p>
<p>MyCustomControls.PercentageControl = <span style="COLOR: blue">function</span> (element) {<br /> MyCustomControls.PercentageControl.initializeBase(<span style="COLOR: blue">this</span>, [element]);<br /> <span style="COLOR: blue">this</span>._errorCssClass = <span style="COLOR: blue">null</span>;<br />};</p>
<p><br /><ins>3) Nous implémentons notre classe protoype avec 2 méthodes .... initialize et dispose</ins></p>
<p>MyCustomControls.PercentageControl.prototype = {<br /> initialize: <span style="COLOR: blue">function</span> () {<br /> MyCustomControls.PercentageControl.callBaseMethod(<span style="COLOR: blue">this</span>, <span style="COLOR: maroon">'initialize'</span>);<br /> },<br /> dispose: <span style="COLOR: blue">function</span> () {<br /> $clearHandlers(<span style="COLOR: blue">this</span>.get_element());<br /> MyCustomControls.PercentageControl.callBaseMethod(<span style="COLOR: blue">this</span>, <span style="COLOR: maroon">'dispose'</span>);<br /> }<br />};</p>
<p><ins>4) Nous implémentons les propriétés pour le css d'erreur à appliquer en JavaScript</ins></p>
<p>MyCustomControls.PercentageControl.prototype = {<br /> initialize: <span style="COLOR: blue">function</span> () {<br /> MyCustomControls.PercentageControl.callBaseMethod(<span style="COLOR: blue">this</span>, <span style="COLOR: maroon">'initialize'</span>);<br /> },<br /> dispose: <span style="COLOR: blue">function</span> () {<br /> $clearHandlers(<span style="COLOR: blue">this</span>.get_element());<br /> MyCustomControls.PercentageControl.callBaseMethod(<span style="COLOR: blue">this</span>, <span style="COLOR: maroon">'dispose'</span>);<br /> },<br /> set_errorCssClass: <span style="COLOR: blue">function</span> (value) {<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">this</span>._errorCssClass !== value) {<br /> <span style="COLOR: blue">this</span>._errorCssClass = value;<br /> <span style="COLOR: blue">this</span>.raisePropertyChanged(<span style="COLOR: maroon">'errorCssClass'</span>);<br /> }<br /> },<br /> get_errorCssClass: <span style="COLOR: blue">function</span> () {<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">this</span>._errorCssClass;<br /> }<br />};</p>
<p><ins>5) Nous donnons explicitement les descripteurs (utile pour la sérialisation JSON)</ins></p>
<p>MyCustomControls.PercentageControl.descriptor = {<br /> properties: [{ name: <span style="COLOR: maroon">'errorCssClass'</span>, type: String}]<br />};</p>
<p><ins>6) Nous enregistrons la classe et nous informons le framework que c'est chargé.</ins></p>
<p>MyCustomControls.PercentageControl.registerClass(<span style="COLOR: maroon">'MyCustomControls.PercentageControl'</span>, Sys.UI.Control);<br /><span style="COLOR: blue">if</span> (<span style="COLOR: blue">typeof</span> (Sys) !== <span style="COLOR: maroon">'undefined'</span>) Sys.Application.notifyScriptLoaded();</p>
<p><ins>7) Nous souhaitons implémenter notre code "business"</ins></p>
<p>L'idée est de mettre un cadre rouge autour des texbox lorsqu'il y a une erreur. Pour ce faire, nous allons nous abonner à l'event change et ajouter notre css d'erreur en cas de donnée incorrecte. Nous obtenons au final le résultat ci-dessous.</p>
<p>Type.registerNamespace(<span style="COLOR: maroon">'MyCustomControls'</span>);<br />MyCustomControls.PercentageControl = <span style="COLOR: blue">function</span> (element) {<br /> MyCustomControls.PercentageControl.initializeBase(<span style="COLOR: blue">this</span>, [element]);<br /> <span style="COLOR: blue">this</span>._errorCssClass = <span style="COLOR: blue">null</span>;<br />};<br />MyCustomControls.PercentageControl.prototype = {<br /> initialize: <span style="COLOR: blue">function</span> () {<br /> MyCustomControls.PercentageControl.callBaseMethod(<span style="COLOR: blue">this</span>, <span style="COLOR: maroon">'initialize'</span>);<br /> <span style="COLOR: blue">this</span>._onchangeHandler = Function.createDelegate(<span style="COLOR: blue">this</span>, <span style="COLOR: blue">this</span>._onchange);<br /> $addHandlers(<span style="COLOR: blue">this</span>.get_element(), { <span style="COLOR: maroon">'change'</span>: <span style="COLOR: blue">this</span>._onchangeHandler }, <span style="COLOR: blue">this</span>);<br /> },<br /> dispose: <span style="COLOR: blue">function</span> () {<br /> $clearHandlers(<span style="COLOR: blue">this</span>.get_element());<br /> MyCustomControls.PercentageControl.callBaseMethod(<span style="COLOR: blue">this</span>, <span style="COLOR: maroon">'dispose'</span>);<br /> },<br /> _onchange: <span style="COLOR: blue">function</span> (e) {<br /> <span style="COLOR: blue">var</span> value = parseFloat(e.target.value);<br /> <span style="COLOR: blue">var</span> isIncorrect = <span style="COLOR: blue">false</span>;<br /> <span style="COLOR: blue">if</span> (isNaN(value) || !isFinite(value)) {<br /> isIncorrect = <span style="COLOR: blue">true</span>;<br /> }<br /> <span style="COLOR: blue">if</span> (isIncorrect || value > 100 || value < 0) {<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">this</span>._errorCssClass !== <span style="COLOR: blue">null</span> && <span style="COLOR: blue">this</span>._errorCssClass !== <span style="COLOR: maroon">''</span>) {<br /> <span style="COLOR: blue">this</span>.addCssClass(<span style="COLOR: blue">this</span>._errorCssClass);<br /> }<br /> }<br /> <span style="COLOR: blue">else</span> {<br /> <span style="COLOR: blue">this</span>.removeCssClass(<span style="COLOR: blue">this</span>._errorCssClass); <br /> }<br /> },<br /> set_errorCssClass: <span style="COLOR: blue">function</span> (value) {<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">this</span>._errorCssClass !== value) {<br /> <span style="COLOR: blue">this</span>._errorCssClass = value;<br /> <span style="COLOR: blue">this</span>.raisePropertyChanged(<span style="COLOR: maroon">'errorCssClass'</span>);<br /> }<br /> },<br /> get_errorCssClass: <span style="COLOR: blue">function</span> () {<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">this</span>._errorCssClass;<br /> }<br />};<br />MyCustomControls.PercentageControl.descriptor = {<br /> properties: [{ name: <span style="COLOR: maroon">'errorCssClass'</span>, type: String}]<br />};<br />MyCustomControls.PercentageControl.registerClass(<span style="COLOR: maroon">'MyCustomControls.PercentageControl'</span>, Sys.UI.Control);<br /><span style="COLOR: blue">if</span> (<span style="COLOR: blue">typeof</span> (Sys) !== <span style="COLOR: maroon">'undefined'</span>) Sys.Application.notifyScriptLoaded();</p>
<p>Il ne reste plus qu'à ajouter ma class css dans ceux-ci</p>
<p><span style="COLOR: blue"><</span><span style="COLOR: maroon">style</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/css"</span><span style="COLOR: blue">></span><br /> <span style="COLOR: maroon">.errorCss</span><br /> {<br /> <span style="COLOR: red">border-color</span>: <span style="COLOR: blue">Red</span>;<br /> }<br /><span style="COLOR: blue"></</span><span style="COLOR: maroon">style</span><span style="COLOR: blue">></span></p>
<div>et de l'ajouter dans notre code asp.net</div>
<div> </div>
<div><span style="COLOR: blue"><</span><span style="COLOR: maroon">div</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Button</span> <span style="COLOR: red">ID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"Button1"</span> <span style="COLOR: red">Text</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"Click"</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: blue">/></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">Custom</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">PercentageControl</span> <span style="COLOR: red">ID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"PercentageControl1"</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <br /> <span style="COLOR: red">ErrorCssClass</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"errorCss"</span> <span style="COLOR: red">Value</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"100"</span> <span style="COLOR: blue">/></span><br /><span style="COLOR: blue"></</span><span style="COLOR: maroon">div</span><span style="COLOR: blue">></span></div>
<div> </div>
<div>Nous pouvons maintenant l'exécuter et nous voyons que l'on retrouve un cadre rouge si on encode 200, -10 ou encore le "é" dans notre textbox. Vous pouvez retrouver la solution en fichier attaché ci-dessous.</div>Création d'un Custom WebControlurn:md5:9109b73f4e0db7afeb98a0a378dd3f882012-06-18T19:57:00+02:002012-06-19T13:20:25+02:00Thierry ThouaASP.NET<p>Depuis que je développe en .NET, j'entend toujours des gens expliquer qu'asp.net génère du code HTML de très mauvaise qualité, etc. Il n'en est rien dans la pratique. En effet, il est tout à fait possible de travailler en ASP.NET et de générer du beau code HTML. J'ai décidé suite à certaines implémentations réalisées il n'y a pas si longtemps ... de réaliser quelques articles sur ce sujet (en effet, nombre d'entre nous ne connait pas toute la puissance d'ASP.NET). Le premier porte ici sur la création d'un contrôle simple affichant une textbox. Côté .NET, nous pouvons récupérer la valeur. J'expliquerai prochainement comment ajouter des validations client JS propres ainsi que la réalisation de contrôles plus complexes.</p> <p>La première étape est de créer une nouvelle classe héritant de WebControl. Nous décidons de l'appeler PercentageControl. </p>
<p>[<span style="COLOR: #2b91af">ToolboxData</span>(<span style="COLOR: #a31515">"<{0}:PercentageControl runat=server></{0}:PercentageControl>"</span>)]<br /><span style="COLOR: blue">public</span> <span style="COLOR: blue">class</span> <span style="COLOR: #2b91af">PercentageControl</span> : <span style="COLOR: #2b91af">WebControl</span><br />{<br />}</p>
<div>Il s'agit d'un contrôle "pourcentage" qui est censé nous donner un pourcentage. Nous décidons donc de lui rajouter une propriété renvoyant le pourcentage. Nous définissons également, par attribut, que la "default property" est cette propriété. Nous allons également garder en ViewState cette valeur si elle existe.</div>
<div> </div>
<div>[<span style="COLOR: #2b91af">DefaultProperty</span>(<span style="COLOR: #a31515">"Value"</span>)]<br />[<span style="COLOR: blue"><span style="COLOR: #2b91af"><span style="COLOR: #2b91af">ToolboxData</span>(<span style="COLOR: #a31515">"<{0}:PercentageControl runat=server></{0}:PercentageControl>"</span><span style="COLOR: black">)]</span><br /></span>public</span> <span style="COLOR: blue">class</span> <span style="COLOR: #2b91af">PercentageControl</span> : <span style="COLOR: #2b91af">WebControl</span><br />{<br /> [<span style="COLOR: #2b91af">Bindable</span>(<span style="COLOR: blue">true</span>)]<br /> [<span style="COLOR: #2b91af">Category</span>(<span style="COLOR: #a31515">"Custom Category"</span>)]<br /> [<span style="COLOR: #2b91af">DefaultValue</span>(<span style="COLOR: #a31515">""</span>)]<br /> [<span style="COLOR: #2b91af">Description</span>(<span style="COLOR: #a31515">"The percentage value."</span>)]<br /> [<span style="COLOR: #2b91af">Localizable</span>(<span style="COLOR: blue">false</span>)]<br /> <span style="COLOR: blue">public</span> <span style="COLOR: blue">double</span>? Value<br /> {<br /> <span style="COLOR: blue">get</span><br /> {<br /> <span style="COLOR: blue">var</span> value = <span style="COLOR: blue">this</span>.ViewState[<span style="COLOR: #a31515">"Value"</span>];<br /> <span style="COLOR: blue">if</span> (value != <span style="COLOR: blue">null</span>)<br /> {<br /> <span style="COLOR: blue">return</span> (<span style="COLOR: blue">double</span>)value;<br /> }<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">default</span>(<span style="COLOR: blue">double</span>?);<br /> }<br /> <span style="COLOR: blue">set</span> { <span style="COLOR: blue">this</span>.ViewState[<span style="COLOR: #a31515">"Value"</span>] = <span style="COLOR: blue">value</span>; }<br /> }<br />}</div>
<div> </div>
<div>Nous avons maintenant notre propriété mais nous n'avons encore aucun HTML généré... L'idée est donc maintenant d'implémenter le code C# qui après processing affichera du code HTML.</div>
<div> </div>
<div><span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: #2b91af">HtmlTextWriterTag</span> TagKey<br />{<br /> <span style="COLOR: blue">get</span> { <span style="COLOR: blue">return</span> <span style="COLOR: #2b91af">HtmlTextWriterTag</span>.Input; }<br />}<br /><span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> AddAttributesToRender(<span style="COLOR: #2b91af">HtmlTextWriter</span> writer)<br />{<br /> <span style="COLOR: blue">base</span>.AddAttributesToRender(writer);<br /> writer.AddAttribute(<span style="COLOR: #2b91af">HtmlTextWriterAttribute</span>.Type, <span style="COLOR: #a31515">"text"</span>);<br /> writer.AddAttribute(<span style="COLOR: #2b91af">HtmlTextWriterAttribute</span>.Name, <span style="COLOR: blue">this</span>.UniqueID);<br /> writer.AddAttribute(<span style="COLOR: #2b91af">HtmlTextWriterAttribute</span>.Value, <span style="COLOR: blue">this</span>.Value.HasValue <br /> ? <span style="COLOR: blue">this</span>.Value.ToString() <br /> : <span style="COLOR: blue">string</span>.Empty);<br />}</div>
<div> </div>
<div>Si nous exécutions ce code dans une page HTML, nous verrions donc une textbox. Mais, si nous ajoutions un bouton ou tout autre contrôle provoquant un PostBack, nous verrions que le contrôle serait chaque fois remis à la valeur enregistrée par défaut. Pour garder le contrôle à jour et pour mettre à jour la propriété "Value", il faut implémenter l'interface IPostBackDataHandler et enregistrer notre contrôle comme supportant le "postback". Via ce mécanisme, nous pouvons par exemple lancer un event pour annoncer que notre pourcentage a été modifié lors du postback.</div>
<div> </div>
<div><span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> OnPreRender(System.<span style="COLOR: #2b91af">EventArgs</span> e)<br />{<br /> <span style="COLOR: blue">base</span>.OnPreRender(e);<br /> <span style="COLOR: blue">this</span>.Page.RegisterRequiresPostBack(<span style="COLOR: blue">this</span>);<br />}</div>
<div><br /><span style="COLOR: blue">#region</span> IPostBackDataHandler Members</div>
<div><span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> LoadPostData(<span style="COLOR: blue">string</span> postDataKey, <span style="COLOR: #2b91af">NameValueCollection</span> postCollection)<br />{<br /> <span style="COLOR: blue">var</span> result = postCollection[<span style="COLOR: blue">this</span>.UniqueID];<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">string</span>.IsNullOrEmpty(result))<br /> {<br /> <span style="COLOR: blue">this</span>.Value = <span style="COLOR: blue">default</span>(<span style="COLOR: blue">double</span>?);<br /> <span style="COLOR: blue">return</span> !<span style="COLOR: blue">this</span>.Value.HasValue;<br /> }<br /> <span style="COLOR: blue">double</span> newValue;<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">double</span>.TryParse(result, <span style="COLOR: blue">out</span> newValue))<br /> {<br /> <span style="COLOR: blue">bool</span> hasChanged = <span style="COLOR: blue">this</span>.Value != newValue;<br /> <span style="COLOR: blue">this</span>.Value = newValue;<br /> <span style="COLOR: blue">return</span> hasChanged;<br /> }<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">false</span>;</div>
<div>}</div>
<div><br /><span style="COLOR: blue">public</span> <span style="COLOR: blue">void</span> RaisePostDataChangedEvent()<br />{<br />}</div>
<div><span style="COLOR: blue">#endregion</span></div>
<div> </div>
<div>Nous obtenons un contrôle fonctionnel. Il ne nous reste plus qu'à l'utiliser. Afin d'améliorer un petit peu le look and feel pour nous développeurs, nous pouvons ajouter une icône qui sera visible dans la toolbox de Visual Studio. Nous ajoutons une image en "embedded resource" et nous ajoutons un attribut sur notre classe qui pointe vers ce fichier.</div>
<div> </div>
<div>[<span style="COLOR: #2b91af">ToolboxBitmap</span>(<span style="COLOR: blue">typeof</span>(<span style="COLOR: #2b91af">PercentageControl</span>), <span style="COLOR: #a31515">"Percentage.bmp"</span>)]</div>
<div> </div>
<div><img src="http://www.lelibre.net/public/157_CustomWebControl/IconForWebControl.png" /></div>
<div> </div>
<div>Voici le fichier final: </div>
<div> </div>
<div>[<span style="COLOR: #2b91af">DefaultProperty</span>(<span style="COLOR: #a31515">"Value"</span>)]<br />[<span style="COLOR: #2b91af">ToolboxData</span>(<span style="COLOR: #a31515">"<{0}:PercentageControl runat=server></{0}:PercentageControl>"</span>)]<br />[<span style="COLOR: #2b91af">ToolboxBitmap</span>(<span style="COLOR: blue">typeof</span>(<span style="COLOR: #2b91af">PercentageControl</span>), <span style="COLOR: #a31515">"Percentage.bmp"</span>)]<br /><span style="COLOR: blue">public</span> <span style="COLOR: blue">class</span> <span style="COLOR: #2b91af">PercentageControl</span> : <span style="COLOR: #2b91af">WebControl</span>, <span style="COLOR: #2b91af">IPostBackDataHandler</span><br />{<br /> [<span style="COLOR: #2b91af">Bindable</span>(<span style="COLOR: blue">true</span>)]<br /> [<span style="COLOR: #2b91af">Category</span>(<span style="COLOR: #a31515">"Custom Category"</span>)]<br /> [<span style="COLOR: #2b91af">DefaultValue</span>(<span style="COLOR: #a31515">""</span>)]<br /> [<span style="COLOR: #2b91af">Description</span>(<span style="COLOR: #a31515">"The percentage value."</span>)]<br /> [<span style="COLOR: #2b91af">Localizable</span>(<span style="COLOR: blue">false</span>)]<br /> <span style="COLOR: blue">public</span> <span style="COLOR: blue">double</span>? Value<br /> {<br /> <span style="COLOR: blue">get</span><br /> {<br /> <span style="COLOR: blue">var</span> value = <span style="COLOR: blue">this</span>.ViewState[<span style="COLOR: #a31515">"Value"</span>];<br /> <span style="COLOR: blue">if</span> (value != <span style="COLOR: blue">null</span>)<br /> {<br /> <span style="COLOR: blue">return</span> (<span style="COLOR: blue">double</span>)value;<br /> }<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">default</span>(<span style="COLOR: blue">double</span>?);<br /> }<br /> <span style="COLOR: blue">set</span> { <span style="COLOR: blue">this</span>.ViewState[<span style="COLOR: #a31515">"Value"</span>] = <span style="COLOR: blue">value</span>; }<br /> }<br /> <span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: #2b91af">HtmlTextWriterTag</span> TagKey<br /> {<br /> <span style="COLOR: blue">get</span> { <span style="COLOR: blue">return</span> <span style="COLOR: #2b91af">HtmlTextWriterTag</span>.Input; }<br /> }<br /> <span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> AddAttributesToRender(<span style="COLOR: #2b91af">HtmlTextWriter</span> writer)<br /> {<br /> <span style="COLOR: blue">base</span>.AddAttributesToRender(writer);<br /> writer.AddAttribute(<span style="COLOR: #2b91af">HtmlTextWriterAttribute</span>.Type, <span style="COLOR: #a31515">"text"</span>);<br /> writer.AddAttribute(<span style="COLOR: #2b91af">HtmlTextWriterAttribute</span>.Name, <span style="COLOR: blue">this</span>.UniqueID);<br /> writer.AddAttribute(<span style="COLOR: #2b91af">HtmlTextWriterAttribute</span>.Value, <span style="COLOR: blue">this</span>.Value.HasValue <br /> ? <span style="COLOR: blue">this</span>.Value.ToString() <br /> : <span style="COLOR: blue">string</span>.Empty);<br /> }<br /> <span style="COLOR: blue">protected</span> <span style="COLOR: blue">override</span> <span style="COLOR: blue">void</span> OnPreRender(System.<span style="COLOR: #2b91af">EventArgs</span> e)<br /> {<br /> <span style="COLOR: blue">base</span>.OnPreRender(e);<br /> <span style="COLOR: blue">this</span>.Page.RegisterRequiresPostBack(<span style="COLOR: blue">this</span>);<br /> }<br /><span style="COLOR: blue"> #region</span> IPostBackDataHandler Members<br /> <span style="COLOR: blue">public</span> <span style="COLOR: blue">bool</span> LoadPostData(<span style="COLOR: blue">string</span> postDataKey, <span style="COLOR: #2b91af">NameValueCollection</span> postCollection)<br /> {<br /> <span style="COLOR: blue">var</span> result = postCollection[<span style="COLOR: blue">this</span>.UniqueID];<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">string</span>.IsNullOrEmpty(result))<br /> {<br /> <span style="COLOR: blue">this</span>.Value = <span style="COLOR: blue">default</span>(<span style="COLOR: blue">double</span>?);<br /> <span style="COLOR: blue">return</span> !<span style="COLOR: blue">this</span>.Value.HasValue;<br /> }<br /> <span style="COLOR: blue">double</span> newValue;<br /> <span style="COLOR: blue">if</span> (<span style="COLOR: blue">double</span>.TryParse(result, <span style="COLOR: blue">out</span> newValue))<br /> {<br /> <span style="COLOR: blue">bool</span> hasChanged = <span style="COLOR: blue">this</span>.Value != newValue;<br /> <span style="COLOR: blue">this</span>.Value = newValue;<br /> <span style="COLOR: blue">return</span> hasChanged;<br /> }<br /> <span style="COLOR: blue">return</span> <span style="COLOR: blue">false</span>;<br /> }<br /> <span style="COLOR: blue">public</span> <span style="COLOR: blue">void</span> RaisePostDataChangedEvent()<br /> {<br /> }<br /><span style="COLOR: blue"> #endregion</span><br />}</div>
<div> </div>
<div>Nous pouvons dès à présent le référencer et l'utiliser dans notre code ASP.NET.</div>
<div> </div>
<div><span style="COLOR: blue"><</span><span style="COLOR: maroon">div</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">Custom</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">PercentageControl</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: red">Value</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"200"</span> <span style="COLOR: blue">/></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Button</span> <span style="COLOR: red">Text</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"Click"</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: blue">/></span><br /><span style="COLOR: blue"></</span><span style="COLOR: maroon">div</span><span style="COLOR: blue">></span></div>
<div> </div>
<div><img src="http://www.lelibre.net/public/157_CustomWebControl/PageTest.png" /></div>Conserver le "tab" courant en cas de postback avec JQuery UI Tabsurn:md5:96f912e6b884254332e3ca19daef9f8a2011-12-05T18:41:00+01:002011-12-05T18:41:00+01:00Thierry ThouaASP.NET<p>Nous souhaitons souvent amener un caractère sexy à notre page... Le framework à la mode est JQuery et il a intégré dans son plugin UI le composant permettant d’afficher une zone sous forme de 'tabs'. Néanmoins, l'utilisation d'ASP.NET amène parfois des problèmes. En effet, le moindre "changement" dans une dropdown en autopostback provoque un rechargement de la page. Evidement, JQuery UI Tabs étant 100% côté client, il est impossible de revenir sur le tab "courant" qui a déclenché le PostBack... </p>
<p>Cependant, nous pouvons facilement ajouter ce type de fonctionnalité dans notre code. Cet article l'explique.</p> <p>Prenons par exemple une page ASP.NET de base héritant d'une MasterPage.</p>
<p><span style="COLOR: blue"><span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Content</span> <span style="COLOR: red">ID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"BodyContent"</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: red">ContentPlaceHolderID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"MainContent"</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">div</span> <span style="COLOR: red">class</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"tabs"</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">ul</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">li</span><span style="COLOR: blue">><</span><span style="COLOR: maroon">a</span> <span style="COLOR: red">href</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"#tabs1"</span><span style="COLOR: blue">></span>Tab 1<span style="COLOR: blue"></</span><span style="COLOR: maroon">a</span><span style="COLOR: blue">></</span><span style="COLOR: maroon">li</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">li</span><span style="COLOR: blue">><</span><span style="COLOR: maroon">a</span> <span style="COLOR: red">href</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"#tabs2"</span><span style="COLOR: blue">></span>Tab 2<span style="COLOR: blue"></</span><span style="COLOR: maroon">a</span><span style="COLOR: blue">></</span><span style="COLOR: maroon">li</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"></</span><span style="COLOR: maroon">ul</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">div</span> <span style="COLOR: red">id</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"tabs1"</span><span style="COLOR: blue">></span><br /> Tab 1<br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Button</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: red">Text</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"Click from tab 1"</span> <span style="COLOR: blue">/></span><br /> <span style="COLOR: blue"></</span><span style="COLOR: maroon">div</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">div</span> <span style="COLOR: red">id</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"tabs2"</span><span style="COLOR: blue">></span><br /> Tab 2<br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Button</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: red">Text</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"Click from tab 2"</span> <span style="COLOR: blue">/></span><br /> <span style="COLOR: blue"></</span><span style="COLOR: maroon">div</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"></</span><span style="COLOR: maroon">div</span><span style="COLOR: blue">></span><br /><span style="COLOR: blue"></</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Content</span><span style="COLOR: blue">></span></p>
<p><br /></span>Nous ajoutons les script JQuery et JQuery UI via CDN. Nous ajoutons également la mise en place du mécanisme de tabs sous JQuery UI, à savoir l'utilisation de la méthode tabs() sur notre div.</p>
<p><span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Content</span> <span style="COLOR: red">ID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"HeaderContent"</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: red">ContentPlaceHolderID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"HeadContent"</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">script</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/javascript"</span> <span style="COLOR: red">src</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"</span><span style="COLOR: blue">></</span><span style="COLOR: maroon">script</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">script</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/javascript"</span> <span style="COLOR: red">src</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"http://ajax.microsoft.com/ajax/jquery.ui/1.8.5/jquery-ui.js"</span><span style="COLOR: blue">></</span><span style="COLOR: maroon">script</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">link</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/css"</span> <span style="COLOR: red">rel</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"stylesheet"</span> <span style="COLOR: red">href</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"http://ajax.microsoft.com/ajax/jquery.ui/1.8.5/themes/redmond/jquery-ui.css"</span> <span style="COLOR: blue">/></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">script</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/javascript"</span> <span style="COLOR: red">language</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"javascript"</span><span style="COLOR: blue">></span><br /> $(<span style="COLOR: blue">function</span> () {<br /> $(<span style="COLOR: maroon">"div.tabs"</span>).tabs();<br /> });<br /> <span style="COLOR: blue"></</span><span style="COLOR: maroon">script</span><span style="COLOR: blue">></span><br /><span style="COLOR: blue"></</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Content</span><span style="COLOR: blue">></span></p>
<p>Notre page s'affiche et les div sont correctement rendus avec des tabs. Nous devons maintenant ajouter la possibilité de retenir le tab courant. Nous allons donc ajouter dans notre page un input field de type hidden:<br /><br /><span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">HiddenField</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: red">ID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"currentTab"</span> <span style="COLOR: blue">/></span></p>
<p>Nous allons également modifier notre code javascript pour retenir le tab courant:</p>
<p><span style="COLOR: blue"><</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Content</span> <span style="COLOR: red">ID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"HeaderContent"</span> <span style="COLOR: red">runat</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"server"</span> <span style="COLOR: red">ContentPlaceHolderID</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"HeadContent"</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">script</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/javascript"</span> <span style="COLOR: red">src</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js"</span><span style="COLOR: blue">></</span><span style="COLOR: maroon">script</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">script</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/javascript"</span> <span style="COLOR: red">src</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"http://ajax.microsoft.com/ajax/jquery.ui/1.8.5/jquery-ui.js"</span><span style="COLOR: blue">></</span><span style="COLOR: maroon">script</span><span style="COLOR: blue">></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">link</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/css"</span> <span style="COLOR: red">rel</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"stylesheet"</span> <span style="COLOR: red">href</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"http://ajax.microsoft.com/ajax/jquery.ui/1.8.5/themes/redmond/jquery-ui.css"</span> <span style="COLOR: blue">/></span><br /> <span style="COLOR: blue"><</span><span style="COLOR: maroon">script</span> <span style="COLOR: red">type</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"text/javascript"</span> <span style="COLOR: red">language</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"javascript"</span><span style="COLOR: blue">></span><br /> $(<span style="COLOR: blue">function</span> () {<br /> $(<span style="COLOR: maroon">"div.tabs"</span>).tabs();<br /> <span style="COLOR: blue">var</span> currentTabId = $(<span style="COLOR: maroon">"#</span><span style="BACKGROUND: yellow; COLOR: maroon"><%</span><span style="COLOR: maroon">=</span><span style="COLOR: maroon"> currentTab.ClientID </span><span style="BACKGROUND: yellow; COLOR: maroon">%></span><span style="COLOR: maroon">"</span>);<br /> $(<span style="COLOR: maroon">"div.tabs"</span>).tabs(<span style="COLOR: maroon">'select'</span>, currentTabId.val());<br /> $(<span style="COLOR: maroon">"div.tabs"</span>).bind(<span style="COLOR: maroon">'tabsselect'</span>, <span style="COLOR: blue">function</span> (event, ui) {<br /> currentTabId.val(ui.panel.id);<br /> });<br /> });<br /> <span style="COLOR: blue"></</span><span style="COLOR: maroon">script</span><span style="COLOR: blue">></span><br /><span style="COLOR: blue"></</span><span style="COLOR: maroon">asp</span><span style="COLOR: blue">:</span><span style="COLOR: maroon">Content</span><span style="COLOR: blue">></span></p>
<p>A partir de ce moment, nous avons une page qui s'affiche sur le bon tab en cas de postback. Nous pouvons donc accéder en C# à l'information via le hiddenfield.Value ou via JS. </p>Utiliser l'authentification OAuth2 de Foursquare sur un site ASP.NET MVC 3urn:md5:7ec4842f39e2460c7fe1a458523888942011-09-08T20:58:00+02:002011-09-21T15:29:50+02:00Thierry ThouaASP.NET<p>Oauth a tendance à se généraliser dans le monde web pour l'authentification. Une des forces du système est la simplicité avec laquelle on centralise les informations et on s'authentifie ! L'exemple de ce post montre comment prendre n'importe quel site Web ASP.NET MVC 3 et ajouter un mécanisme d'authentification différent du "MemberShip" classique. Vous pouvez trouver plus d'informations sur OAuth via ce <a href="http://oauth.net/" hreflang="en">lien</a>.</p> <p>La première opération est de récupérer une librairie supportant OAuth2. Ici, j'ai fait le choix de prendre <a href="http://www.dotnetopenauth.net/" hreflang="en">DotNetOpenAuth</a> en version bêta (supportant donc OAuth 2).<br />La seconde opération est d'aller sur le <a href="https://fr.foursquare.com/oauth/" hreflang="en">site de foursquare</a> et d'enregistrer son application afin d'obtenir une clé. Il est très important de correctement définir l'adresse url du site sur lequel on ajoute la fonctionnalité ou le processus d'authentification ne fonctionnera pas!</p>
<p>Le moment est venu d'implémenter notre code sur notre site. Nous allons donc aller dans notre page de login dans le controlleur Account. Nous ajoutons une image (le logo de foursquare) ainsi qu'une action dessus. Lorsque l'utilisateur cliquera sur l'image, l'action "LogOnFoursquare" s'exécutera.</p>
<div><pre style="FONT-FAMILY: Consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 13px"><span style="COLOR: blue"><</span><span style="COLOR: maroon">a</span> <span style="COLOR: red">href</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"</span><span style="BACKGROUND: yellow">@</span><span style="COLOR: blue">Url</span><span style="COLOR: blue">.</span><span style="COLOR: blue">Action</span><span style="COLOR: blue">(</span><span style="COLOR: #a31515">"LogOnFoursquare"</span><span style="COLOR: blue">, </span><span style="COLOR: #a31515">"Account"</span><span style="COLOR: blue">)"</span><span style="COLOR: blue">></span>
<span style="COLOR: blue"><</span><span style="COLOR: maroon">img</span> <span style="COLOR: red">src</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"</span><span style="BACKGROUND: yellow">@</span><span style="COLOR: blue">Url</span><span style="COLOR: blue">.</span><span style="COLOR: blue">Content</span><span style="COLOR: blue">("~/</span><span style="COLOR: blue">Images/foursquare_logo.png")"</span> <span style="COLOR: red">alt</span><span style="COLOR: blue">=</span><span style="COLOR: blue">""</span> <span style="COLOR: red">style</span><span style="COLOR: blue">=</span><span style="COLOR: blue">"</span><span style="COLOR: red">height</span><span style="COLOR: blue">:</span><span style="COLOR: blue">30px</span><span style="COLOR: blue">;</span><span style="COLOR: red">width</span><span style="COLOR: blue">:</span><span style="COLOR: blue">100px</span><span style="COLOR: blue">"</span> <span style="COLOR: blue">/></span><span style="COLOR: blue"></</span><span style="COLOR: maroon">a</span><span style="COLOR: blue">></span></pre></div>
<div>Evidement, comme vu au dessus, nous devons ajouter l'action dans le controlleur Account. C'est à cet endroit que l'on exécutera l'authentification OAuth2. Fonctionnant en multi couches, je décide donc de créer une classe FoursquareConnect (qui sera décrite/implémentée plus bas). Le constructeur reçoit en paramètre la clé client et notre clé secrète. Ces deux informations ont été fournies par le site de Foursquare lors de notre enregistrement.<br />Il est donc maintenant possible de créer la méthode (vide) demandant un token et envoyant l'url de retour. Avec cette classe, j'ai la possibilité de terminer ma méthode "LogOnFoursquare".</div>
<div>Il est temps d'implémenter la méthode "OAuthFoursquare" que l'on a référencé en adresse de callback dans notre précédente méthode. Nous pouvons donc "processer" la demande et récupérer le user pour le sauvegarder (ici dans le futur dans un cookie session). La dernière étape est de rediriger l'utilisateur sur la page "Home".</div>
<div><pre style="FONT-FAMILY: Consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 13px"><span style="COLOR: blue">private</span> <span style="COLOR: blue">static</span> <span style="COLOR: blue">readonly</span> <span style="COLOR: #2b91af">FoursquareConnect</span> foursquare = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">FoursquareConnect</span>(<span style="COLOR: #a31515">"clientID"</span>, <span style="COLOR: #a31515">"secretID"</span>);
<span style="COLOR: blue">public</span> <span style="COLOR: #2b91af">ActionResult</span> LogOnFoursquare()
{
<span style="COLOR: blue">var</span> url = <span style="COLOR: blue">string</span>.Format(<span style="COLOR: #a31515">"{0}://{1}/Account/OAuthFoursquare"</span>,
Request.Url.Scheme,
Request.Url.Authority);
foursquare.RequestUserAuthorization(url);
<span style="COLOR: blue">return</span> <span style="COLOR: blue">null</span>;
}
<span style="COLOR: blue">public</span> <span style="COLOR: #2b91af">ActionResult</span> OAuthFoursquare()
{
<span style="COLOR: #2b91af">OAuthUser</span> user = foursquare.ProcessUserAuthorization();
CreateAuthCookie(user);
<span style="COLOR: blue">return</span> RedirectToAction(<span style="COLOR: #a31515">"Index"</span>, <span style="COLOR: #a31515">"Home"</span>);
}</pre></div>
<div>A ce moment nous avons la structure de l'authentification mais il manque l'implémentation même de notre classe FoursquareConnect. Nous allons donc le faire ci-dessous.</div>
<div>La première étape est d'enregistrer la description du service (cfr ci-dessous).</div>
<div><pre style="FONT-FAMILY: Consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 13px"><span style="COLOR: blue">private</span> <span style="COLOR: blue">static</span> <span style="COLOR: blue">readonly</span> <span style="COLOR: #2b91af">AuthorizationServerDescription</span> FoursquareServiceDescription = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">AuthorizationServerDescription</span>
{
AuthorizationEndpoint = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">Uri</span>(<span style="COLOR: #a31515">"https://fr.foursquare.com/oauth2/authorize"</span>),
TokenEndpoint = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">Uri</span>(<span style="COLOR: #a31515">"https://fr.foursquare.com/oauth2/access_token"</span>),
ProtocolVersion = DotNetOpenAuth.OAuth2.<span style="COLOR: #2b91af">ProtocolVersion</span>.V20
};</pre></div>
<div>Ensuite voici le moment d'implémenter la méthode demandant un "token".</div>
<div><pre style="FONT-FAMILY: Consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 13px"><span style="COLOR: blue">public</span> <span style="COLOR: blue">void</span> RequestUserAuthorization(<span style="COLOR: blue">string</span> url)
{
DotNetOpenAuth.OAuth2.<span style="COLOR: #2b91af">WebServerClient</span> client = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">WebServerClient</span>(FoursquareServiceDescription)
{
ClientIdentifier = clientIdentifier,
ClientSecret = clientSecret
};
client.RequestUserAuthorization(returnTo: <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">Uri</span>(url));
}</pre></div>
<div>Enfin, nous pouvons implémenter la méthode recevant la réponse. Celle-ci sera traduite par la méthode GetUser.</div>
<div><pre style="FONT-FAMILY: Consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 13px"><span style="COLOR: blue">public</span> <span style="COLOR: #2b91af">OAuthUser</span> ProcessUserAuthorization()
{
DotNetOpenAuth.OAuth2.<span style="COLOR: #2b91af">WebServerClient</span> client = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">WebServerClient</span>(FoursquareServiceDescription)
{
ClientIdentifier = clientIdentifier,
ClientSecret = clientSecret
};
<span style="COLOR: blue">var</span> result = client.ProcessUserAuthorization();
<span style="COLOR: blue">return</span> GetUser(result.AccessToken);
}</pre><pre style="FONT-FAMILY: Consolas; BACKGROUND: white; COLOR: black; FONT-SIZE: 13px"><span style="COLOR: blue">private</span> <span style="COLOR: #2b91af">OAuthUser</span> GetUser(<span style="COLOR: blue">string</span> token)
{
<span style="COLOR: #2b91af">HttpClient</span> request = <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">HttpClient</span>();
<span style="COLOR: blue">var</span> response = request.Get(<span style="COLOR: #a31515">"https://api.foursquare.com/v2/users/self?oauth_token="</span> + token);
<span style="COLOR: #2b91af">JObject</span> obj = (<span style="COLOR: #2b91af">JObject</span>)<span style="COLOR: #2b91af">JsonConvert</span>.DeserializeObject(response.Content.ReadAsString());
<span style="COLOR: blue">return</span> <span style="COLOR: blue">new</span> <span style="COLOR: #2b91af">OAuthUser</span>
{
Id = (<span style="COLOR: blue">string</span>)obj.SelectToken(<span style="COLOR: #a31515">"response.user.id"</span>),
UserName = (<span style="COLOR: blue">string</span>)obj.SelectToken(<span style="COLOR: #a31515">"response.user.firstName"</span>) + <span style="COLOR: #a31515">" "</span> + (<span style="COLOR: blue">string</span>)obj.SelectToken(<span style="COLOR: #a31515">"response.user.lastName"</span>),
AccessToken = token,
UserType = <span style="COLOR: #2b91af">UserType</span>.Foursquare
};
}</pre></div>
<div>La dernière étape pour faire fonctionner votre authentification consiste à créer un cookie en enregistrant votre utilisateur. Je ne l'explique pas dans ce post. Je vous invite à regarder ces deux liens:</div>
<div>- <a href="http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html" hreflang="en"><a href="http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html">http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html</a></div>- <a title="http://www.hanselman.com/blog/AccessingTheASPNETFormsAuthenticationTimeoutValue.aspx" href="http://www.hanselman.com/blog/AccessingTheASPNETFormsAuthenticationTimeoutValue.aspx" hreflang="en">http://www.hanselman.com/blog/AccessingTheASPNETFormsAuthenticationTimeoutValue.aspx</a>Création d'un custom WebControlurn:md5:8dfb3e3ba4715faa23341fec660d8a9f2010-09-30T18:39:00+02:002010-10-02T19:03:14+02:00Thierry ThouaASP.NET<p>Souvent utilisé, parfois mal utilisé ... Voici un petit post de rappel sur "comment créer un custom WebControl" basique composé de deux textbox sans passer par un CompositeControl. Notre cas concret ici sera donc la création d'un contrôle Identité. Bonne lecture ...</p> <h2>1) Page ASP.NET</h2>
<p>Voici une page ASP.NET que l'on va écrire. Le contrôle est réutilisable dans n'importe quelle page. Nous avons enregistré l'assembly/Namespace dans le fichier web.config afin de pouvoir y accéder dans les pages. Pour cette démonstration, nous avons mis "demo". Cet exemple représente donc un contrôle avec un login / pass et un évènement informant quand l'utilisateur a changé.</p>
<pre class="csharp"><span style="color: #0600FF;"><%</span>@ Page Language<span style="color: #0600FF;">=</span><span style="color: #808080;">"C#"</span> AutoEventWireup<span style="color: #0600FF;">=</span><span style="color: #808080;">"true"</span> CodeFile<span style="color: #0600FF;">=</span><span style="color: #808080;">"Default.aspx.cs"</span> Inherits<span style="color: #0600FF;">=</span><span style="color: #808080;">"_Default"</span> <span style="color: #0600FF;">%></span>
<span style="color: #0600FF;"><!</span>DOCTYPE html <span style="color: #0600FF;">PUBLIC</span> <span style="color: #808080;">"-//W3C//DTD XHTML 1.0 Transitional//EN"</span>
<span style="color: #808080;">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>html xmlns<span style="color: #0600FF;">=</span><span style="color: #808080;">"http://www.w3.org/1999/xhtml"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>head runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>title<span style="color: #0600FF;">></span>Exemple controle bas niveau<span style="color: #0600FF;"></</span>title<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>head<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>body<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>form id<span style="color: #0600FF;">=</span><span style="color: #808080;">"form1"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>demo<span style="color: #0600FF;">:</span>ControleIdentite ID<span style="color: #0600FF;">=</span><span style="color: #808080;">"monControle"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>Button ID<span style="color: #0600FF;">=</span><span style="color: #808080;">"btnSoumettre"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span> Text<span style="color: #0600FF;">=</span><span style="color: #808080;">"Soumettre"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>form<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>body<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>html<span style="color: #0600FF;">></span></pre>
<pre class="csharp"><span style="color: #0600FF;">using</span> <span style="color: #FFFFFF;">System</span>;
<span style="color: #0600FF;">using</span> <span style="color: #FFFFFF;">System</span>.<span style="color: #0000FF;">Collections</span>.<span style="color: #0000FF;">Generic</span>;
<span style="color: #0600FF;">using</span> <span style="color: #FFFFFF;">System</span>.<span style="color: #0000FF;">Linq</span>;
<span style="color: #0600FF;">using</span> <span style="color: #FFFFFF;">System</span>.<span style="color: #0000FF;">Web</span>;
<span style="color: #0600FF;">using</span> <span style="color: #FFFFFF;">System</span>.<span style="color: #0000FF;">Web</span>.<span style="color: #0000FF;">UI</span>;
<span style="color: #0600FF;">using</span> <span style="color: #FFFFFF;">System</span>.<span style="color: #0000FF;">Web</span>.<span style="color: #0000FF;">UI</span>.<span style="color: #0000FF;">WebControls</span>;
<span style="color: #0600FF;">public</span> partial <span style="color: #FF0000;">class</span> _Default <span style="color: #0600FF;">:</span> <span style="color: #FFFFFF;">System</span>.<span style="color: #0000FF;">Web</span>.<span style="color: #0000FF;">UI</span>.<span style="color: #0000FF;">Page</span>
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">void</span> Page_Load<span style="color: #0600FF;">(</span><span style="color: #FF0000;">object</span> sender, EventArgs e<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
monControle.<span style="color: #0000FF;">IdentiteChanged</span> <span style="color: #0600FF;">+=</span> <span style="color: #008000;">new</span> EventHandler<span style="color: #0600FF;">(</span>monControle_IdentiteChanged<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">void</span> monControle_IdentiteChanged<span style="color: #0600FF;">(</span><span style="color: #FF0000;">object</span> sender, EventArgs e<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span></pre>
<h2>2) Création du contrôle</h2>
<h3>a) Création de la classe.</h3>
<p>Celle-ci représente donc les 2 contrôles. Chaque contrôle a un identifiant unique.</p>
<pre class="csharp"><span style="color: #0600FF;">[</span>Serializable<span style="color: #0600FF;">]</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> Identite
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Prenom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Nom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span></pre>
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> ControleIdentite <span style="color: #0600FF;">:</span> WebControl, INamingContainer
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">public</span> Identite Identite
<span style="color: #0600FF;">{</span>
get
<span style="color: #0600FF;">{</span>
<span style="color: #FF0000;">object</span> o <span style="color: #0600FF;">=</span> ViewState<span style="color: #0600FF;">[</span><span style="color: #808080;">"Identite"</span><span style="color: #0600FF;">]</span>;
<span style="color: #0600FF;">return</span> <span style="color: #0600FF;">(</span>o <span style="color: #0600FF;">==</span> <span style="color: #0600FF;">null</span><span style="color: #0600FF;">)</span> <span style="color: #0600FF;">?</span> <span style="color: #008000;">new</span> Identite<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span> <span style="color: #0600FF;">:</span> <span style="color: #0600FF;">(</span>Identite<span style="color: #0600FF;">)</span>o;
<span style="color: #0600FF;">}</span>
set
<span style="color: #0600FF;">{</span>
ViewState<span style="color: #0600FF;">[</span><span style="color: #808080;">"Identite"</span><span style="color: #0600FF;">]</span> <span style="color: #0600FF;">=</span> value;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> ControleIdentite<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">:</span> <span style="color: #0600FF;">base</span><span style="color: #0600FF;">(</span>HtmlTextWriterTag.<span style="color: #0000FF;">Div</span><span style="color: #0600FF;">)</span> <span style="color: #0600FF;">{</span> <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> RenderContents<span style="color: #0600FF;">(</span>HtmlTextWriter writer<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">RenderContents</span><span style="color: #0600FF;">(</span>writer<span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">Write</span><span style="color: #0600FF;">(</span><span style="color: #808080;">"Nom : "</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Type</span>, <span style="color: #808080;">"text"</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Id</span>, <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">ClientID</span> <span style="color: #0600FF;">+</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">ClientIDSeparator</span> <span style="color: #0600FF;">+</span> <span style="color: #808080;">"nom"</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Name</span>, <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">UniqueID</span> <span style="color: #0600FF;">+</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">IdSeparator</span> <span style="color: #0600FF;">+</span> <span style="color: #808080;">"nom"</span><span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">if</span> <span style="color: #0600FF;">(</span><span style="color: #0600FF;">!</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">Identite</span>.<span style="color: #0000FF;">Nom</span><span style="color: #0600FF;">)</span><span style="color: #0600FF;">)</span>
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Value</span>, <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">Identite</span>.<span style="color: #0000FF;">Nom</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">RenderBeginTag</span><span style="color: #0600FF;">(</span>HtmlTextWriterTag.<span style="color: #0000FF;">Input</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">RenderEndTag</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">WriteBreak</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">Write</span><span style="color: #0600FF;">(</span><span style="color: #808080;">"Prénom : "</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Type</span>, <span style="color: #808080;">"text"</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Id</span>, <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">ClientID</span> <span style="color: #0600FF;">+</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">ClientIDSeparator</span> <span style="color: #0600FF;">+</span> <span style="color: #808080;">"prenom"</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Name</span>, <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">UniqueID</span> <span style="color: #0600FF;">+</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">IdSeparator</span> <span style="color: #0600FF;">+</span> <span style="color: #808080;">"prenom"</span><span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">if</span> <span style="color: #0600FF;">(</span><span style="color: #0600FF;">!</span><span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">Identite</span>.<span style="color: #0000FF;">Prenom</span><span style="color: #0600FF;">)</span><span style="color: #0600FF;">)</span>
writer.<span style="color: #0000FF;">AddAttribute</span><span style="color: #0600FF;">(</span>HtmlTextWriterAttribute.<span style="color: #0000FF;">Value</span>, <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">Identite</span>.<span style="color: #0000FF;">Prenom</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">RenderBeginTag</span><span style="color: #0600FF;">(</span>HtmlTextWriterTag.<span style="color: #0000FF;">Input</span><span style="color: #0600FF;">)</span>;
writer.<span style="color: #0000FF;">RenderEndTag</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span></pre>
<h3>b) Gestion du PostBack.</h3>
<p>Si l'on teste l'exemple ci-dessus, on remarque rapidement que lorsqu'on clique sur le bouton de la page, on perd les données du contrôle. Nous allons donc ajouter la gestion du postback dans le contrôle ainsi que lever un évènement lorsque l'identité à changé. Pour ce faire, on va implémenter l'interface IPostBackDataHandler sur notre contrôle.</p>
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> ControleIdentite <span style="color: #0600FF;">:</span> WebControl, INamingContainer, IPostBackDataHandler
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">event</span> EventHandler IdentiteChanged;
....
<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> OnPreRender<span style="color: #0600FF;">(</span>EventArgs e<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #008080; font-style: italic;">// Il est important d'enregistrer le contrôle sur la page pour la gestion du PostBack</span>
Page.<span style="color: #0000FF;">RegisterRequiresPostBack</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">this</span><span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">OnPreRender</span><span style="color: #0600FF;">(</span>e<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #008080;">#region IPostBackDataHandler Members</span>
<span style="color: #FF0000;">bool</span> IPostBackDataHandler.<span style="color: #0000FF;">LoadPostData</span><span style="color: #0600FF;">(</span><span style="color: #FF0000;">string</span> postDataKey, NameValueCollection postCollection<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #008080; font-style: italic;">// On va regarder si l'identité à changée. Si on retourne true, la méthode RaisePostDataChangedEvent</span>
<span style="color: #008080; font-style: italic;">// sera lancée. </span>
Identite identite <span style="color: #0600FF;">=</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">Identite</span>;
var nom_value <span style="color: #0600FF;">=</span> postCollection<span style="color: #0600FF;">[</span><span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">UniqueID</span> <span style="color: #0600FF;">+</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">IdSeparator</span> <span style="color: #0600FF;">+</span> <span style="color: #808080;">"nom"</span><span style="color: #0600FF;">]</span>;
var prenom_value <span style="color: #0600FF;">=</span> postCollection<span style="color: #0600FF;">[</span><span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">UniqueID</span> <span style="color: #0600FF;">+</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">IdSeparator</span> <span style="color: #0600FF;">+</span> <span style="color: #808080;">"prenom"</span><span style="color: #0600FF;">]</span>;
<span style="color: #FF0000;">bool</span> hasChanged <span style="color: #0600FF;">=</span> <span style="color: #0600FF;">false</span>;
<span style="color: #0600FF;">if</span> <span style="color: #0600FF;">(</span>identite.<span style="color: #0000FF;">Nom</span> <span style="color: #0600FF;">!=</span> nom_value<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
identite.<span style="color: #0000FF;">Nom</span> <span style="color: #0600FF;">=</span> nom_value;
hasChanged <span style="color: #0600FF;">=</span> <span style="color: #0600FF;">true</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">if</span> <span style="color: #0600FF;">(</span>identite.<span style="color: #0000FF;">Prenom</span> <span style="color: #0600FF;">!=</span> prenom_value<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
identite.<span style="color: #0000FF;">Prenom</span> <span style="color: #0600FF;">=</span> prenom_value;
hasChanged <span style="color: #0600FF;">=</span> <span style="color: #0600FF;">true</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">if</span> <span style="color: #0600FF;">(</span>hasChanged<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">Identite</span> <span style="color: #0600FF;">=</span> identite;
<span style="color: #0600FF;">return</span> hasChanged;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">void</span> IPostBackDataHandler.<span style="color: #0000FF;">RaisePostDataChangedEvent</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #008080; font-style: italic;">// Nous levons l'évènement de changement de l'identité</span>
<span style="color: #0600FF;">if</span> <span style="color: #0600FF;">(</span>IdentiteChanged <span style="color: #0600FF;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #0600FF;">)</span>
IdentiteChanged<span style="color: #0600FF;">(</span><span style="color: #0600FF;">this</span>, EventArgs.<span style="color: #0000FF;">Empty</span><span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #008080;">#endregion</span>
<span style="color: #0600FF;">}</span></pre>
<h2>3) Conclusion</h2>
<p>Vous venez de voir comment créer un petit contrôle de bas niveau gérant le postback sans passer par un contrôle Composite. Ce type de contrôle est certes souvent plus verbeux mais on maîtrise exactement l'html généré ainsi que tout ce qui est mis dans le ViewState. Si vous avez la moindre question, n'hésitez pas à me l'envoyer par mail ou en commentaire ici.</p>Gridview ASP.NET avec en source une collection d'elements "interface'urn:md5:573e2100782709072b424ebc481e8cd72009-10-11T18:00:00+02:002009-10-11T17:18:25+02:00Thierry ThouaASP.NET<p>J'ai été confronté ce vendredi au travail à une petite question "classique" que les développeurs posent quand ils remarquent un "problème" avec l'utilisation des GridView .... à savoir ... comment afficher dans une GridView une collection d'éléments de types différents ... Voici la réponse dans ce post !</p> <p>Prenons par exemple une interface décrivant un profil .. Nous afficherons donc dans la vue une grille avec le nom et le prénom.</p>
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">interface</span> IMonInterface
<span style="color: #0600FF;">{</span>
<span style="color: #FF0000;">string</span> Nom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #FF0000;">string</span> Prenom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span></pre>
<p>Nous allons implémenter cette interface dans deux classes différentes ... A et B ... Nous aurions pu dire "Homme" / "Femme" ... Ce n'est pas important !</p>
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> A <span style="color: #0600FF;">:</span> IMonInterface
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Nom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Prenom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">int</span> Age <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> B <span style="color: #0600FF;">:</span> IMonInterface
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Nom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Prenom <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> Sexe <span style="color: #0600FF;">{</span> get; set; <span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span></pre>
<p>Afin de rendre les données dans la grille ASP.NET 2.0, nous remplissons la liste et nous fournissons cette liste a notre grille.</p>
<pre class="csharp"><span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">void</span> Page_Load<span style="color: #0600FF;">(</span><span style="color: #FF0000;">object</span> sender, EventArgs e<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
List<span style="color: #0600FF;"><</span>IMonInterface<span style="color: #0600FF;">></span> macollection <span style="color: #0600FF;">=</span> <span style="color: #008000;">new</span> List<span style="color: #0600FF;"><</span>IMonInterface<span style="color: #0600FF;">></span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #008000;">new</span> B<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span><span style="color: #0600FF;">{</span> Nom<span style="color: #0600FF;">=</span><span style="color: #808080;">"Alfred"</span>, Prenom<span style="color: #0600FF;">=</span><span style="color: #808080;">"Jean"</span>, Sexe<span style="color: #0600FF;">=</span> <span style="color: #0600FF;">true</span><span style="color: #0600FF;">}</span>,
<span style="color: #008000;">new</span> B<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span><span style="color: #0600FF;">{</span> Nom<span style="color: #0600FF;">=</span><span style="color: #808080;">"Alfredo"</span>, Prenom<span style="color: #0600FF;">=</span><span style="color: #808080;">"Jeanot"</span>, Sexe<span style="color: #0600FF;">=</span> <span style="color: #0600FF;">false</span><span style="color: #0600FF;">}</span>,
<span style="color: #008000;">new</span> A<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span><span style="color: #0600FF;">{</span> Nom<span style="color: #0600FF;">=</span><span style="color: #808080;">"Jean"</span>, Prenom<span style="color: #0600FF;">=</span><span style="color: #808080;">"Conrad"</span>, Age<span style="color: #0600FF;">=</span><span style="color: #FF0000;">18</span><span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span>;
gv.<span style="color: #0000FF;">DataSource</span> <span style="color: #0600FF;">=</span> macollection;
gv.<span style="color: #0000FF;">DataBind</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span></pre>
<p>Que ce soit en AutoGenerateColumns ou en BoundField (ci-dessous), nous aurons une exception de type : "L'accesseur de propriété 'Nom' sur l'objet 'WebApplicationAjax4.A' a levé l'exception suivante :'L'objet ne correspond pas au type cible.'".... Il faut donc comprendre que le type joue un rôle important dans la reflection pour le remplissage d'une GridView ...</p>
<pre class="csharp"><span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>BoundField DataField<span style="color: #0600FF;">=</span><span style="color: #808080;">"Nom"</span> <span style="color: #0600FF;">/></span></pre>
<p>Mais comment faire pour que cela fonctionne <acronym></acronym>? Simple ... Il faut réflechir au comportement du BoundField et au comportement du ItemTemplate ... On se rend vite compte que si on implémente le code ci-dessous .... l'utilisation du "Eval" nous permettra de rendre via un autre mécanisme l'information ... Le type n'étant plus pris en compte de la même façon, le rendu fonctionne parfaitement ... Voici donc une solution au problème ! Vous en avez une autre ? Un petit commentaire est le bienvenu ... !</p>
<pre class="csharp"><span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>GridView ID<span style="color: #0600FF;">=</span><span style="color: #808080;">"gv"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span> AutoGenerateColumns<span style="color: #0600FF;">=</span><span style="color: #808080;">"False"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>Columns<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>TemplateField<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>ItemTemplate<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>Label runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span> ID<span style="color: #0600FF;">=</span><span style="color: #808080;">"nomID"</span> Text<span style="color: #0600FF;">=</span><span style="color: #808080;">'<%# Eval("Nom")%>'</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>ItemTemplate<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>asp<span style="color: #0600FF;">:</span>TemplateField<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>TemplateField<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>ItemTemplate<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>Label runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span> ID<span style="color: #0600FF;">=</span><span style="color: #808080;">"prenomID"</span> Text<span style="color: #0600FF;">=</span><span style="color: #808080;">'<%# Eval("Prenom")%>'</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>ItemTemplate<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>asp<span style="color: #0600FF;">:</span>TemplateField<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>Columns<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>asp<span style="color: #0600FF;">:</span>GridView<span style="color: #0600FF;">></span></pre>Custom engine en ASP.NET MVC 1.0urn:md5:d469912cc315071f29fc691a8b5202372009-07-06T22:00:00+02:002009-07-06T21:29:06+02:00Thierry ThouaASP.NET<p>La force d'asp.net MVC est sa modularité. Il est possible en quelques minutes de modifier les "briques" de base du projet. Je vais expliquer comment le réaliser. Le but de ce post n'est pas de faire un cas "concret" mais d'expliquer comment le faire. Je vais donc montrer comment modifier le module "Controller" et "Vue" du projet.</p> <h3>1) Controller</h3>
<p>Le controlleur est une des brique super importante. Parfois, il faut ajouter des comportements ou des données sous forme de propriétés comme par exemple des collections de "droits",.... En effet, il faut parfois instancier un autre controller en fonction d'un contexte Y. Ceci se fait très rapidement en ASP.NET MVC. Il suffit d'implémenter une classe héritant par exemple de la classe "standard" utilisée dans le framework. On Ajoutera le comportement dans cette classe. La génération des classes "Controller" passera toujours par cette classe !</p>
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> CustomControllerFactory <span style="color: #0600FF;">:</span> DefaultControllerFactory
<span style="color: #0600FF;">{</span>
<span style="color: #008080; font-style: italic;">// Création d'une classe IController</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> IController CreateController<span style="color: #0600FF;">(</span>RequestContext requestContext, <span style="color: #FF0000;">string</span> controllerName<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">CreateController</span><span style="color: #0600FF;">(</span>requestContext, controllerName<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #008080; font-style: italic;">// Fin des traitements</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> ReleaseController<span style="color: #0600FF;">(</span>IController controller<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">ReleaseController</span><span style="color: #0600FF;">(</span>controller<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span></pre>
<p>Cependant, tout ne fonctionne pas directement. En effet, il faut enregistrer la factory de controller comme étant celle à utiliser dans l'applicatif.</p>
<pre class="csharp">ControllerBuilder.<span style="color: #0000FF;">Current</span>.<span style="color: #0000FF;">SetControllerFactory</span><span style="color: #0600FF;">(</span><span style="color: #008000;">typeof</span><span style="color: #0600FF;">(</span>CustomControllerFactory<span style="color: #0600FF;">)</span><span style="color: #0600FF;">)</span>;</pre>
<h3>2) View Engine</h3>
<p>Il est également possible de "modifier" la factory gérant le rendu dans l'application. Cela offre de nouvelles perspectives comme le support de plusieurs vues différentes en fonction du "browser". Il est donc possible en quelques lignes d'avoir une vue pour IPhone et une autre vue pour IE tout en gardant le même controller etc etc. Pour se faire il faut surcharger la méthode recherchant les bonnes vues !</p>
<pre class="csharp"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> CustomViewEngine <span style="color: #0600FF;">:</span> WebFormViewEngine
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> IView CreatePartialView<span style="color: #0600FF;">(</span>ControllerContext controllerContext, <span style="color: #FF0000;">string</span> partialPath<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">CreatePartialView</span><span style="color: #0600FF;">(</span>controllerContext, partialPath<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> IView CreateView<span style="color: #0600FF;">(</span>ControllerContext controllerContext, <span style="color: #FF0000;">string</span> viewPath, <span style="color: #FF0000;">string</span> masterPath<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #008080; font-style: italic;">// Méthode appelée en second</span>
<span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">CreateView</span><span style="color: #0600FF;">(</span>controllerContext, viewPath, masterPath<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> ViewEngineResult FindView<span style="color: #0600FF;">(</span>ControllerContext controllerContext, <span style="color: #FF0000;">string</span> viewName, <span style="color: #FF0000;">string</span> masterName, <span style="color: #FF0000;">bool</span> useCache<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #008080; font-style: italic;">// Méthode appelée en premier</span>
<span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">FindView</span><span style="color: #0600FF;">(</span>controllerContext, viewName, masterName, useCache<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> ViewEngineResult FindPartialView<span style="color: #0600FF;">(</span>ControllerContext controllerContext, <span style="color: #FF0000;">string</span> partialViewName, <span style="color: #FF0000;">bool</span> useCache<span style="color: #0600FF;">)</span>
<span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">FindPartialView</span><span style="color: #0600FF;">(</span>controllerContext, partialViewName, useCache<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span></pre>
<p>Il faut également toujours comme précisé plus haut modifier le moteur de rendu dans le fichier global.asax pour prendre en compte le nouveau moteur.</p>
<pre class="csharp">ViewEngines.<span style="color: #0000FF;">Engines</span>.<span style="color: #0000FF;">Clear</span><span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span>;
ViewEngines.<span style="color: #0000FF;">Engines</span>.<span style="color: #0000FF;">Add</span><span style="color: #0600FF;">(</span><span style="color: #008000;">new</span> CustomViewEngine<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span><span style="color: #0600FF;">)</span>;</pre>
<h3>3) Conclusion</h3>
<p>Après lecture de ce post, il vous sera très facile d'ajouter de nouvelles opportunités à votre application ASP.NET MVC ! Si vous voulez par exemple ajouter le support des "mobiles", je vous conseille également le fichier "browser" des mobiles disponible ici.</p>Client Ajax pour ADO.Net data Services (opération SELECT)urn:md5:f56d06445b68a40814c07d230b4c06e82009-04-07T23:08:00+02:002009-04-07T23:08:00+02:00Thierry ThouaASP.NET<p>Le but de ce mini post est de montrer qu'il est possible de faire rapidement une page Ajax contenant une dropdown qui se remplit lorsqu'on le souhaite via une requête sur le "service" ADO.Net que l'on a créé dans les précédents posts !. Ce type de développement offre de belles perspectives et va réduire la taille du viewstate & le nombre de ko transféré en POST au serveur ... Que du positif pour l'optimisation du site web !</p> <h3>1°) La première étape est de créer une simple page asp.Net avec la dropdown et le code javascript vide d'appel lors du click sur le bouton. C'est lors de ce clic que l'on chargera la dropdown !</h3>
<pre class="csharp"><span style="color: #0600FF;"><%</span>@ Page Language<span style="color: #0600FF;">=</span><span style="color: #808080;">"C#"</span> AutoEventWireup<span style="color: #0600FF;">=</span><span style="color: #808080;">"true"</span> CodeFile<span style="color: #0600FF;">=</span><span style="color: #808080;">"Default.aspx.cs"</span> Inherits<span style="color: #0600FF;">=</span><span style="color: #808080;">"_Default"</span> <span style="color: #0600FF;">%></span>
<span style="color: #0600FF;"><!</span>DOCTYPE html <span style="color: #0600FF;">PUBLIC</span> <span style="color: #808080;">"-//W3C//DTD XHTML 1.0 Transitional//EN"</span> <span style="color: #808080;">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>html xmlns<span style="color: #0600FF;">=</span><span style="color: #808080;">"http://www.w3.org/1999/xhtml"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>head runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>title<span style="color: #0600FF;">></span>Page de démo<span style="color: #0600FF;"></</span>title<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>script type<span style="color: #0600FF;">=</span><span style="color: #808080;">"text/javascript"</span> language<span style="color: #0600FF;">=</span><span style="color: #808080;">"javascript"</span><span style="color: #0600FF;">></span>
function ChargePays<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span> <span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;"></</span>script<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>head<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>body<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>form id<span style="color: #0600FF;">=</span><span style="color: #808080;">"form1"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>select id<span style="color: #0600FF;">=</span><span style="color: #808080;">"cbPays"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>select<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>br <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>input id<span style="color: #0600FF;">=</span><span style="color: #808080;">"fillPays"</span> type<span style="color: #0600FF;">=</span><span style="color: #808080;">"button"</span> value<span style="color: #0600FF;">=</span><span style="color: #808080;">"Charge les pays"</span> onclick<span style="color: #0600FF;">=</span><span style="color: #808080;">"ChargePays();"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>form<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>body<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>html<span style="color: #0600FF;">></span></pre>
<h3>2°) La seconde étape consiste à remplir le code HTML du body en y ajoutant les références aux fichiers JS !</h3>
<pre class="csharp"><span style="color: #0600FF;"><</span>body<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>form id<span style="color: #0600FF;">=</span><span style="color: #808080;">"form1"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptManager ID<span style="color: #0600FF;">=</span><span style="color: #808080;">"ScriptManager1"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>Scripts<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptReference Path<span style="color: #0600FF;">=</span><span style="color: #808080;">"MicrosoftAjax.js"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptReference Path<span style="color: #0600FF;">=</span><span style="color: #808080;">"MicrosoftAjaxTemplates.js"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptReference Path<span style="color: #0600FF;">=</span><span style="color: #808080;">"MicrosoftAjaxAdoNet.js"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>Scripts<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>asp<span style="color: #0600FF;">:</span>ScriptManager<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>select id<span style="color: #0600FF;">=</span><span style="color: #808080;">"cbPays"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>select<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>br <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>input id<span style="color: #0600FF;">=</span><span style="color: #808080;">"fillPays"</span> type<span style="color: #0600FF;">=</span><span style="color: #808080;">"button"</span> value<span style="color: #0600FF;">=</span><span style="color: #808080;">"Charge les pays"</span> onclick<span style="color: #0600FF;">=</span><span style="color: #808080;">"ChargePays();"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>form<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>body<span style="color: #0600FF;">></span></pre>
<h3>3°) La troisième étape consiste à implémenter la logique de réquêtage du service ADO.NET (astoria).</h3>
<pre class="javascript"><span style="color: #66cc66;"><</span>script type=<span style="color: #3366CC;">"text/javascript"</span> language=<span style="color: #3366CC;">"javascript"</span><span style="color: #66cc66;">></span>
<span style="color: #003366; font-weight: bold;">function</span> ChargePays<span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #003366; font-weight: bold;">var</span> dataService = <span style="color: #003366; font-weight: bold;">new</span> Sys.<span style="color: #006600;">Data</span>.<span style="color: #006600;">AdoNetServiceProxy</span><span style="color: #66cc66;">(</span><span style="color: #3366CC;">"WebDataServiceAstoria.svc"</span><span style="color: #66cc66;">)</span>;
dataService.<span style="color: #006600;">query</span><span style="color: #66cc66;">(</span><span style="color: #3366CC;">"Pays"</span>, ExecutionReussite, ExcutionEchec<span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span>
<span style="color: #003366; font-weight: bold;">function</span> ExecutionReussite<span style="color: #66cc66;">(</span>result, context, operation<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #66cc66;">}</span>
<span style="color: #003366; font-weight: bold;">function</span> ExcutionEchec<span style="color: #66cc66;">(</span>error, context, operation<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #000066;">alert</span><span style="color: #66cc66;">(</span>error<span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span>
<span style="color: #66cc66;"></</span>script<span style="color: #66cc66;">></span></pre>
<h3>4°) La quatrième étape consiste à remplir la dropdown avec les valeurs récupérées via le service</h3>
<pre class="javascript"><span style="color: #66cc66;"><</span>script type=<span style="color: #3366CC;">"text/javascript"</span> language=<span style="color: #3366CC;">"javascript"</span><span style="color: #66cc66;">></span>
<span style="color: #003366; font-weight: bold;">function</span> ExecutionReussite<span style="color: #66cc66;">(</span>result, context, operation<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #66cc66;">(</span>result <span style="color: #66cc66;">!</span>= <span style="color: #003366; font-weight: bold;">null</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
<span style="color: #003366; font-weight: bold;">var</span> select = $get<span style="color: #66cc66;">(</span><span style="color: #3366CC;">"cbPays"</span><span style="color: #66cc66;">)</span>;
select.<span style="color: #006600;">length</span> = <span style="color: #CC0000;">0</span>;
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #66cc66;">(</span>i = <span style="color: #CC0000;">0</span>; i <span style="color: #66cc66;"><</span> result.<span style="color: #006600;">length</span>; i++<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">{</span>
select.<span style="color: #006600;">options</span>.<span style="color: #006600;">add</span><span style="color: #66cc66;">(</span><span style="color: #003366; font-weight: bold;">new</span> Option<span style="color: #66cc66;">(</span>result<span style="color: #66cc66;">[</span>i<span style="color: #66cc66;">]</span>.<span style="color: #006600;">Nom</span>, result<span style="color: #66cc66;">[</span>i<span style="color: #66cc66;">]</span>.<span style="color: #006600;">ID</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>;
<span style="color: #66cc66;">}</span>
<span style="color: #66cc66;">}</span>
<span style="color: #66cc66;">}</span>
<span style="color: #66cc66;"></</span>script<span style="color: #66cc66;">></span></pre>
<h3>5°) Voici le résultat final du code implémenté !</h3>
<pre class="csharp"><span style="color: #0600FF;"><%</span>@ Page Language<span style="color: #0600FF;">=</span><span style="color: #808080;">"C#"</span> AutoEventWireup<span style="color: #0600FF;">=</span><span style="color: #808080;">"true"</span> CodeFile<span style="color: #0600FF;">=</span><span style="color: #808080;">"Default.aspx.cs"</span> Inherits<span style="color: #0600FF;">=</span><span style="color: #808080;">"_Default"</span> <span style="color: #0600FF;">%></span>
<span style="color: #0600FF;"><!</span>DOCTYPE html <span style="color: #0600FF;">PUBLIC</span> <span style="color: #808080;">"-//W3C//DTD XHTML 1.0 Transitional//EN"</span> <span style="color: #808080;">"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>html xmlns<span style="color: #0600FF;">=</span><span style="color: #808080;">"http://www.w3.org/1999/xhtml"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>head runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>title<span style="color: #0600FF;">></span>Page de démo<span style="color: #0600FF;"></</span>title<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>script type<span style="color: #0600FF;">=</span><span style="color: #808080;">"text/javascript"</span> language<span style="color: #0600FF;">=</span><span style="color: #808080;">"javascript"</span><span style="color: #0600FF;">></span>
function ChargePays<span style="color: #0600FF;">(</span><span style="color: #0600FF;">)</span> <span style="color: #0600FF;">{</span>
var dataService <span style="color: #0600FF;">=</span> <span style="color: #008000;">new</span> Sys.<span style="color: #0000FF;">Data</span>.<span style="color: #0000FF;">AdoNetServiceProxy</span><span style="color: #0600FF;">(</span><span style="color: #808080;">"WebDataServiceAstoria.svc"</span><span style="color: #0600FF;">)</span>;
dataService.<span style="color: #0000FF;">query</span><span style="color: #0600FF;">(</span><span style="color: #808080;">"Pays"</span>, ExecutionReussite, ExcutionEchec<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
function ExecutionReussite<span style="color: #0600FF;">(</span>result, context, operation<span style="color: #0600FF;">)</span> <span style="color: #0600FF;">{</span>
<span style="color: #0600FF;">if</span> <span style="color: #0600FF;">(</span>result <span style="color: #0600FF;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #0600FF;">)</span> <span style="color: #0600FF;">{</span>
var select <span style="color: #0600FF;">=</span> $get<span style="color: #0600FF;">(</span><span style="color: #808080;">"cbPays"</span><span style="color: #0600FF;">)</span>;
select.<span style="color: #0000FF;">length</span> <span style="color: #0600FF;">=</span> <span style="color: #FF0000;">0</span>;
<span style="color: #0600FF;">for</span> <span style="color: #0600FF;">(</span>i <span style="color: #0600FF;">=</span> <span style="color: #FF0000;">0</span>; i <span style="color: #0600FF;"><</span> result.<span style="color: #0000FF;">length</span>; i<span style="color: #0600FF;">++</span><span style="color: #0600FF;">)</span> <span style="color: #0600FF;">{</span>
select.<span style="color: #0000FF;">options</span>.<span style="color: #0000FF;">add</span><span style="color: #0600FF;">(</span><span style="color: #008000;">new</span> Option<span style="color: #0600FF;">(</span>result<span style="color: #0600FF;">[</span>i<span style="color: #0600FF;">]</span>.<span style="color: #0000FF;">Nom</span>, result<span style="color: #0600FF;">[</span>i<span style="color: #0600FF;">]</span>.<span style="color: #0000FF;">ID</span><span style="color: #0600FF;">)</span><span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;">}</span>
function ExcutionEchec<span style="color: #0600FF;">(</span>error, context, operation<span style="color: #0600FF;">)</span> <span style="color: #0600FF;">{</span>
alert<span style="color: #0600FF;">(</span>error<span style="color: #0600FF;">)</span>;
<span style="color: #0600FF;">}</span>
<span style="color: #0600FF;"></</span>script<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>head<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>body<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>form id<span style="color: #0600FF;">=</span><span style="color: #808080;">"form1"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptManager ID<span style="color: #0600FF;">=</span><span style="color: #808080;">"ScriptManager1"</span> runat<span style="color: #0600FF;">=</span><span style="color: #808080;">"server"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>Scripts<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptReference Path<span style="color: #0600FF;">=</span><span style="color: #808080;">"MicrosoftAjax.js"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptReference Path<span style="color: #0600FF;">=</span><span style="color: #808080;">"MicrosoftAjaxTemplates.js"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>asp<span style="color: #0600FF;">:</span>ScriptReference Path<span style="color: #0600FF;">=</span><span style="color: #808080;">"MicrosoftAjaxAdoNet.js"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>Scripts<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>asp<span style="color: #0600FF;">:</span>ScriptManager<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>select id<span style="color: #0600FF;">=</span><span style="color: #808080;">"cbPays"</span><span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>select<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"><</span>br <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"><</span>input id<span style="color: #0600FF;">=</span><span style="color: #808080;">"fillPays"</span> type<span style="color: #0600FF;">=</span><span style="color: #808080;">"button"</span> value<span style="color: #0600FF;">=</span><span style="color: #808080;">"Charge les pays"</span> onclick<span style="color: #0600FF;">=</span><span style="color: #808080;">"ChargePays();"</span> <span style="color: #0600FF;">/></span>
<span style="color: #0600FF;"></</span>div<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>form<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>body<span style="color: #0600FF;">></span>
<span style="color: #0600FF;"></</span>html<span style="color: #0600FF;">></span></pre>
<p>Et en images !</p>
<p>Avant la requête:</p>
<p><img src="http://www.lelibre.net/public/ASP.NET/AJax_Preview_4_-_Astoria/.ajax_avant_m.jpg" alt="ajax_avant.png" title="ajax_avant.png, avr. 2009" /></p>
<p>Après la requête:
<img src="http://www.lelibre.net/public/ASP.NET/AJax_Preview_4_-_Astoria/.ajax_apres_m.jpg" alt="ajax_apres.png" title="ajax_apres.png, avr. 2009" /></p>
<h3>6°) Conclusion</h3>
<p>Ce petit post montre combien il est simple d'implémenter ce type de récupération en quelques minutes. Cette démonstration a été réalisée sous <a href="http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24645">ASP.NET Ajax Preview 4</a>. Elle ne fonctionnera pas avec les preview précédentes. En effet, les noms des classes JS pour requêter Astoria ont un peu changé.</p>Merge rapide de colonnes d'une GridView en ASP.NETurn:md5:f22aab84f214aa874e73bd07068347432009-03-26T22:45:00+01:002009-03-26T22:46:45+01:00Thierry ThouaASP.NET<p>Il est si simple d'avoir une petite gridview dans une page ASP.NET pour afficher des résultats... Mais qu'en est il d'un regroupement des mêmes valeurs ... En effet, parfois on ne veut qu'une seule occurence propre dans une colonne ...Par exemple un seul lien externe qui représente le lien qui nous amènera vers l'ensemble des lignes de la grille ayant le "même type". Il est évidement possible de jouer avec le RowSpan d'une grille en quelques minutes. Bref anyway ! Passons a l'exemple ... Ce sera plus parlant ;-)</p> <h4>Prenons une simple classe "business" que l'on souhaite afficher dans une GridView:</h4>
<p>public class DocumentAttache<br />{<br /> public int TypeDocument { get; set; }<br /> public string Nom { get; set; }<br /> public string Description { get; set; }<br />}</p>
<h4>Créons la grille dans une page ASP.NET</h4>
<p>protected void Page_Load(object sender, EventArgs e)<br />{<br /> if (!IsPostBack)<br /> {<br /> List<DocumentAttache> liste = new List<DocumentAttache>();<br /> liste.Add(new DocumentAttache() { TypeDocument = 1, Nom = "Doc1", Description = "Description Doc1" });<br /> liste.Add(new DocumentAttache() { TypeDocument = 1, Nom = "Doc2", Description = "Description Doc2" });<br /> liste.Add(new DocumentAttache() { TypeDocument = 1, Nom = "Doc3", Description = "Description Doc3" });<br /> liste.Add(new DocumentAttache() { TypeDocument = 2, Nom = "Doc4", Description = "Description Doc4" });<br /> liste.Add(new DocumentAttache() { TypeDocument = 2, Nom = "Doc5", Description = "Description Doc5" });<br /> liste.Add(new DocumentAttache() { TypeDocument = 3, Nom = "Doc7", Description = "Description Doc7" });<br /> liste.Add(new DocumentAttache() { TypeDocument = 3, Nom = "Doc7", Description = "Description Doc7" });<br /> this.GridView1.DataSource = liste;<br /> this.GridView1.DataBind();<br /> MergeColumn(this.GridView1, 0);<br /> }<br />}</p>
<p>Comme vous avez pu le voir plus haut dans le remplissage de la gridview, il y a la dernière ligne du précédent code qui est "intéressante" pour le "merge des colonnes.</p>
<p>Mais qu'en est il derrière ?</p>
<h4>Le merge des colonnes</h4>
<p>Voici la réponse : </p>
<p>private static void MergeColumn(GridView gv, int position)<br />{<br /> Dictionary<string, int> hash = new Dictionary<string, int>();<br /> string currentText = string.Empty;<br /> int count = 0;<br /> int currentCell = 0;<br /> do<br /> {<br /> GridViewRow dataRow = gv.Rows[currentCell++];<br /> if (dataRow.RowType == DataControlRowType.DataRow)<br /> {<br /> bool sameText = dataRow.Cells[position].Text == currentText;<br /> if (currentCell == gv.Rows.Count)<br /> {<br /> if (!sameText)<br /> {<br /> // Fin mais pas meme texte<br /> if (count > 1)<br /> hash.Add(currentText, count);<br /> }<br /> else<br /> {<br /> // Fin meme texte<br /> hash.Add(currentText, count + 1);<br /> }<br /> }<br /> else<br /> {<br /> // Pas meme texte<br /> if (!sameText)<br /> {<br /> if (count > 1)<br /> hash.Add(currentText, count);<br /> currentText = dataRow.Cells[position].Text;<br /> count = 0;<br /> }<br /> }<br /><br /> ++count;<br /> }<br /> }<br /> while (currentCell < gv.Rows.Count);<br /><br /> currentText = string.Empty;<br /> foreach (GridViewRow row in gv.Rows)<br /> {<br /> if (row.RowType == DataControlRowType.DataRow &&<br /> hash.ContainsKey(row.Cells[position].Text))<br /> {<br /> if (row.Cells[position].Text == currentText)<br /> row.Cells.Remove(row.Cells[position]);<br /> else<br /> {<br /> currentText = row.Cells[position].Text;<br /> row.Cells[position].RowSpan = hash[currentText];<br /> row.Cells[position].VerticalAlign = VerticalAlign.Middle;<br /> }<br /><br /> }<br /><br /> }<br />}</p>
<h4>Voici le résultat:</h4>
<p><img title="Merge column GridView ASP.NET, mar. 2009" alt="" src="http://www.lelibre.net/index.php?post/2009/03/26/../public/MergeGridView.png" /></p>
<p>Evidement, je suis preneur pour simplifier mon code de merge ;-). Mais ce soir ... la migraine m'empêche d'optimiser =S</p>Création d'un système de notification en Ajax (microsoft)urn:md5:eb22a686864e5ca595a8c745805a3e9a2009-03-03T19:58:00+01:002009-03-17T21:47:13+01:00Thierry ThouaASP.NET<h1 style="text-decoration: underline;">I<strong>ntroduction</strong></h1>
Je vais vous présenter ici un petit mécanisme de notification passant
par un webservice. A interval régulier, le client via Javascript va
demander au webservice une information. Nous utiliserons ici le
framework Ajax de Microsoft.<br /> <h1><ins><strong>Implémentation</strong></ins></h1>
L'implémentation se réalise en deux étapes. La première concerne la création de la page statique avec un div qui se rendra en bas à droite et disparaitra. La seconde étape est la réalisation du webservice et l'implémentation du code JS faisant appel à ce service dédié.<br /><br /><h3 style="text-decoration: underline;">Code de la page web vide de logique</h3>
<pre><%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" <br /> Inherits="_Default" %><br /><br /><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <br /> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /><head runat="server"><br /> <title></title><br /></head><br /><body><br /> <form id="form1" runat="server"><br /> <div><br /> Pif paf pouf ;-)<br /> </div><br /> <div id="modal_dialog" style="visibility: hidden; display: none;"><br /> <div><br /> Mon popup !<span style="cursor: hand" onclick="javascript:HidePopup();"><br /> <img alt="Hide Popup" src="http://www.lelibre.net/index.php?post/2009/02/04/close.png" style="height: 24px; width: 24px;" /><br /> </span><br /> </div><br /> <div id="modal_dialog_content"><br /> </div><br /> </div><br /> </form><br /></body><br /></html></pre><h3 style="text-decoration: underline;">Implémentation de la logique du Service web</h3>
<pre>using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Web;<br />using System.Web.Services;<br />using System.Web.Script.Services;<br /><br />[ScriptService]<br />public class ServiceWeb : System.Web.Services.WebService<br />{<br /> private static int nbr = 0;<br /><br /> [WebMethod]<br /> public string HelloWorld()<br /> {<br /> return string.Format("Hello World {0}", ++nbr);<br /> }<br /><br />}</pre>
<h3 style="text-decoration: underline;">Implémentation de la logique Javascript dans la page ASP.NET</h3>
<pre><%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" <br /> Inherits="_Default" %><br /><br /><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <br /> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><br /><html xmlns="http://www.w3.org/1999/xhtml"><br /><head runat="server"><br /> <title></title><br /> <style type="text/css"><br /> #modal_dialog<br /> {<br /> bottom: 0px;<br /> right: 0px;<br /> position: fixed;<br /> width: 250px;<br /> height: 100px;<br /> border: solid 2px black;<br /> margin: 0px 0px 0px 20px;<br /> background-color: red;<br /> }<br /> </style><br /></head><br /><body><br /> <form id="form1" runat="server"><br /> <asp:ScriptManager ID="sm1" runat="server"><br /> <Services><br /> <asp:ServiceReference Path="~/ServiceWeb.asmx" /><br /> </Services><br /> </asp:ScriptManager><br /><br /> <script language="javascript" type="text/javascript"><br /> var message;<br /><br /> var app = Sys.Application;<br /> app.add_init(applicationInitHandler);<br /><br /> function applicationInitHandler(sender, args) {<br /> StartChecking();<br /> }<br /><br /> function StartChecking() {<br /> // les Argument d'entrée dans le webservice sont à mettre en premier avant le callback<br /> ServiceWeb.HelloWorld(OnCurrentHelloWorldCallback);<br /> }<br /><br /> function OnCurrentHelloWorldCallback(result, userContext, methodName) {<br /> if (result !== message) {<br /> ShowPopup();<br /> $get("modal_dialog_content").innerHTML = result;<br /> message = result;<br /> }<br /> window.setTimeout(StartChecking, 10000);<br /> }<br /><br /> function ShowPopup() {<br /> $get("modal_dialog").style.visibility = "visible";<br /> $get("modal_dialog").style.display = "block";<br /> }<br /><br /> function HidePopup() {<br /> $get("modal_dialog").style.visibility = "hidden";<br /> $get("modal_dialog").style.display = "none";<br /> }<br /> <br /> </script><br /><br /> <div><br /> Pif paf pouf ;-)<br /> </div><br /> <div id="modal_dialog" style="visibility: hidden; display: none;"><br /> <div><br /> Mon popup !<span style="cursor: hand" onclick="javascript:HidePopup();"><br /> <img alt="Hide Popup" src="http://www.lelibre.net/index.php?post/2009/02/04/close.png" style="height: 24px; width: 24px;" /><br /> </span><br /> </div><br /> <div id="modal_dialog_content"><br /> </div><br /> </div><br /> </form><br /></body><br /></html></pre><h1><ins><strong><strong>Résultat<br /></strong></strong></ins></h1>
Voici le résultat au rendu ... :-)<br /><br /><img title="Notification Ajax, fév. 2009" alt="" src="http://www.lelibre.net/public/Ajax_Notification/.PopupNotificationMicrosoft_m.jpg" />Custom View en ASP.NET MVC Bêtaurn:md5:811a4c05828b5fabde992ee86bdf49d42008-12-14T16:50:00+01:002008-12-14T16:57:03+01:00Thierry ThouaASP.NET<p>Il est possible avec certains framework MVC du marché de créer des vues optimisées pour un browser. Prenons par exemple le cas de Ruby on Rails et du support de l'iphone (expliqué sur ce <a href="http://www.slashdotdash.net/articles/2007/12/04/iphone-on-rails-creating-an-iphone-optimised-version-of-your-rails-site-using-iui-and-rails-2" hreflang="en">post</a>). Mais qu'en est-il de cette fonctionnalité sous ASP.NET MVC ?</p> <p>Il est possible de créer un "simulacre de gestion de multi views selon le browser en interceptant l'action dans le controlleur. Ce ne sera pas aussi performant que sous RoR. En effet, si on ne précise pas de vue à appliquer, il prendra celle par défaut ... Pour gérer tous ces cas, il faudrait modifier plus en profondeur la dll System.Web.MVC ce qui n'est pas le but de ce post.</p>
<ul>
<li><strong>Structure de la solution</strong><br />
<img src="http://www.lelibre.net/public/ASP.NET_MVC_CustomView_112/MVC_Arbre.png" alt="Arbre MVC" title="Arbre MVC, déc. 2008" />
</li>
<li><strong>Implémentation du Custom controlleur</strong><br />
<pre>public abstract class ControllerCustomView : Controller<br />{<br /> protected abstract string DefaultDirectory { get; }<br /><br /> protected abstract string FirefoxDirectory { get; }<br /><br /> protected override ViewResult View(string viewName, <br /> string masterName, <br /> object model)<br /> {<br /> ViewResult result = base.View(viewName, masterName, model);<br /> if (!string.IsNullOrEmpty(viewName))<br /> result.ViewName = GetDirectory() + viewName;<br /> return result;<br /> }<br /><br /> private string GetDirectory()<br /> {<br /> string value = Request.Browser.Browser;<br /> return (value.Contains("Firefox") <br /> ? FirefoxDirectory <br /> : DefaultDirectory) <br /> + @"\";<br /><br /> }<br />}</pre></li>
<li><strong>Implémentation d'un controlleur héritant de cette classe</strong><br />
<pre>[HandleError]<br />public class HomeController : ControllerCustomView<br />{<br /> protected override string DefaultDirectory<br /> {<br /> get { return "Default"; }<br /> }<br /><br /> protected override string FirefoxDirectory<br /> {<br /> get { return "Firefox"; }<br /> }<br /><br /><br /> public ActionResult Index()<br /> {<br /> ViewData["Title"] = "Home Page";<br /> ViewData["Message"] = "Welcome to ASP.NET MVC!";<br /><br /> return View();<br /> }<br /><br /> public ActionResult Products()<br /> {<br /> var products = new List<Product>() <br /> {<br /> new Product(){ ID = 1, Name="Olive"},<br /> new Product(){ID = 2, Name="Machine"}<br /> };<br /><br /> return View("Products", products);<br /> }<br />}</pre>
</li>
<li><strong>Résultat</strong><br />
<img src="http://www.lelibre.net/public/ASP.NET_MVC_CustomView_112/MVC_Mozilla.png" alt="MVC_Mozilla.png" title="MVC_Mozilla.png, déc. 2008" />
<img src="http://www.lelibre.net/public/ASP.NET_MVC_CustomView_112/MVC_IE.png" alt="MVC_IE.png" title="MVC_IE.png, déc. 2008" />
</li>
<li><strong>Limitations</strong><br />
Il n'y a pas encore d'intégration complète de ce "multi view" en ASP.NET MVC. Mais il est possible de réaliser certains développements pour un browser particulier. Il faudrait modifier plus en profondeur le coeur du système pour supporter ce mécanisme. Avis aux amateurs ?
</li>
</ul>Custom Model binder en ASP.NET MVC Betaurn:md5:93892e2a96bfa0880ca734c0bf30a61a2008-12-07T17:52:00+01:002008-12-08T08:43:44+01:00Thierry ThouaASP.NET<p>Après plusieurs semaines sans Internet à domicile, me revoici en ligne
avec le reste du monde ;-).. J'en profite pour publier un article sur
la gestion des "Binders" en ASP.NET MVC.
</p> <ol>
<li>BINDERS ? Kezako ?</li>
Il existe un mécanisme de binding qui offre la possibilité de passer un "objet métier" à une méthode d'un controlleur. L'objet "Binder" fera cette traduction entre ce qui se trouve dans l'objet Form ASP.NET et l'objet métier. La liaison se définit dans le fichier global.asax.
<li>Exemple visuel</li>
<ul>
<li>Un formulaire basique d'insertion d'une facture<br/>
<img title="Form de base, dec 2008" alt="" src="http://www.lelibre.net/index.php?post/2008/12/07/../public/ASP.NET_MVC_Model_Binders/DefaultForm.png" />
<br /></li>
<li>On ne donne pas le montant de la facture. Il s'agit d'une erreur "bloquante"<br/>
<img title="FormIncorrect.png, dec 2008" alt="" src="http://www.lelibre.net/index.php?post/2008/12/07/../public/ASP.NET_MVC_Model_Binders/FormIncorrect.png" />
<br /></li>
<li>Le binding s'effectuera et remplira l'objet métier qui sera passé à la méthode du controlleur. De plus on affichera une erreur pour signaler que l'on a encodé une valeur erronnée<br/>
<img title="FormAvecMessageErreur.png, dec 2008" alt="" src="http://www.lelibre.net/index.php?post/2008/12/07/../public/ASP.NET_MVC_Model_Binders/.FormAvecMessageErreur_m.jpg" />
</li>
</ul>
<li>Exemple de code</li>
<ul>
<li>Implémentation du binding de la classe Invoice</li>
<pre>public class InvoiceBinder : IModelBinder<br />{<br /> #region IModelBinder Members<br /><br /> public ModelBinderResult BindModel(ModelBindingContext bindingContext)<br /> {<br /> if (bindingContext == null)<br /> throw new ArgumentNullException("bindingContext");<br /> Invoice invoice = new Invoice();<br /> NameValueCollection values = bindingContext.HttpContext.Request.Form;<br /> invoice.CustomerName = values["CustomerName"];<br /> try<br /> {<br /> string totalAmount = values["TotalAmount"];<br /> if (string.IsNullOrEmpty(totalAmount))<br /> bindingContext.ModelState.AddModelError("TotalAmount",<br /> "Ce champ est obligatoire !");<br /> else<br /> invoice.TotalAmount = Convert.ToSingle(values["TotalAmount"]);<br /> }<br /> catch (Exception ex)<br /> {<br /> bindingContext.ModelState.AddModelError("TotalAmount", ex);<br /> }<br /> return new ModelBinderResult(invoice);<br /> }<br /><br /> #endregion<br />}</pre>
<li>Déclaration du binding dans le Global.asax</li>
<pre>protected void Application_Start()<br />{<br /> ModelBinders.Binders[typeof(Invoice)] = new InvoiceBinder();<br /> ModelBinders.DefaultBinder = new DefaultModelBinder();<br /> RegisterRoutes(RouteTable.Routes);<br />}</pre>
<br />
<li>Implémentation du controlleur</li>
<pre>[HandleError]<br />public class HomeController : Controller<br />{<br /> public ActionResult Index()<br /> {<br /> return RedirectToAction("Create");<br /> }<br /><br /> [AcceptVerbs("GET")]<br /> public ActionResult Create()<br /> {<br /> return View(new Invoice());<br /> }<br /><br /> [AcceptVerbs("POST")]<br /> public ActionResult Create(Invoice invoice)<br /> {<br /> return View(invoice);<br /> }<br />}</pre>
<br />
<li>Implémentation du formulaire</li>
<pre><%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" <br /> AutoEventWireup="true" CodeBehind="Create.aspx.cs" <br /> Inherits="DemoMVC.Views.Home.Create" %><br /><br /><asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"><br /> <h2><br /> Add invoice :<br /> </h2><br /> <% Html.BeginForm("Create", "Home"); %><br /> <table><br /> <tr><br /> <td><br /> Customer Name :<br /> </td><br /> <td><br /> <%= Html.TextBox("CustomerName") %><br /> </td><br /> </tr><br /> <tr><br /> <td><br /> Total amount :<br /> </td><br /> <td><br /> <%= Html.TextBox("TotalAmount") %><br /> <%= Html.ValidationMessage("TotalAmount") %><br /> </td><br /> </tr><br /> </table><br /> <input type="submit" value="Click clack" /><br /> <% Html.EndForm(); %><br /></asp:Content></pre>
</ul>
<li>Conclusion</li>
Ce petit post se termine ici. Il ne se focalise pas trop sur les binders ... mais plutôt sur le couple ModelState + Binder. Il n'empêche ... ce mécanisme de binder offre de belles perspectives !
</ol>ASP.NET MVC Preview 4 : Support d'ajaxurn:md5:51d93aee3444ba08776f8f1c958765252008-07-17T20:47:00+02:002008-07-17T21:20:31+02:00Thierry ThouaASP.NETDepuis ce 16 juillet 2008, la nouvelle version d'ASP.NET MVC Preview 4 est disponible en test. Il y a quelques nouveautés intéressantes .... Je passerai ici les actions disponible pour l'authentification... En effet, il était possible de le réaliser simplement via l'attribut ActionFilterAttribute dont je vous ai parlé il y a quelques temps ...<br />
Les sujets de ce soir seront l'ajout d'ajax! (Il était temps ;-)) et les changements pour l'attribut ActionFilter. Voici comment il est possible simplement de mettre en place Ajax sous ASP.NET MVC Preview 4. Le but de cette manipulation est en Ajax d'insérer le texte qui sera encodé manuellement ...<br /><br /><br />
<p><img title="ASP.NET MVC Preview 4 exemple ajax, juil 2008" style="margin: 0 auto; display: block;" alt="" src="http://www.lelibre.net/public/exemple_demo.png" /></p>
<ul><li><strong> Ajout des scripts en référence dans la master page</strong></li>
</ul>
<ul>
<pre><code><head runat="server"><br /> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><br /> <title><%= Html.Encode(ViewData["Title"]) %></title><br /> <link href="http://www.lelibre.net/index.php?post/2008/07/17/../../Content/Site.css" rel="stylesheet" type="text/css" /><br /> <script src="http://www.lelibre.net/index.php?post/2008/07/17/../../Content/MicrosoftAjax.js" type="text/javascript"></script><br /> <script src="http://www.lelibre.net/index.php?post/2008/07/17/../../Content/MicrosoftMvcAjax.debug.js" type="text/javascript"></script><br /></head></code></pre>
</ul>
<ul><li><strong> Implémentation des deux actions dans le controlleur</strong></li>
</ul>
<ul>
<pre><code>using System;<br />using System.Web.Mvc;<br />namespace MvcApplication1.Controllers<br />{<br /> public class PloufController : Controller<br /> {<br /> public ActionResult Index()<br /> { return View(); }<br /><br /> public string About(string message)<br /> {<br /> return string.Format("{0} => {1}", <br /> DateTime.Now.ToShortTimeString(), message);<br /> }<br /> }<br />}</code></pre>
<li><strong>Implémentation de la page UI</strong></li>
<pre><code><%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true"<br /> CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Plouf.Index" %><br /> <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server"><br /> <p><br /> <%using (Ajax.Form("About", new AjaxOptions<br /> {<br /> InsertionMode = InsertionMode.InsertAfter,<br /> UpdateTargetId = "resultat"<br /> }))<br /> { %><br /> <%= Html.TextBox("message")%><br /> <input type="submit" value="Parle !" /><br /> <% } %><br /> </p><br /> <div id="resultat" /><br /></asp:Content></code></pre>
<li><strong>Conclusion</strong></li>
Comme vous pouvez le voir, il est très simple d'ajouter le support d'Ajax dans les pages ASP.NET. Il n'y a pas beaucoup de différence entre mes différents posts sur le couplage asp.net MVC + prototype ... Mais avec le support Ajax de base, on a la possibilité de masquer le code js via des helpers c#...</ul>
<p><ins><strong><code>
Remarque :</code></strong></ins></p>
<p>Le dernier petit point que j'aimerais aborder dans ce post est le changement d'héritage de l'attribut ActionFilterAttribute. Cette classe n'hérite plus de la classe Attribute mais bien de FilterAttribute. De même, une nouvelle interface plus parlante est apparue ... IResultFilter. Celle-ci récupère deux méthodes qui se trouvaient précédement dans IActionFilter... Ce déplacement de code me semble très judicieux. Vivement les prochaines releases d' ASP.NET MVC !!
</p>Set de propriétés de contrôles asp.net en fonction du browserurn:md5:c7faa4fc78d2ff333e25968ccc0e39a72008-07-16T22:38:00+02:002008-07-16T22:07:19+02:00Thierry ThouaASP.NET Dernièrement, j'ai découvert qu'il était possible de préfixer les propriétés de contrôles en fonction du browser. Il est possible d'afficher un texte différent dans une page ASP.NET sur un bouton en fonction du browser utilisé. Ceci ne fonctionne qu'en déclaratif dans la page aspx. La liste des browsers se trouve dans ce répertoire : C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers.<br /> Il est important de noter que tout code c# affectant ces propriétés modifiera le comportement de tous les browsers.
<br />Voici un petit exemple:
<pre>
<asp:Button ID="Button1" runat="server"
ie:Text="Button IE" mozilla:Text="Button Mozilla" />
</pre>Etendre les actions / Result sur le framework ASP.NET MVCurn:md5:642243c8bb650c20ff27382790b2b78b2008-06-29T19:00:00+02:002008-06-29T18:18:46+02:00Thierry ThouaASP.NET Il est possible d'étendre simplement les actions et données renvoyées lors d'un appel vers un controller. Pour se faire, il suffit d'implémenter le comportement que l'on souhaite ajouter et de tag la méthode avec l'attribut.<br />
<ul>
<li>Implémentation de la classe qui ajoutera le comportement</li>
<pre>public class FiltrageAttribute : ActionFilterAttribute<br />{<br /> public override void OnActionExecuting(<br /> ActionExecutingContext filterContext)<br /> {}<br /> public override void OnActionExecuted(<br /> ActionExecutedContext filterContext)<br /> {}<br /> public override void OnResultExecuted(<br /> ResultExecutedContext filterContext)<br /> {}<br /> public override void OnResultExecuting(<br /> ResultExecutingContext filterContext)<br /> {}<br />}</pre>
<li>Tag sur la méthode</li>
<pre>public class HomeController : Controller<br />{<br /> [FiltrageAttribute]<br /> public ActionResult Index()<br /> { return new View(); }<br />}</pre>
</ul>
En quelques minutes, il est possible d'ajouter un mécanisme d'authentification unifié sur une application ASP.NET MVC ou de réduire le droit d'accès sur une méthode en fonction d'un rôle utilisateur.Surcharge de thème en ASP.NET 2.0+urn:md5:2821841f113993c6f45ebdf11f48b5d62008-06-22T21:17:46+00:002008-06-22T21:20:00+00:00Thierry ThouaASP.NET Vous utilisez peut-être la propriété "Theme" sur votre page comme ceci:<br/>
<pre>
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" Theme="Lelibre" %>
</pre>
Comment surcharger certaines propriétés CSS d'un contrôle sur une page ? Il existe à ma connaissance deux approches.<br/>
<ul>
<li>Désactivation du thème sur le contrôle</li>
Le contrôle qui a sa propriété "EnableTheme" à "false" ne sera pas rendu en utilisant les skin disponibles sur le site web.
<pre>
<asp:Label runat="server" ID="label" Text="Hello world !"
EnableTheming="false" ForeColor="Red" />
</pre>
<li>Utilisation de la propriété "StylesheetTheme" en lieu et place de "Theme"</li>
L'utilisation de "StylesheetTheme" offre au développeur la possibilité de surcharger certaines propriétés du thème via code / propriétés. Si nous spécifions une couleur "Red" à la propriété "ForeColor" d'un label et que dans le skin le ForeColor du label est à "Green", le rendu affichera le label en rouge et non en vert.
<pre>
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default"
StylesheetTheme="Lelibre" %>
</pre>
J'espère avoir pu vous aider dans la notion de surcharge de CSS en asp.Net 2.0. Si vous connaissez une autre approche, merci de le signaler ;-)EventValidation (Vive le Web 2.0) ...urn:md5:0c6a311e9e723d1f9b9b86a3b9c316892008-06-02T07:58:08+00:002008-06-02T07:58:08+00:00Thierry ThouaASP.NETJe vais vous présenter un sujet intéressant.... J'ai pu discuter ce weekend avec un ex-collègue parisien qui est devenu spécialiste Web 2.0 ... Nous avons remarqué que certaines nouveautés d'asp.net 2.0 ajoutant de la sécurité pouvaient devenir des contraintes avec du développement javascript. Je vais donc vous résumer ce premier point.... D'autres points pourraient venir ;-). <br/>
Le premier point, concerne la validation des données envoyées via postback. En effet, il existe une validation des données ... Que faire si on ajoute des données via javascript ? ... Voici quelques éléments de réponse ...
<ul>
<li>Suppression de la validation sur toute la page (également possible sur tout le site dans le web.config)</li>
<pre>
<%@ Page EnableEventValidation="false" ... %>
</pre>
<li>Customisation du contrôle (ou nous intégrons la validation via l'attribut <a href="http://msdn.microsoft.com/en-us/library/system.web.ui.supportseventvalidationattribute.aspx">SupportsEventValidation</a>). Comme expliqué plus haut, il est possible d'insérer certaines lignes via javascript. C'est ce que nous faisons ici.</li>
<ol>
<li>Insertion du javascript ajoutant une ligne à la drop down</li>
<pre>
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string script2 = @"var d = document.getElementById('" + ddl2.ClientID + "'); d.options[2] = new Option('Mazda', '3');";
this.Page.ClientScript.RegisterStartupScript(typeof(_Default), "AjouteLigneViaJs2", script2, true);
}
}
</pre>
<li>Surcharge de la dropdown pour ajouter des valeurs qui seront acceptées via PostBack.</li>
<pre>
[SupportsEventValidation]
public class DynamicDropDownList : DropDownList
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
// Obligatoire dans le render !!!
this.Page.ClientScript.RegisterForEventValidation(this.UniqueID, "3");
base.Render(writer);
}
}
</pre>
<li>Code ASP.NET de l'exemple.</li>
<pre>
<form id="form1" runat="server">
<div>
<cc1:DynamicDropDownList ID="ddl2" runat="server" AutoPostBack="true">
<asp:ListItem Value="1">Audi</asp:ListItem>
<asp:ListItem Value="2">Peugeot</asp:ListItem>
</cc1:DynamicDropDownList>
</div>
</form>
</pre>
</ol>
</ul>
<br/>
J'espère avoir pu vous ouvrir quelques pistes pour éviter d'avoir des exceptions suite à votre passage dans l'ère Web 2.0 ;-)