Overblog
Suivre ce blog Administration + Créer mon blog

.net

Sérialisation d'objets de domaine Active Record dans WCF

1 Décembre 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

Active record est un pattern implémenté dans les frameworks de type Rails. Certaines produits existent pour .net et Java.
 
Un Active Record est un POCO (en .NET) dérivant d’une classe de base qui intègre les opérations de base (find, delete, create …).
 
Dans la technologie .NET, le framework el plus avancé est Castle (http://www.castleproject.org). Ce framework s’appuie sur Nhibernate pour la couche mapping OR.
 
Par défaut, WCF ne sait pas sérialiser les objets avec des références cycliques ce qui est gênant vis-à-vis du principe de réciprocité des relations du framework Castle (à 1 relation 1-n correspond une relation 1-1).
 

 

Lire la suite

Architecture n-tiers Ajax .NET

28 Novembre 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

Cet article présente une architecture n-tiers Ajax autour des technologies .NET
 
Lire la suite

Gridview et DetailView avec ASP.NET AJAX

9 Novembre 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

Le but de cet article est de construire une page AJAX contenant une gridView et une detailView du genre master/detail.

Les pré-requis sont :

L'installation de asp.net ajax fournit un ensemble d'outils supplémentaires dans la toolbox :

  • Timer : permet le rafraichissement partiel et périodique d'une page
  • ScriptManager : objet de base qui permet d'éviter le postback (à condition de positionner à true la propriété EnablePartialRendering
  • ScriptManagerProxy (gestion du scriptmanager dans des pages complexes avec des frames par exemple)
  • UpdatePanel : permet de définir une entité (un panel) pour le rafraîchissement partiel

L'installation permet également de disposer d'un template de projet et de page pour asp.net ajax.

Pour commencer :

  • construire un nouveau site Web Ajax : File-->New-->Web site et choisir Asp.Net Ajax Enabled Web Site
  • Le template génère une page par défaut (Default.aspx) blanche qui contient le code suivant :

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

 

 

<title>Untitled Page</title>

</head>

<body>

 

 

<form id="form1" runat="server">

<asp:ScriptManager ID="ScriptManager1" runat="server" />

<div>

</div>

</form>

</body>

</html>

 

 

  • La seule différence avec une page asp.net habituelle est le tag <asp:ScriptManager>
  • Donc la première chose à faire est de positionner à true la propriété EnablePartialRendering de l'objet ScriptManager1
  • Ensuite faites glisser un updatePanel sur la page
  • Faire glisser un gridview et un detailView à côté (on s'occupera de la mise en page plus tard!)
  • Dans notre exemple, une interface métier IOperations fournira les données. La méthode getComptesForClient(long idclient)
  • Pour le gridView, afficher les smarttags et choisir "Choose datasource". Créer un nouveau ObjectDatasource comptesDS (ici on choisit un type business object). Comme la méthode de l'objet métier prend un paramètre un entrée, celui-ci sera cherché dans la session (variable idclient) de l'utilisateur.
  • Pour le detailView, même principe appel de la méthode getFicheCompte(long idcompte) qui prendra son paramètre dans la sélection de la gridview
  • Il faut donc positionner les propriétés suivante de gridView1 :
    • AutogenerateColumns à true
    • AutogenerateSelectButton à true
    • Datakeynames à id (clé primaire)
    • SelectedIndex à 0
  • et voilà c'est tout : pas de code javascript à écrire ni de code c# ou vb. Pas de postback lors du changement de sélection et le detailView est rendu en partiel.

 

CODE HTML COMPLET DE LA PAGE

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

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>

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

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

 

 

<title>Consultation des comptes</title>

<link href="style.css" rel="stylesheet" type="text/css" />

</head>

<body>

 

 

<form id="form1" runat="server">

 

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true">

</asp:ScriptManager>

<div id="header" style="width: 678px; height: 65px">

<br />

<asp:Menu ID="Menu1" runat="server" BackColor="#E0E0E0" DynamicHorizontalOffset="2"

Font-Names="Arial" Font-Size="Large" ForeColor="#0000C0" Orientation="Horizontal"

StaticSubMenuIndent="10px" Width="780px">

<StaticMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />

<DynamicHoverStyle BackColor="#7C6F57" ForeColor="White" />

<DynamicMenuStyle BackColor="#F7F6F3" />

<StaticSelectedStyle BackColor="#5D7B9D" />

<DynamicSelectedStyle BackColor="#5D7B9D" />

<DynamicMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" />

<Items>

<asp:MenuItem NavigateUrl="~/Default.aspx" Text="Accueil" Value="Accueil"></asp:MenuItem>

<asp:MenuItem NavigateUrl="~/comptes.aspx" Text="Comptes" Value="Comptes"></asp:MenuItem>

<asp:MenuItem NavigateUrl="~/mouvements.aspx" Text="Mouvements" Value="Mouvements"></asp:MenuItem>

<asp:MenuItem Text="Donn&#233;es personnelles" Value="Donn&#233;es personnelles" NavigateUrl="~/client.aspx"></asp:MenuItem>

<asp:MenuItem Text="Etats" Value="Etats"></asp:MenuItem>

</Items>

<StaticHoverStyle BackColor="#7C6F57" ForeColor="White" />

</asp:Menu>

</div>

 

 

<asp:UpdatePanel ID="UpdatePanel1" runat="server">

<ContentTemplate>

<asp:ObjectDataSource ID="comptesDS" runat="server" SelectMethod="getComptesForClient"

TypeName="bankdemoBL.Operations">

<SelectParameters>

<asp:SessionParameter Name="idclient" SessionField="idclient" Type="Int64" />

</SelectParameters>

</asp:ObjectDataSource>

<div style="text-align: center">

<table>

<tr>

<td style="width: 500px; height: 210px;">

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" BackColor="White"

BorderColor="#999999" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" DataKeyNames="id"

DataSourceID="comptesDS" ForeColor="Black" GridLines="Vertical" SelectedIndex="0"

Width="347px">

<FooterStyle BackColor="#CCCCCC" />

<Columns>

<asp:CommandField ShowSelectButton="True" />

<asp:BoundField DataField="id" Visible="False" />

<asp:BoundField DataField="numcompte" />

<asp:BoundField DataField="libcompte" />

</Columns>

<SelectedRowStyle BackColor="#000099" Font-Bold="True" ForeColor="White" />

<PagerStyle BackColor="#999999" ForeColor="Black" HorizontalAlign="Center" />

<HeaderStyle BackColor="Black" Font-Bold="True" ForeColor="White" />

<AlternatingRowStyle BackColor="#CCCCCC" />

</asp:GridView>

</td>

<td style="width: 850px; height: 210px;">

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" CellPadding="4"

DataSourceID="compteDS" ForeColor="#333333" GridLines="None" Height="50px" Width="265px">

<FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />

<CommandRowStyle BackColor="#E2DED6" Font-Bold="True" />

<EditRowStyle BackColor="#999999" />

<RowStyle BackColor="#F7F6F3" ForeColor="#333333" />

<PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />

<Fields>

<asp:BoundField DataField="id" HeaderText="id" SortExpression="id" />

<asp:BoundField DataField="numcompte" HeaderText="N&#176; compte" SortExpression="numcompte" />

<asp:BoundField DataField="libcompte" HeaderText="Libell&#233;" SortExpression="libcompte" />

<asp:BoundField DataField="datecreat" DataFormatString="{0:dd/MM/yyyy}" HeaderText="Date cr&#233;ation"

HtmlEncode="False" SortExpression="datecreat" />

</Fields>

<FieldHeaderStyle BackColor="#E9ECF1" Font-Bold="True" />

<HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />

<AlternatingRowStyle BackColor="White" ForeColor="#284775" />

</asp:DetailsView>

&nbsp;<asp:ObjectDataSource ID="compteDS" runat="server" SelectMethod="getFicheCompte"

TypeName="bankdemoBL.Operations">

<SelectParameters>

<asp:ControlParameter ControlID="GridView1" Name="idcompte" PropertyName="SelectedValue"

Type="Int64" />

</SelectParameters>

</asp:ObjectDataSource>

</td>

</tr>

</table>

</div>

</ContentTemplate>

</asp:UpdatePanel>

 

</form>

 

</body>

</html>

 

 

Lire la suite

Custom membership provider minimaliste appelant une fonction métier

8 Novembre 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

  • Nous allons voir comment mettre en place une authentification pour un site WEB en utilisant les outils Microsoft et en customisant un MembershipProvider.

Par défaut, les fonctions d'authentification et de gestion des rôles peuvent être délèguer au provider par défaut (AspnetMembership provider). Celui-ci va lire les données dans une base SQL. Cette manière de faire pose des problèmes d'architecture et de sécurité car : la couche présentation accède directement à la couche DATA.

Nous allons donc construire notre propre fournisseur pour l'authentification qui respectera les règles habituelles.

Pour cela :

  • Identifier la fonction métier qui réalise l'authentification : ici ce sera l'interface IOperations via la fonction authentifie
System.Int64  op.authentifie(string username, string password);
  • Créer une classe (par exemple MonMembershipProvider qui dérive de la classe MembershipProvider)

 public class MonMembershipProvider : MembershipProvider

Il faut ensuite surcharger les nombreuses méthodes et propriétés.

  • Au minimum, il faut implémenter :
    • la propriété Name (nom du provider)

public override string Name

{

get

{

return "MonMembershipProvider";

}

}

    • la méthode ValidateUser
        • public override bool ValidateUser(string username, string password)
        • {
        • IOperations op = new Operations();
        • Int64 res = op.authentifie(username, password);
        • if (res != 0)
        • {
        • HttpContext.Current.Session.Add("idclient", res.ToString());
        • return true;
        • }
        • else
        • return false;
      • Modifier le fichier Web.config

<authentication mode="Forms">

<forms loginUrl="login.aspx" timeout="20">

</forms>

</authentication>

<authorization>

<deny users="?" />

</authorization>

<membership defaultProvider="MonMembershipProvider">

<providers>

<add name="MonMembershipProvider"

passwordFormat="Hashed"

minRequiredPasswordLength="2"

minRequiredNonalphanumericCharacters="0"

requiresQuestionAndAnswer="False"

requiresUniqueEmail="True"

type="bankdemoAJAX.MonMembershipProvider"/>

</providers>

</membership>

  • Il ne reste plus qu'à faire glisser sur la page login.aspx un contrôle "Login" et modifier la propriété membershipProvider à MonMembershipProvider.
  • Voilà c'est fini. Pour aller plus loin, il est possible de surcharger CreateUser, ChangePassword ...

Lire la suite
Lire la suite

Une DAO générique avec VS2005 et le framework CASTLE

27 Février 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

Les genrics dans .NET 2.0 permettent de factoriser le code; parfois de façon spectaculaire.

Par exemple, un DAO expose les méthodes CRUD pour accéder aux classes métier. En général,

il faut écrire une classe DAO par entité métier.

Avec les générics, c'est fini :

 

///*********************************************************************************************************

///Classe DAOGeneric

///*********************************************************************************************************

///Classe utilisant Hibernate, Castle(Active Record) pour la persistance

using System;

using System.Collections.Generic;

using System.Text;

using Appliref.domain;

using Castle.ActiveRecord;

using Castle.ActiveRecord.Queries;

using NHibernate;

namespace Appliref.Dao

{

public class daoGenerics<T,U,V>

{

 

public daoGenerics()

{

}

///

///Recherche un objet par clé

 

 

 

public T getObject(U ID)

{

return ((T)(ActiveRecordMediator.FindByPrimaryKey(typeof(T), ID)));

}

///

///Récupère la collection d'un type donné

public T[] getObjects()

{

return ((T[])(ActiveRecordMediator.FindAll(typeof(T))));

}

///

///Supprime un objet

///

public bool deleteObject(T objet)

{

 

try

 

 

 

 

 

{

ActiveRecordMediator.Delete(objet);

return true;

}

catch (Exception e)

{

return false;

}

}

///

///Vide une table

///

public bool deleteAllObjects()

{

try

 

 

 

 

 

{

ActiveRecordMediator.DeleteAll(typeof(T));

return true;

}

catch (Exception e)

{

return false;

}

}

 ///

///Mise à jour d'un objet

///

public T updateObject(T objet)

{

try

 

 

 

 

 

{

ActiveRecordMediator.Save(objet);

return objet;

}

catch(Exception e)

{

return default(T);

}

 

}

///

///Création d'un nouvel objet

///

public T newObject(T objet)

{

try

 

 

 

 

 

{

ActiveRecordMediator.Create(objet);

return objet;

}

catch (Exception e)

{

return default(T);

}

}

///

///Exécute une requête de sélection (HQL)

public V[] executeQuery(SimpleQuery q)

{

return (V[])ActiveRecordMediator.ExecuteQuery(q);

}

}

}

 

 

 

 

 

 

Lire la suite

Exemple XMLENCRYPT

30 Janvier 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

XmlEncrypt est un standard qui permet d'échanger des données chiffrées au format xml.

L'exemple ci-dessous permet de chiffrer une partie d'un fichier xml dans un programme de type console

et de déchiffrer dans un autre programme de type Winform.

Programme console de chiffrement

using System;

using System.Collections.Generic;

using System.Text;

using System.Xml;

using System.Security.Cryptography;

using System.Security.Cryptography.Xml;

namespace cryptage

{

class Program

{

static void Main(string[] args)

{

XmlDocument xmlDoc = new XmlDocument();

// Charge le fichier XML en clair dans un objet XmlDocument.

try

{

xmlDoc.PreserveWhitespace = true;

xmlDoc.Load("c:\\crypto\\test.xml");

}

catch (Exception e)

{

Console.WriteLine(e.Message);

}

// Création d'un clé RSA. Cette clé servira à chiffrer la clé symétrique qui sera embarquée,

// dans le fichier xml.

RSA rsaKey = new RSACryptoServiceProvider();

 

XmlDocument xmlKey = new XmlDocument();

xmlKey.LoadXml(rsaKey.ToXmlString(true));

xmlKey.Save("c:\\crypto\\key.xml");

 

try

{

// Chiffrement de l'élément XML.

Encrypt(xmlDoc, "creditcard", rsaKey, "rsaKey");

// Sauvegarde du fichier chiffré

xmlDoc.Save("c:\\crypto\\test2.xml"); ;

}

catch (Exception e)

{

Console.WriteLine(e.Message);

}

finally

{

// Clear the RSA key.

rsaKey.Clear();

}

}

public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, RSA Alg, string KeyName)

{

// Contrôle des arguments.

if (Doc == null)

throw new ArgumentNullException("Doc");

if (ElementToEncrypt == null)

throw new ArgumentNullException("ElementToEncrypt");

if (Alg == null)

throw new ArgumentNullException("Alg");

////////////////////////////////////////////////

// Recherche de l'élément à chiffrer

////////////////////////////////////////////////

XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;

if (elementToEncrypt == null)

{

throw new XmlException("The specified element was not found");

}

//////////////////////////////////////////////////

//Création d'une nouvelle instance EncryptedXml pour chiffrer l'XmlElement

// avec une clé symétrique aléatoire.

//////////////////////////////////////////////////

// Création d'une clé de 256 bits.

RijndaelManaged sessionKey = new RijndaelManaged();

sessionKey.KeySize = 256;

EncryptedXml eXml = new EncryptedXml();

byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);

////////////////////////////////////////////////

// Construction d'un objet EncryptedData et renseignement des informations de chiffrement

////////////////////////////////////////////////

EncryptedData edElement = new EncryptedData();

edElement.Type = EncryptedXml.XmlEncElementUrl;

// Creation d'une EncryptionMethod

edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);

//Chiffrement de la clé de session et rajout à l'élément EncryptedKey

EncryptedKey ek = new EncryptedKey();

byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false);

ek.CipherData = new CipherData(encryptedKey);

ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);

edElement.KeyInfo = new KeyInfo();

// Create a new KeyInfoName element.

KeyInfoName kin = new KeyInfoName();

// Specify a name for the key.

kin.Value = KeyName;

// Add the KeyInfoName element to the

// EncryptedKey object.

ek.KeyInfo.AddClause(kin);

// Add the encrypted key to the

// EncryptedData object.

edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));

