venerdì 16 settembre 2011

Vb Generic Class e Generic Method

Questa è stata un filino più ostica, ma non del tutto complessa.

Al di la del fatto che il linguaggio possa piacere o meno, sono riuscito ad ottenere la mia prima classe generica.

Public Class GenericTest(Of t)

Public Function GetProperty() As PropertyInfo()


Dim actObject = Activator.CreateInstance(Of t)()

GetProperty = actObject.GetType().GetProperties()
End Function

End Class


Devo essere onesto non è nemmeno troppo bella... ma quanto meno sono riuscito a infilarci reflection e generic in un unica botta.

Module Module1

Sub Main()


Dim ents As New Entities()

Dim ttype As New GenericTest(Of Entity)()

Dim pI As PropertyInfo() = ttype.GetProperty()

For i = 0 To pI.Length - 1
Console.WriteLine(pI(i).Name)

Next
Console.ReadLine()


End Sub

End Module


E questo è il main per verificare che cosa succede, onestamente come sintassi, continuo a sostenere che sia molto più elegante e leggibile il C# ma credo che il discorso sia sempre più una questione di abitudine.

Vb net Entity e Linq

mmm questa però non mi convince molto, ossia osservando anche nei miei stessi post relativi a C# e linq devo dire che in Vb.Net la cosa mi convince un po poco, ma probabilmente sono i primi esperimenti e quindi non ci sto trovando il vero gusto.

Tuttavia lambda c'e' ... sensa riscrivere quanto già scritto per l'entity che è solo nel post precedente ecco un banale esempio di come applicare lambda su generic.

Certo è vero che con C# è molto più flessibile la cosa ( ma torno a dire si tratta solo dei primi passi .. )

Module Module1

Sub Main()


Dim ents As New Entities()

For i = 1 To 10000
Dim ent1 As New Entity()
ent1.idEntity = i
ent1.EntityName = i.ToString.PadLeft(3, "0")
ent1.EntityDescription = "Test Number " + i.ToString

ents.Add(ent1)
Next i


Dim res1 = From entsList In ents Where entsList.idEntity < 100


End Sub

End Module

Vb net Entity e List T

Giusto perchè oggi mi sento bello carico e in vena di prove con Vb.Net ecco che mi cimento nel mio classico esempietto.

La mia Amorevole classe entity rivista in versione Vb.Net, mi rendo conto sempre più dello sforzo fatto da MS, per ottenere due linguaggi (differenti) a cui dare una certa somiglianza.

Mi pare però che le differenze ci siano e non troppo ben celate.

Public Class Entity

Private _idEntity As Integer
Private _EntityName As String
Private _EntityDescription As String

Public Property idEntity() As Integer
Get
Return _idEntity
End Get
Set(ByVal value As Integer)
_idEntity = value
End Set
End Property


Public Property EntityName() As String
Get
Return _EntityName
End Get
Set(ByVal value As String)
_EntityName = value
End Set
End Property


Public Property EntityDescription() As String
Get
Return _EntityDescription
End Get
Set(ByVal value As String)
_EntityDescription = value
End Set
End Property


End Class


Public Class Entities
Inherits List(Of Entity)

End Class


Tuttavia mi pare che a fronte di una sintassi non troppo differente il risultato
sia più o meno simile.

Tanto simili anche nell'utilizzo...

Module Module1

Sub Main()

Dim ent1 As New Entity()
Dim ent2 As New Entity()

ent1.idEntity = 1
ent1.EntityName = "C#"
ent1.EntityDescription = "il primo amore"

ent2.idEntity = 2
ent2.EntityName = "vb"
ent2.EntityDescription = "il primo linguaggio"


Dim ents As New Entities()

ents.Add(ent1)
ents.Add(ent2)


End Sub

End Module


Potrei farci l'abitudine

How To:Static Class VB.Net

In Vb.Net le classi statiche non esistono, tuttavia ci sono i moduli.
Gli affezionati alla programmazione VB ( 4,5,6 ) sapranno bene quanto i moduli possono essere a libera interpretazione, ma la somiglianza con una classe statica è molto forte.

Di seguito un breve esempio ( una delle possibilità ) su come realizzare un elemento statico in VB.Net ( non si tratta realmente di una classe ... )

Module StaticSamples

Public Function DoStaticMethod(ByVal value As String) As String

DoStaticMethod = value.ToUpper()

End Function

End Module

How To: Read Write File Vb.Net

Dato che sono sempre stato estermamente curioso mi sono deciso a fare qualche passo in un mondo abbastanza vicino al c#... vicino ma non vicinissimo.

