venerdì 31 luglio 2009

Rilasciata ASP.NET MVC V2 Preview 1

Rilasciata la preview 1 di ASP.NET MVC V2.

se siete interessati a maggiori informazioni potete andare sul post originale di Scott Guthrie image:

ASP.NET MVC V2 Preview 1 Released - ScottGu's Blog

Technorati Tag:

giovedì 30 luglio 2009

VB.NET : GridView con paginazione selezionata dall'utente

Sul sito della community romana del mondo .NET (www.dotnetromacesta.org) trovate un mio piccolo articolo su come realizzare un controllo ASP.NET, derivato dal controllo GridView, che permette all’utente di selezionare il numero di record da visualizzare.

Per semplicità riporto l’intero articolo rimandandovi al link di cui sopra per scaricare il file con il codice.

La nostra GridView modificherà il pager della GridView originale suddividendolo in due colonne, la prima delle quali conterrà il controllo di paginazione originale (normalmente contenuto in una cella con l’attributo ColumnSpan pari al numero di colonne della griglia), mentre la seconda conterrà una label e una drop down list con i possibili valori della paginazione (recuperati da una nuova proprietà che l’utente può impostare da codice).

Creiamo, dunque una classe che chiameremo DynamicPageSizeGridView e che deriverà dalla GridView contenuta nel namespace System.Web.UI.WebControls.

Definiamo tre proprietà pubbliche:

PageSizeList : elenco dei possibili valori selezionabili dall’utente. Si tratta di una stringa composta da valori numerici separati dal carattere “;” ;

PageSelectorText : testo che comparirà al fianco del controllo di selezione del numero di record;

PageSelectorCssClass : classe di stile della cella contenente la label e la dropdown di selezione.

Tutte e tre le proprietà sfruttano il viewstate per memorizzare i valori in modo da mantenerli tra un post back ed il successivo:

Public Property PageSelectorText() As String
   Get
        Dim _PageSelectorText = Me.ViewState("PageSelectorText")
        Return CStr(_PageSelectorText)
    End Get
    Set(ByVal value As String)
        Me.ViewState("PageSelectorText") = value
    End Set
End Property

Per creare fisicamente i controlli di gestione della paginazione, andiamo a gestire l’evento RowCreated ed in particolare ci occupiamo di agire sulla riga di tipo Pager:

