in

DotNetSide

Dot Net South Italy Developers User Group

Tips

Asp.Net

  • HttpHandler per un'immagine casuale

    Autore: Luca Barbi

    Gli HTTP Handler sono dei meccanismi di ASP.NET che si occupano di elaborare le risposte a specifiche richieste HTTP e fornirle, secondo la forma più consona, al richiedente.

    Questo Generic Handler restituisce un'immagine a caso tra quelle presenti in una directory di un sito web.

    Si tratta di un file con estensione .ashx che non ha bisogno di essere compilato, né di essere registrato nel file web.config. Basterà solamente far riferimento ad esso come URL di un'immagine, indipendentemente da dove questo sia utilizzato.

    Ad esempio, supponendo di chiamare il nostro file ImmagineCasuale.ashx e di metterlo nella root del sito web www.miosito.it, potremmo utilizzarlo per visualizzare un'immagine casuale In diversi modi.

    • Attraverso un tag HTML in una pagina web
    	<img src="/ImmagineCasuale.ashx" alt="immagine casuale"/> 
    • In un foglio di stile
    	div.intestazione { 
    background-image: url (/ImmagineOraria.ashx);
    }
    • In un controllo server web ASP.NET
    	<asp:Image ID="ImmagineCasuale" runat="server" ImageUrl="~/ImmagineCasuale.ashx" 
    AlternateText="Immagine Casuale" />

    E' possibile, inoltre, chiedere l'immagine casuale da un altro sito, sarà sufficiente indicare l'URL completo: http://www.miosito.it/ImmagineCasuale.ashx

    Ecco il codice:

    <%@ WebHandler Language="VB" Class="ImmagineCasuale" %>

    Imports System
    Imports System.Web

    Public Class ImmagineCasuale : Implements IHttpHandler

    ' qui indico la directory in cui ci sono le immagini
    Const DIRIMMAGINI = "immagini/fotocasuali"

    ' implementazione del metodo
    Public Sub ProcessRequest(ByVal context As HttpContext) _
    Implements IHttpHandler.ProcessRequest
    ' metto i nomi dei file .jpg in un array
    ' (potrei farlo anche per altre estensioni)
    Dim nomiFileImmagine() As String = _
    System.IO.Directory.GetFiles(context.Server.MapPath(DIRIMMAGINI), "*.jpg")
    ' se ci sono immagini ne estraggo una a caso e la invio come HttpResponse
    If nomiFileImmagine.Length > 0 Then
    Dim n As Integer
    Dim vMax As Integer
    vMax = nomiFileImmagine.GetUpperBound(0)
    Randomize()
    n = CInt(Int((vMax + 1) * Rnd()))

    Dim response As Web.HttpResponse = context.Response
    response.ContentType = "image/jpeg"
    response.Cache.SetCacheability(HttpCacheability.Public)
    response.BufferOutput = False
    response.WriteFile(nomiFileImmagine(n))
    response.End()
    End If
    End Sub
    ' poiché si tratta di sola lettura imposto IsReusable a True
    Public ReadOnly Property IsReusable() As Boolean _
    Implements IHttpHandler.IsReusable
    Get
    Return True
    End Get
    End Property
    End Class

    Un esempio di possibile utilizzo potrebbe essere un banner pubblicitario di una pagina web, in cui ad ogni richiesta lo sponsor varia casualmente.

    Possibili varianti: cambiare la directory o scegliere l'immagine a seconda dei parametri passati attraverso una QueryString, oppure scegliere l'immagine a seconda dell'ora.

    In quest'ultimo caso il codice potrebbe essere:

    <%@ WebHandler Language="VB" Class="ImmagineOraria" %> 
    Imports System
    Imports System.Web

    Public Class ImmagineOraria : Implements IHttpHandler

    Const DIRIMMAGINI = "immagini/orarie"

    Public Sub ProcessRequest(ByVal context As HttpContext) _
    Implements IHttpHandler.ProcessRequest

    Dim nomiFileImmagine() As String = _
    {"mattino", "giorno", "pomeriggio", "sera", "notte"}
    Dim n, ora As Integer
    ora = DateTime.Now.Hour
    Select Case ora
    Case 22 To 24, 0 To 6
    n = 4
    Case 7 To 9
    n = 0
    Case 17 To 19
    n = 2
    Case 20 To 21
    n = 3
    Case Else
    n = 1
    End Select

    Dim response As Web.HttpResponse = context.Response
    response.ContentType = "image/jpeg"
    response.Cache.SetCacheability(HttpCacheability.Public)
    response.BufferOutput = False
    response.WriteFile(context.Server.MapPath(DIRIMMAGINI & _
    nomiFileImmagine(n) & ".jpg"))
    response.End()
    End Sub

    Public ReadOnly Property IsReusable() As Boolean _
    Implements IHttpHandler.IsReusable
    Get
    Return True
    End Get
    End Property
    End Class

    In allegato una solution per VS 2005 con entrambi questi handler e due pagine html per provarli.

  • DataObjectAttribute e ObjectDataSource

    Autore: Mario Ferrante

    L’attributo DataObject rende più facile la ricerca delle classi che si vogliono legare ad un controllo DataBound durante la configurazione dell’ObjectDataSource.
    Quando si utilizza l’ObjectDataSource, la prima cosa che devo fare è scegliere l’oggetto Business da utilizzare per recuperare o gestire i dati e per legarli ad un controllo DataBound:

    Purtroppo se chiedo al wizard dell’ObjectDataSource di mostrarmi solo i “Data Components” (come in figura), la maggior parte delle volte il risultato che ottengo è un menù a discesa vuoto.
    Dunque non rimane che levare la spunta a “Show only data components” e cercare l’oggetto Business che mi interessa tra tutti quelli a cui è referenziata la mia applicazione, come si vede nella figura successiva.

     

    Poco male nel caso di piccole applicazioni, ma nel caso di applicazioni molto grandi o che comunque referenziano molti assemblies il problema diventa un po’ più serio.
    Ed è qui che viene in aiuto l’attributo DataObjectAttribute o semplicemente DataObject. Questo attributo può essere usato a livello di classe, ma anche a livello dei singoli metodi.

    L’Attributo DataObject a livello di classe
    Supponiamo che nella mia applicazione ho una classe che mi gestisce il CRUD (Create Retrieve Update e Delete) di News a cui aggiungo, a livello di classe, l’attributo DataObject:

     

     

    Imports System.ComponentModel Namespace Mario.DotNetSide <DataObject()> _ Public Class NewsManager 'Implementazione della Classe End Class End Namespace

     

    Il risultato sarà:

    Il costruttore dell’attributo DataObject accetta anche un parametro di tipo System.Boolean, se False dichiaro esplicitamente all’Object Data Source di non considerare quella classe come Data Component.
    L’Attributo DataObject a livello di metodo

    Abbiamo usato questo attributo a livello di Classe, ma lo posso utilizzare anche a livello di metodi per definire quali di essi devono essere utilizzati per selezionare i dati, quali per inserire un record, cancellarlo o modificarlo:

     

    <DataObject()> _ Public Class NewsManager <DataObjectMethod(DataObjectMethodType.Select, True)> _ Public Function GetNews() As NewsCollection End Function <DataObjectMethod(DataObjectMethodType.Insert, True)> _ Public Function AddNews(ByVal item As News) As Integer End Function End Class

    I valori dell’enumerazione DataObjectMethodType sono autoesplicativi:

    • Delete
    • Fill
    • Insert
    • Select
    • Update

    Il secondo parametro booleano passato all’attributo (True in questo caso) indica all Object Data Source se considerare (True) o meno (False) quel metodo per una determinata funzione (ad esempio di Select).
    In .Net gli attributi hanno una fondamentale importanza, essi contribuiscono a fornire tutte quelle informazioni che costituiscono i MetaData di un’assembly. Inoltre possono influenzare il comportamento di un oggetto sia a run-time sia (come in questo caso) a design-time.

  • Membership APIs - L'enumerazione MembershipCreateStatus

    Autore: Mario Ferrante

    Quando si crea un nuovo utente utilizzando le Membership APIs (Membership e MembershipUser), può capitare che si vogliano catturare le eventuali eccezioni che questo processo può generare per fornire all’utente un messaggio più user friendly e dare più dettagli circa l’errore (ad esempio:”username già utilizzato da un altro utente”, “password invalida perché deve contenere almeno due caratteri non alfanumerici”, etc.).
    Per fare questo possiamo utilizzare l’enumerazione MembershipCreateStatus.

    Per poterla utilizzare devo prima creare una variabile di tipo MembershipCreateStatus, quindi passare per riferimento tale variabile al metodo CreateUser della classe Membership.

    In questo modo la variabile può assumere diversi valori, da Success (utente creato con successo) a DuplicateUserName, InvalidPassword e così via.

    Ecco un esempio di codice:

     

    Dim status As MembershipCreateStatus 'la nostra variabile MembershipCreateStatus
    Dim myuser As MembershipUser = _
    Membership.CreateUser(username, _
    password, email, question, answer, isActive, status)
    'la variabile status viene passata Per Riferimento
    If status = MembershipCreateStatus.Success Then
    'la registrazione del nuovo utente è avvenuta con successo
    Else
    Select Case status
    Case MembershipCreateStatus.InvalidPassword
    Response.Write(
    "La Password utilizzata non è nel formato corretto, assicurarsi che sia di almeno 6 caratteri e contenga un carattere non alfanumerico")
    Case MembershipCreateStatus.DuplicateUserName
    Response.Write(
    "L'Username usata esiste già, cambiarla e continuare con la registrazione")
    Case MembershipCreateStatus.DuplicateEmail
    Response.Write(
    "L'Email usata esiste già, cambiarla e continuare con la registrazione")
    Case 'qui possiamo sfruttare altri valori dell’enumerazione
    End Select
    End If

    Per maggiori dettagli si può dare uno sguardo al seguente link:
    http://msdn2.microsoft.com/en-us/library/system.web.security.membershipcreatestatus.aspx

    Posted Nov 29 2006, 09:56 AM by VitoA with 2 comment(s)
    Filed under:
  • Convertire HTML in Testo

    Autore: Stefano De Mattia

    Quella che segue è una funzione che converte una stringa HTML in una di testo semplice.

    Sono necessari i seguenti Imports:

    Imports System.Text
    Imports System.Text.RegularExpressions

    Il codice della funzione:

    ''' <summary>
    '
    '' Funzione che converte una stringa HTML in una di testo semplice
    '
    '' </summary>
    '
    '' <param name="html">Stringa da convertire</param>
    '
    '' <returns>Stinga semplice</returns>
    '
    '' <remarks></remarks>
    Function Html2Text(ByVal html As String) As String
    ' pattern per la rimozione dei tag HTML
    Dim pattern As String = "\<[^\>]*\>"
    Dim re As New Regex(pattern, RegexOptions.IgnoreCase)

    'qui posso modificare la formattazione sui
    'tag che mi interessano, prima di eliminarli ad esempio
    'html = html.Replace("<p>", vbCrLf)
    'html = html.Replace("<\p>", vbCrLf & vbCrLf)
    'html = html.Replace("&nbsp;", " ")
    html = html.Replace("<br />", vbCrLf)

    'applico l'espressione regolare,
    'sostituendo i caratteri speciali con la stringa vuota
    html = re.Replace(html, String.Empty)

    Return html

    End Function
    Posted Oct 31 2006, 11:53 AM by VitoA with 2 comment(s)
    Filed under: ,
  • Controlli dinamici in ASP.NET 2

    Autore: Vito Arconzo

    Sia con Windows Forms 2 che con ASP.NET 2 è possibile creare controlli dinamicamente.

    In Windows Forms il seguente codice da utilizzare è :

     

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim btn As New Button
    btn.Text
    = "Click"
    Me.Controls.Add(btn)
    End Sub

    Il risultato:

    Se proviamo ad utilizzare lo stesso codice in una pagina ASP.NET, invece, il risultato sarà:

    Un bell'errore di compilazione!!!!!!!!!!

    Per risolvere il problema, attualmente, è necessario includere il controllo all'interno di un contenitore come Panel o Tabella.

    Il codice corretto sarà, quindi:

     

    Dim btn As New Button
    btn.Text
    = "Click"
    ‘ aggiunge il controllo al panel
    Me.Panel1.Controls.Add(btn)
    End Sub

    In questo modo il controllo sarà aggiunto correttamente alla pagina :-)

    Posted Sep 18 2006, 01:02 AM by VitoA with no comments
    Filed under:
  • Caricare dinamicamente uno User Control

    Autore: Mario Ferrante

    Normalmente quando in una pagina aspx sono presenti User Controls, essi devono essere “registrati” nella direttiva @Register della pagina che lo contiene:

    <%@ Register Src="[path dello User Control]" TagName="myUC" TagPrefix="uc1" %>

    Quindi possono essere richiamati in qualsiasi parte del corpo della pagina attraverso una sintassi di questo tipo:

    <uc1:myUC ID="myUC1" runat="server" />

    L’IDE di Visual Studio esegue tutto questo lavoro automaticamente, basta trascinare lo User Control appena costruito dalla finestra Solution Explorer all’interno della pagina per vedere comparire la direttiva Register e tutto il resto.

    Tuttavia possono capitare situazioni in cui abbiamo la necessità di caricare degli User Control dinamicamente in base ad alcuni eventi, tipo il cambio di valore della Querystring.
    Ad esempio, supponiamo di avere tre User Control per gestire l’aggiunta, la visualizzazione e la modifica di clienti in un’applicazione di Commercio Elettronico.
    Mettiamo caso che nella pagina customers.aspx, in base al valore della chiave action della querystring, dobbiamo caricare l’User Control appropriato.
    La pagina
    customers.aspx conterrà sempilecemente un controllo Panel:

    1    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="customers.aspx.cs" Inherits="customers" %>
    2
    3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    4
    5 <html xmlns="http://www.w3.org/1999/xhtml" >
    6 <head runat="server">
    7 <title>Untitled Page</title>
    8 </head>
    9 <body>
    10 <form id="form1" runat="server">
    11 <div>
    12 <asp:Panel ID="Panel1" runat="server" Width="80%">
    13 </asp:Panel>
    14 </div>
    15 </form>
    16 </body>
    17 </html>

    Nel Code Behind associato alla pagina, customers.aspx.cs avremo:

    1    protected void Page_Load(object sender, EventArgs e)
    2 {
    3 System.Web.UI.Control myUserControl;
    4 string action = Request.QueryString["action"];
    5 switch (action) {
    6 case "add":
    7 myUserControl = LoadControl("../Controls/addCustomer.ascx");
    8 break;
    9 case "update":
    10 myUserControl = LoadControl("../Controls/updateCustomer.ascx");
    11 break;
    12 case "view":
    13 myUserControl = LoadControl("../Controls/viewCustomers.ascx");
    14 break;
    15 default:
    16 myUserControl = LoadControl("../Controls/homeCustomers.ascx");
    17 break;
    18 }
    19 this.Panel1.Controls.Add(myUserControl);
    20 }

    Nell’esempio, il caricamento dinamico dello UC viene inserito nell’evento Load della pagina in base al valore assunto da una querystring, ma è possibile eseguire questa azione all’interno di altri eventi quali il Click di una Button e così via.

    Da notare che nella pagina aspx non vi è traccia alcuna della direttiva @Register.

     
    Posted Jul 14 2006, 09:42 AM by VitoA with no comments
    Filed under:
  • Interfaccia Inserimento e ReadOnly

    Autore: Francesco Guadagno

    Molto spesso mi son trovato difronte al semplice “problema” di dover gestire una interfaccia o form di inserimento, nella doppia modalità Inserimento e sola visualizzazione.

    Il problema, se pur semplice, ci costringe a iterare sulle varie proprietà “ReadOnly” ed “Enabled” dei vari controlli impostando il valore che ci serve in quel momento.

    Se sfruttiamo la ControlCollection di un qualsiasi WebControl, è possibile fare qualcosa di questo tipo:

    1    public static void EnableFields(Control c, bool bEnabled){
    2        foreach (Control c1 in c.Controls){
    3            string sType = c1.ToString();
    4            switch (c1.ToString()){
    5                   case "System.Web.UI.WebControls.TextBox":
    6                        ((TextBox)c1).Enabled = bEnabled;
    7                        break;
    8                   case "System.Web.UI.WebControls.DropDownList":
    9                        ((DropDownList)c1).Enabled = bEnabled;
    10                       break;
    11                  case "System.Web.UI.WebControls.CheckBox":
    12                       ((CheckBox)c1).Enabled = bEnabled;
    13                       break;
    14                  case "System.Web.UI.WebControls.ListBox":
    15                       ((ListBox)c1).Enabled = bEnabled;
    16                       break;
    17             }
    18             if (c1.HasControls()){
    19                  EnableFields(c1, bEnabled);
    20             }
    21       }
    22   }
    

    Si tratta di una funzione ricorsiva che accetta in input un qualsiasi controllo, ad esempio la tabella che contiene tutti i webcontrols, e che ripete la procedura per ogni controllo trovato nella ControlCollection.

    Le operazioni effettuabili sono le più disparate. Possiamo in questo modo pensare di gestire anche problematiche come visibilità, abilitazioni di Validator,Reset form, ecc.

    Posted Jun 08 2006, 01:03 PM by VitoA with no comments
    Filed under:
Powered by Community Server (Commercial Edition), by Telligent Systems