Ecco quindi una serie di post specifici per il cugino Vb.Net

Perchè non iniziare con qualcosa di semplice ?? ecco come leggere e scrivere un
file con Vb.Net ( pseudo traduzione da C# )

Imports System.IO


Public Class IOSamples

Public Function WriteFile(ByVal FileName As String,
ByVal outputText As String) As Boolean
If FileName = "" Then
WriteFile = False
End If

If Not File.Exists(FileName) Then
Dim tw As New StreamWriter(FileName)

tw.Write(outputText)

tw.Close()

tw = Nothing

End If

WriteFile = True

End Function


Public Function ReadFile(ByVal fileName As String) As String

Dim inputText As String = ""

If fileName = "" Then
ReadFile = ""
End If


If File.Exists(fileName) Then
Dim tr As New StreamReader(fileName)

inputText = tr.ReadToEnd()
tr.Close()

tr = Nothing

End If

ReadFile = inputText
End Function
End Class

venerdì 9 settembre 2011

How To: Add Template column via Code

Ecco una cosa che generalmente si cerca di fare ma che difficilmente risulta semplice.

Ossia aggiungere una column Template via codice. Per far questo è necessario comprendere che cosa è effettivamete una template column.

Nulla di più nulla di meno che un contenitore il nocciolo di questo contenitore è l'interfaccia ITemplate che espone il metodo:

InstantiateIn che come paraemtro espone il control container.


Quest'esempietto mostra come realizzare una Colonna (con Header e Item ) contenente un immagine.

public class ImageColumnTemplate : ITemplate
{
#region Private
private DataControlRowType templateType;
private string _columnName;

private string _alternateText;


public ImageColumnTemplate(DataControlRowType type,
string columnName)
{
templateType = type;
_columnName = columnName;
_alternateText = " ";
}

public ImageColumnTemplate(DataControlRowType type,
string columnName, string altrenate)
{
templateType = type;
_columnName = columnName;
_alternateText = altrenate;
}


public void InstantiateIn(System.Web.UI.Control container)
{

switch (templateType)
{
case DataControlRowType.Header:
Literal lc = new Literal();
lc.Text = "<a href=\"#\">" + _columnName + "</a>";

container.Controls.Add(lc);
break;

case DataControlRowType.DataRow:

Image im = new Image();

im.DataBinding += new EventHandler(im_DataBinding);
container.Controls.Add(im);

im.AlternateText = _alternateText;
break;

default:

break;
}
}


public void im_DataBinding(object sender, EventArgs e)
{
Image l = (Image)sender;

GridViewRow row = (GridViewRow)l.NamingContainer;

if (DataBinder.Eval(
row.DataItem, _columnName).ToString().ToLower() == "true")
{
l.ImageUrl = "/Styles/commons/green.png";
}
else
{
l.ImageUrl = "/Styles/commons/red.png";
}
}
}


E questo è come aggiungere la colonna all grid view

TemplateField tcf = new TemplateField();

tcf.ItemTemplate = new ImageColumnTemplate(
DataControlRowType.DataRow,
NomeCampoBinding);

tcf.HeaderTemplate = new ImageColumnTemplate(
DataControlRowType.Header, "Stato");

gvwDataGrid.Columns.Add(tcf);

giovedì 8 settembre 2011

How To: Membership Set Approved

Membership per default crea l'utente come "Approvato", questa logica tecnicamente è corretta,
ma potrebbe non ricalcare tutti i casi.

Nel mio per esempio l'utente deve essere creato e approvato successivamente. A tal proposito
Membership mette a disposizione una proprietà ( R/W ) IsApproved di tipo boolean.

Questa agisce sull'utente ma non salva su db, per poterlo fare è necessario aggiornare
l'utente stesso.

MembershipUser mb = Membership.CreateUser("Fabio", "Arosio");                                

mb.IsApproved = false;

Membership.UpdateUser(mb);

mercoledì 7 settembre 2011

How To: Membership Get Password

Ecco un'altra bella prova complicata... come ottenere la passwrod di un utente ?
Lo scopo per cui voler far ciò devo essere onesto lo lascio a voi.

Banalmente si ottiene l'utente, e di contro si sfrutta il metodo GetPassword

MembershipUser mb = Membership.GetUser(MembershipUserKey);
string Password = mb.GetPassword();


Tuttavia questo potrebbe portare a due tipi di eccezione:

"This Membership Provider has not been configured to support password retrieval"

il che implica l'assenza di un paio di voci nel web.config proprio nel vostro
provider.

Provate a verificare gli attributi:
-enablePasswordRetrieval
-requiresQuestionAndAnswer
-passwordFormat

<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider"
connectionStringName="..."
minRequiredPasswordLength="4"
minRequiredNonalphanumericCharacters="0"
type="System.Web.Security.SqlMembershipProvider"
applicationName="/"
enablePasswordRetrieval="true"
requiresQuestionAndAnswer="false"
passwordFormat="Encrypted"
requiresUniqueEmail="false" />
</providers>
</membership>


Se questo basta avete risolto... tuttavia sono quasi sicuro che si verificherà
una seconda eccezione:

"Hashed passwords cannot be decoded"

Il che implica due cose
a) non avete impostato la Machine Key Trovate il generatore qui!