Private Sub DynamicPageSizeGridView_RowCreated( _

        ByVal sender As Object, _
        ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
        Handles Me.RowCreated
    If e.Row.RowType = DataControlRowType.Pager Then
        Dim pagerControl = e.Row.Cells(0).Controls(0)
        e.Row.Cells(0).Controls.Clear()
        e.Row.Cells(0).Controls.Add(CreatePagerTable(pagerControl))
    End If
End Sub

In particolare andiamo a salvarci il controllo PagerTable che contiene il controllo di paginazione originale (che si trova nell’unica cella della riga di paginazione) e creiamo una tabella con una riga e due colonne. Nella prima di queste colonne (entrambe che occupano il 50% dello spazio) rimettiamo il paginatore originale, mentre nella seconda costruiamo i due controlli per la selezione del numero di record per pagina.

Function CreatePagerTable(ByVal pagerControl As Control) As Table
    Dim table = New Table()
    Dim row As New TableRow
    Dim pagerCell As New TableCell
    With pagerCell
        .Width = Unit.Percentage(50)
        .Controls.Add(pagerControl)
    End With
    row.Cells.Add(pagerCell)
    Dim sizeCell As New TableCell
    With sizeCell
        .CssClass = Me.PageSelectorCssClass
        .Width = Unit.Percentage(50)
        Dim label = New Label()
        label.Text = Me.PageSelectorText
        .Controls.Add(label)
        .Controls.Add(CreatePageSizeListDropDown())
    End With
    row.Cells.Add(sizeCell)
    table.Rows.Add(row)
    table.Width = Unit.Percentage(100)
    Return table
End Function

Nella funzione CreatePageSizeListDropDown creiamo la dropdown per la selezione della dimensione di paginazione:

Private Function CreatePageSizeListDropDown() As DropDownList
    Dim combo = New DropDownList()
    combo.Items.AddRange((From s In Me.PageSizeList.Split(CChar(";")) _
                      Where IsNumeric(s) _
                      Order By s Ascending _
                      Distinct Select New ListItem(s, s)).ToArray())
    combo.AutoPostBack = True
    combo.SelectedValue = Me.PageSize.ToString()
    AddHandler combo.SelectedIndexChanged, _
    AddressOf Me.ComboPageSizeSelectionChanged
    Return combo
End Function

Da notare l’utilizzo di LINQ per creare la lista dei valori possibili di paginazione contenuti nella proprietà PageSizeList.

Nell’evento di cambio dell’indice della dropdown effettuiamo il cambio di paginazione:

Protected Sub ComboPageSizeSelectionChanged( _
        ByVal sender As Object, _
        ByVal e As EventArgs)
    Dim combo = CType(sender, DropDownList)
    Dim selectedValue = combo.SelectedItem.Value
    Me.PageSize = System.Convert.ToInt32(selectedValue)
    Me.PageIndex = 0
End Sub

Recuperiamo il valore selezionato dall’utente, impostiamo il valore del PageSize e riportiamo il PageIndex a zero. Quest’ultima istruzione serve a garantire che, se ci si trova in una pagina diversa dalla prima e si seleziona una paginazione per cui esiste una sola pagina, non si abbia un errore.

A questo punto tutto sembra funzionare ma se selezioniamo una paginazione con un numero di record maggiore del numero di record totali della sorgente dati, scompare la riga di paginazione non consentendo più di cambiare il valore selezionato.

Per risolvere questo problema ci viene in aiuto un post di Ryan McDonnell(link) in cui si spiega come fare in modo di visualizzare sempre la riga di paginazione anche se il numero di record totali è minore del numero di record della pagina.

In sostanza è sufficiente implementare l’override della proprietà PageCount (utilizzata dal frame work per sapere quante pagine servono per visualizzare tutti i dati):

Public Overrides ReadOnly Property PageCount() As Integer
    Get
        Dim basePageCount = MyBase.PageCount
        If basePageCount = 1 Then
            Dim sf = New System.Diagnostics.StackFrame(1)
            If sf.GetMethod().Name = "CreateChildControls" _
                And sf.GetMethod().ReflectedType.Name = "GridView" Then
                    basePageCount += 1
            End If
        End If
        Return basePageCount
    End Get
End Property

Nel momento in cui ci si accorge che il numero di pagine necessarie per visualizzare i dati è pari ad 1 (cioè non viene visualizzata la riga di paginazione), si incrementa tale valore in modo da “ingannare” il framework e fargli , comunque, disegnare la riga di paginazione (priva del paginatore perché, effettivamente, non ci sono record su cui navigare).

In questo modo la nostra griglia è perfettamente funzionante.

Da notare che il tutto funziona sia con la paginazione lato server che con quella lato client.

Il codice sorgente è disponibile al seguente indirizzo

http://www.dotnetromacesta.org/common/articoli/aspnet/gridview/AspNet_GridView_Paginazione.aspx

lunedì 27 luglio 2009

VB.NET : Un metodo di estensione per recuperare, tramite LINQ, un record casuale da una collezione.

Vi segnalo su DotNetRomaCestà un mio tip riguardante LINQ ed esattamente la possibilità di recuperare casualmente un record all’interno di una collezione di elementi.

Riporto interamente il tip per semplicità ma potete trovarlo anche al link.

Questo piccolo trucco può sembrare inutile (e forse lo è), ma può avere utilità quando si ha la necessità di visualizzare, casualmente, un elemento preso da una collezione (ad esempio vetrine, banner pubblicitari, etc., etc.).

Si tratta di un metodo di estensione che si applica ad un’istanza di IQueryable(Of T) e restituisce un oggetto di classe T recuperato a caso (utilizzando il generatore di numeri casuale fornito dalla classe Random del Framework):

<Extension()> _
Public Function GetRandom(Of T) _
    (ByVal coll As IQueryable(Of T)) As T
  Dim retval As T
  Dim rnd As New Random(DateTime.Now.Millisecond)
  retval = coll.Skip(Convert.ToInt32(rnd.NextDouble* _
    (coll.Count - 1))).Take(1).FirstOrDefault
  Return retval
End Function

Il metodo, purtroppo, esegue due query sulla collezione (una per il count e l’altra per il recupero del record) e questo, comporta, in caso di collezioni provenienti da database (ad esempio LINQ to SQL), ad un doppio accesso alla banca dati.

venerdì 17 luglio 2009

Microsoft Popfly chiude i battenti

Dopo due anni di servizio, la Microsoft ha deciso di chiudere Popfly.

Questo è l’avviso che compare sulla home del sito:

Thanks for stopping by. Unfortunately, on August 24th, 2009, the Popfly service will be discontinued, all resources will be taken down, and access to your Popfly account, including games and mashups, will cease. Please see this blog post for more details.

venerdì 10 luglio 2009

Venezia, città antica ma al contempo moderna : TagMyLagoon

 

Riprendo un post di Davide Vernole (link) per segnalare l’interessantissima iniziativa del comune di Venezia:

TagMyLagoon | Cittadinanza Digitale

Questa estate, forse, farò un salto a Venezia e, visto che avevo intenzione di acquistare uno smartphone, forse sarà il caso che mi sbrighi :-)