// Add the encrypted element data to the

// EncryptedData object.

edElement.CipherData.CipherValue = encryptedElement;

////////////////////////////////////////////////////

// Replace the element from the original XmlDocument

// object with the EncryptedData element.

////////////////////////////////////////////////////

EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);

}

}

}

 

Programme Winform de déchiffrement

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Security.Cryptography;

using System.Security.Cryptography.Xml;

using System.Xml;

namespace clnCrypto

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

RSA rsaKey = new RSACryptoServiceProvider();

XmlDocument xmlkey = new XmlDocument();

xmlkey.Load("c:\\crypto\\key.xml");

rsaKey.FromXmlString(xmlkey.OuterXml);

XmlDocument xmlDoc = new XmlDocument();

 

 

// Load an XML file into the XmlDocument object.

//xmlDoc.PreserveWhitespace = true;

 

 

 

xmlDoc.Load("c:\\crypto\\test2.xml");

 

 

this.richTextBox1.Text = xmlDoc.InnerXml;

Decrypt(xmlDoc, rsaKey, "rsaKey");

this.richTextBox2.Text = xmlDoc.InnerXml;

 

}

private static void Decrypt(XmlDocument Doc, RSA Alg, string KeyName)

{

// Check the arguments.

if (Doc == null)

throw new ArgumentNullException("Doc");

if (Alg == null)

throw new ArgumentNullException("Alg");

if (KeyName == null)

throw new ArgumentNullException("KeyName");

 

// Create a new EncryptedXml object.

EncryptedXml exml = new EncryptedXml(Doc);

exml.AddKeyNameMapping(KeyName, Alg);

// Decrypt the element using the symmetric key.

try

{

exml.DecryptDocument();

}

catch (System.Security.Cryptography.CryptographicException e)

{

Console.WriteLine(e.Message);

}

 

 

 

}

}

}