Questa chiave dovrete metterla nel web.config sotto system.web

Se tutto funziona avete risolto... anche se sono convinto che si verificherà ancora...

Questo processo funziona con le password che sono state create dopo l'attuazione del processo stesso.

Ossia, in questo modo state indicando a Membership una modalità di generazione della
password ( è ovvio ) che tutto ciò che è avvenuto prima non sia conforme a questo processo, ( perchè chiaramente non era impostato ).

How To: Login Panel Custom Message

L'argomento è ancora Membership (decisamente attuale per il mio blog). Una delle problematiche
più comuni per il controllo di Login proposto da M.S. e di generare e gestire altri messaggi
in caso di Fallita Login.

A tal propostio può essere utilie ricordare quali sono gli eventi che concorrono per la login
protected void LoginPanel_LoggedIn(object sender, EventArgs e)
{
// generata a Login Effettuata
// comdoda da usare se serve salvare
// qualche informazione in sessione
}

protected void LoginPanel_LoggingIn(object sender,
LoginCancelEventArgs e)
{
//
// generata durante la login
//
if ( condizione1 == false)
{
LoginPanel_LoginError("1", new EventArgs());
e.Cancel = true;
return;
}
if ( condizione2 == false)
{
LoginPanel_LoginError("2", new EventArgs());
e.Cancel = true;
return;
}
if ( condizione3 == false)
{
LoginPanel_LoginError("3", new EventArgs());
e.Cancel = true;
return;
}
}

protected void LoginPanel_LoginError(object sender, EventArgs e)
{
//
// da invocare in caso di errore
// o invocata in caso di errore...
//
if (sender.ToString() == "1")
{
CustomValidator vldLoginFailed =
(CustomValidator)LoginUser.FindControl("cstErrore1");
vldLoginFailed.IsValid = false;
}
// per tutti e tre i casi
}


Questo è quanto necessario riportare nel tag LayoutTemplate

<asp:CustomValidator id="cstErrore1" 
runat="server" ErrorMessage="messaggio 1"
ValidationGroup="LoginUserValidationGroup"
Visible="false" />

<asp:CustomValidator id="cstErrore2"
runat="server" ErrorMessage="messaggio 2"
ValidationGroup="LoginUserValidationGroup"
Visible="false" />

<asp:CustomValidator id="cstErrore3"
runat="server" ErrorMessage="messaggio 3"
ValidationGroup="LoginUserValidationGroup"
Visible="false" />

<asp:ValidationSummary
ID="LoginUserValidationSummary" runat="server"
ValidationGroup="LoginUserValidationGroup"
HeaderText="Login Fallita:"/>


E questa è la dichiarazione del nostro pannello di login

<asp:Login ID="LoginPanel" runat="server" 
EnableViewState="True"
RenderOuterTable="True"
OnLoggedIn="LoginPanel_LoggedIn"
OnLoggingIn="LoginPanel_LoggingIn"
OnLoginError="LoginPanel_LoginError">



Questa non troppo complessa struttura ci consente di effettuare delle verifiche prima che la login sia realmente avvenuta e di comunicare all'utente che cosa ha sbagliato o perchè non può loggarsi

martedì 6 settembre 2011

How To: Membership Get UserID

Dopo qualche breve tentativo, grazie anche all'aiuto del debugger, ecco come ho risolto l'annoso problema di "ottenere" l'id dell'utente appena creato con membership.

D'intuito ho cercato il campo UserId come da tabella Users, ma nell'oggetto MembershipUser il campo non c'e'... o meglio non ha lo stesso nome.

MembershipUser mb =  Membership.CreateUser(txtUserName.Text, txtPassword.Text);
string userKey = mb.ProviderUserKey.ToString();


Il campo appunto è providerUserKey che per complicare le cose è di tipo "object".