martedì 7 luglio 2009

Mobility Developer Day 2009

Eccoci qui: anche il Mobility Developer Day 2009 è terminato e, stavolta è stata proprio dura!!

Milano si è svegliata sotto il nubifragio (vero diluvio universale!!) che ha messo a dura prova l’evento visto che la stessa organizzatrice è arrivata in ritardo!!

A parte questo, però, l’evento è stato di primo ordine: ottimi gli speaker, ottimo (almeno per me che non sono proprio uno specialista della piattaforma Mobile) Windows Mobile 6.5 e, soprattutto, ottime le novità che ci aspettano tra breve.

Non sto a dilungarmi (altri lo faranno con migliore dovizia di particolari) sugli argomenti trattati ma mi preme sottolineare l’idea del Marketplace (per i profani l’alter ego dell’App Store di Apple).

La maggior parte delle persone dirà che Microsoft, al solito, ha copiato, anche se in realtà, ad essere precisi, siti per la pubblicazione e la vendita di software per dispositivi smartphone già ne esistevano prima dell’App Store. Chi ha copiato chi non è il centro della questione, il Marketplace di Microsoft prevede la vendita di applicazioni “certificate” dalla ditta di Redmond e, almeno in linea teorica, non sembra poter diventare il guazzabuglio di applicazioncine “Hello World!!” inutili e pericolose che sono altri store on-line!!

Il Marketplace sarà lanciato, presumibilmente, al termine dell’estate (settembre-ottobre) anche se le iscrizioni come sviluppatori sono già aperte. Per chi fosse interessato può andare sul sito developer.windowsmobile.com dove troverà tutte le info del caso.

Il Marketplace ospiterà solo applicazioni Windows Mobile 6.5 (ma ce ne faremo una ragione), prevederà una quota di iscrizione annua (dovrebbe essere 99$), una quota per ogni applicazione da certificare (anche qui 99$) e un guadagno del 70% del prezzo di vendita allo sviluppatore.

La cosa mi sembra interessante, soprattutto se pensiamo che l’App Store di Apple ha raggiunto il miliardo di download in poco tempo! Quindi, forza ragazzi MOBILITIAMOCI!!!!!

venerdì 3 luglio 2009

ASP.NET : Login page ashx

Salve a tutti, pubblico questo breve post per segnalarvi un piccolo problema capitatomi ma che potrebbe servire ad altri.

Sviluppando una web application in ASP.NET mi è capitato di dover implementare la pagina di login tramite un Handler (un file login.ashx).

Questo perchè l’autenticazione del sito era particolare e non richiedeva interazione con l’utente.

Peccato che, così facendo mi sono accorto di non avere a disposizione la sessione all’interno delle pagine (HttpContext.Current.Session = Nothing tanto per capirci) !!!

Poi, girovagando su internet, mi sono imbattuto in questo vecchio post di Scott Hanselman che si riferisce all’utilizzo della sessione all’interno di HttpHandlers implementando (obbligatoriamente, altrimenti niente sessione) una delle due interfaccie IRequiresSessionSate (per avere controllo completo sulla sessione) o IReadOnlySessionState (per avere la sessione in sola lettura).

Alla fine, morale della favola, se il vostro handler di login (ammesso che ne abbiate bisogno) non implementa la IRequiresSessionState (o la IReadOnlySessionState), vi potete scordare la sessione (come se non venisse mai creata).

Non so se esistono altre soluzioni al problema, ma intanto questa sembra funzionare.