Fichier xml en clair

<?xml version="1.0" encoding="utf-8" ?>

<root>

<creditcard>

<number>19834209</number>

<expiry>02/02/2002</expiry>

</creditcard>

</root>

fichier xml chiffré

<?xml version="1.0" encoding="utf-8"?>

<root>

<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"><EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /><KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#"><EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /><KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><KeyName>rsaKey</KeyName></KeyInfo><CipherData><CipherValue>PbpKLi/EBGoh6qTxUJyRPYat/u+1Rj5g+H6IxIWRXJ3E6cODsKxJbFokzg980+OBFKh6ZAagmrwxATRElX1LMgDZfatCBEW3jIaESG12N0HnPPlntmY5PViqZpny3lm7XltAISeFE7ovxShKFcxU9749uC+Zj+eONlhJUGt5DPQ=</CipherValue></CipherData></EncryptedKey></KeyInfo><CipherData><CipherValue>9fFBfVMGS50njNrt+vJtWKrgEgciG93Py+RkVnW4IWyRzvDx9VoDrEEs7kRPqN5PCAgIt2Y9TnExX6e+eWQM9JlReTAKlJ+RFY3No2oc1APElYcH2JJdpkj4V2XpOLduYOIwK108p2eGJiliO2L1bw==</CipherValue></CipherData></EncryptedData>

</root>

Lire la suite

Mapping O/R : PUZZLE

26 Janvier 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

Un framework  intéressant : Puzzle.

Puzzle comprend :

- ObjectMapper : Outil permettant de générer les POCOs et la couche de persistance avec NPersist ou

NHibernate;

- NPersist : un framework O/R mapping;

- NPath : query sur les graphes en mémoire (objets);

- NAspect : un framework AOP

- NFactory

Tout cela en Opensource et téléchargeable sur le site :

http://www.puzzleframework.com/

 

Lire la suite

Site sur WCF (Indigo)

25 Janvier 2006 , Rédigé par Hugues MEUNIER Publié dans #.NET

Microsoft vient d'ouvrir un site dédié  à WCF.

http://windowscommunication.net/

Il y a pas mal d'articles intéressants dont des exemples pour débuter.

Lire la suite
<< < 1 2 3 4 5 6 7 8