Blog di LucaB

audio, video, disco

May 2007 - Posts

Hanno avvisato il Team di Visual Studio dell'uscita di Vista?

La domanda, direbbe qualcuno, sorge spontanea. Non hanno fatto un'ottima impressione, infatti, nel rilasciare la SP per Vista ben oltre il 30 gennaio. E la situazione attuale non è un granché bella: per lavorare con Visual Studio su Vista (sono reduce da una reinstallazione completa) ho dovuto installare nell'ordine:

  1. Visual Studio
  2. SP1
  3. SP per Vista
  4. SQL Server Express con relativo SP
  5. ASP.NET 2.0 AJAX Extensions 1.0

seguiti da una serie di tools (AJAX futures CTP, AJAX Control Toolkit, starter kit vari, Web Deployment, ecc. ecc.). Senza contare che dopo questi aggiornamenti, Visual Studio (che ho in inglese) si presentava ibrido, ossia mezzo in italiano e mezzo in inglese, come visibile nel ritaglio seguente. E con una serie di conseguenze indesiderate, come l'assenza dei template di progetto, errore nell'apertura della guida in locale (funzionava solo quella on line).

Visual Studio "ibrido"

Ci ho messo un po' per capire che per rimettere tutto a posto basta impostare di nuovo la lingua in inglese invece che "Come Microsoft Windows" (impostazione cambiata in automatico dall'aggiornamento).

 Impostazione della lingua in VS

Ieri, invece, un nuovo problema. Sto lavorando a dei siti web multilingua, per i quali sto cercando delle soluzioni eleganti che implementino la localizzazione dei contenuti tenendo conto anche di teniche di SEO. Di questo ne parlerò in un prossimo post, appena avrò trovato una soluzione ottimale, mentre quella ipotizzata in prima analisi in questo post è stata rivista proprio perché non è adeguata ad offrire visibilità ai motori di ricerca.

Per ora sto sperimentando tecniche di URL rewriting, che in fase di sviluppo hanno un inconveniente: è necessario, infatti, fornire un indirizzo assoluto alle risorse per le quali non si prevede la riscrittura dell'URL, come ad esempio le immagini.

Ma lavorando su un sito web sul filesystem locale, e non su IIS, il progetto parte non in una root, ma in una sottodirectory, come se fosse una directory virtuale su IIS, per cui si complica la scrittura degli handler delle immagini e si hanno problemi con gli indirizzi assoluti delle altre risorse.

Cercando su Internet sono arrivato a questo articolo, in cui è spiegato chiaramente come grazie al SP1 è molto semplice impostare in Visual Studio le proprietà del sito web affinché venga avviato in un virtual path di root.

Impostazione delle proprietà del sito, immagine copiata dal blog di Scott Guthrie

A questo punto si verifica il problema: al momento di pubblicare il sito, la pubblicazione viene saltata a causa di un errore descritto come "Index was outside the bounds of the array"

Errore durante la pubblicazione, immagine copiata dal blog di Scott Guthrie

È ancora Scott Guthrie a fornirmi la soluzione, riferendosi ad una Public Hotfix Patch for VS "Index was outside the bounds of the array" Publish Website Issue. (Ovviamente il suo blog è entrato di prepotenza nel mio blogroll)

Pertanto ho effettuato il download della patch e l'ho installata. Risultato: di nuovo la lingua incasinata e l'errore nella pubblicazione tale e quale a prima.

Leggendo i commenti allo stesso post, scopro che altri utenti con Vista lamentavano l'inefficacia della patch, che invece aveva risolto il problema su altri OS.

Per fortuna in uno di questi commenti ho trovato la soluzione ai miei problemi. In pratica la patch avrebbe dovuto sostituire un file di Visual Studio (C:\Program Files\Microsoft Visual Studio 8\Common7\Packages\mswebprj.dll) portandolo indietro dalla versione 8.0.50727.867 datata 22/2/2007 alla 8.0.50727.813 datata 28/2/2007 (data successiva, numero versione precedente).

Proprietà di mswebprj.dll prima della patch (e anche dopo!)

Per un motivo inspiegabile, però, questo su Windows Vista non avviene. È necessario pertanto applicare la patch ad una copia di Visual Studio installata su una macchina con un altro SO e copiare a mano il file incriminato sul PC con Windows Vista, risolvendo tutti i problemi.

Possibile che nessuno abbia avvisato il Team di sviluppo di Visual Studio dell'uscita di Windows Vista?

Technorati tags: , ,

View blog reactions

File bloccati in Vista

Qualche giorno fa ho scaricato PureText, una mini-utility per incollare il testo della clipboard senza formattazione (dopo averne letto la recensione in questo post).

PureText non ha bisogno di installazione (si tratta di un singolo file eseguibile di 28KB) e una volta avviato, compare un'iconcina nella tray-area e dopo aver copiato un testo, basta la combinazione +V per incollare il testo "purificato".

Nella finestra delle opzioni, inoltre, è possibile scegliere se avviare PureText in automatico.

Le opzioni di PureText

Allora ho creato nella cartella programmi una sottocartella PureText e ho copiato lì l'eseguibile. Poi l'ho avviato ed ho settato l'opzione dell'avvio automatico.

Al successivo riavvio, però, mi è apparsa una schermata di un avviso di protezione, in cui mi si chiedeva se volessi eseguire il file PureText.exe.

L'avviso di protezione che si presentava al riavvio

Poco male, ho tolto la spunta dove dice "Avvisa sempre prima di aprire questo file" e l'ho eseguito, convinto che al prossimo riavvio sarebbe partito senza problemi. Invece non è stato così, perché il giorno dopo, riacceso il PC, di nuovo mi è apparsa la stessa richiesta. Sono andato perciò direttamente sul file eseguibile e nella finestra proprietà ho trovato che il file, essendo stato scaricato dalla rete, risultava bloccato.

Proprietà del file PureText.exe

Anche in questo caso, però, un comodo pulsante annulla blocco sembrava essere la risoluzione del problema. Ho perciò annullato il blocco, ma anche così facendo al riavvio ho ottenuto di nuovo l'avviso di protezione. Tornando a vedere le proprietà del file, questo risultava ancora bloccato.

Probabilmente ciò è dovuto al fatto che la cartella programmi richiede autorizzazioni speciali, sta di fatto che alla fine per risolvere il problema ho:

  • copiato l'eseguibile sul desktop
  • annullato il blocco
  • copiato l'eseguibile dal desktop alla cartella programmi, sovrascrivendo l'esistente

ed al riavvio il programma è partito senza fare domande.

Adottando la stessa tecnica ho risolto un problema analogo sul PC di un collega, anche lui con Vista Business. Nel suo caso era un eseguibile nella cartella Programmi relativo alla scheda audio, che era stato impostato per essere eseguito al login dalla procedure di installazione dei driver della scheda audio, anche questi scaricati da Internet.

Per non avere questi problemi è necessario, perciò, annullare il blocco dei file scaricati da Internet prima di installarli o di copiarli in una cartella protetta come quella programmi.

Technorati tags: ,

View blog reactions

Posted: May 25 2007, 05:10 PM by lucab | with 1 comment(s)
Filed under:
Occhio alla bufala

Windows Vista è il primo sistema operativo Microsoft che è stato lanciato nell'era dei blog. Pertanto è disponibile in rete un mare di informazioni su questo OS, sin da prima del lancio stesso. Insieme alle informazioni, però, è facile trovare anche un'enorme quantità di bufale, probabilmente anche in misura maggiore delle prime.

L'universo dei blog, infatti, comprende tantissimi utenti e spesso la qualità delle informazioni trovate in rete lascia a desiderare. Si assiste, inoltre, a catene in cui un blogger fornisce un'informazione sbagliata e centinaia di altri la ripetono, citandolo e citandosi come fonte, senza che nessuno si preoccupi di verificarne la veridicità.

Di questo tema ha scritto qualche giorno fa Jeff Atwood nel post intitolato "Apparently Bloggers Aren't Journalists", in cui sostanzialmente afferma che i blogger non sono giornalisti professionisti. Questi, infatti, sono tenuti a verificare da diverse fonti le informazioni, a cercare gli interessati per un contradditorio, a verificare l'affidabilità delle fonti stesse, ecc. (evidentemente Jeff non conosce il giornalismo italiano Wink), mentre i blogger no. 

Però, secondo lui (ed io sottoscrivo), prima di mettere un link ad un claim qualsiasi, ogni blogger dovrebbe verificare la notizia ("do their homework").

Bufale in VistaIn attesa che ogni blogger verifichi quello che scrive, può essere utile consultare Bufale in Vista. È una pagina web, da poco on line, dove paperino ha raccolto i post in cui smaschera alcune delle bufale che si possono leggere in giro su Windows Vista.

Conoscendo paperino, ma anche leggendo da tempo i suoi post, sono certo che non l'ha fatto per partecipare all'ennesima guerra di religione in ambito software. Semplicemente gli è proprio difficile accettare senza controbattere il FUD sparso in giro, per cui ha fatto i compiti a casa e fornito le prove che tanti claim in realtà sono semplicemente delle sciocchezze.

Technorati tags: ,

View blog reactions

Posted: May 24 2007, 12:30 AM by lucab | with no comments
Filed under:
Scherzi da ... messenger

Grazie a Beppe (o forse per colpa sua Wink) ho scoperto questo addon gratuito per Windows Live Messenger che, tra l'altro, permette di imitare il proprio interlocutore, ossia far sembrare che sia lui a scrivere.

Io sarei "ideologicamente" contrario a questi addon (spesso includono spyware, speriamo non sia questo il caso), però devo ammettere che è davvero esilarante vedere il proprio interlocutore andare nel panico Big Smile

Technorati tags: ,

View blog reactions

Un plugin per Windows Live Writer

Nel poco tempo a disposizione nell'ultima settimana (una motherboard si è rotta e la nuova si è rivelata difettosa giusto alla fine delle reinstallazioni e ripristino dati) ho provato ad arricchire questo blog con alcuni accessori, come snapshot per i link. Dopo essermi registrato su Technorati, inoltre, ho aggiunto ai post già scritti (tanto sono ancora pochi) i Technorati tags e ho voluto provare ad aggiungere a ciascuno di essi il Link Count Widget, ossia un'indicazione di quanti sono i blog che linkano quel post (per la cronaca, ancora nessuno fino ad ora Sad).

Per aggiungere tale feature su Community Server bisogna inserire in ogni post questo snippet in HTML:

<script src="http://embed.technorati.com/linkcount" type="text/javascript">
</script> <a class="tr-linkcount" href="http://technorati.com/search/{URL}">
View blog reactions</a>

In realtà la prima parte può essere messa una volta per tutte nell'header HTML delle pagine del blog, specificandolo nella Dashboard relativa al proprio account. Nella seconda parte, invece, bisogna sostituire a {URL} l'indirizzo completo del post in questione.

Il problema è che l'indirizzo del post non è noto fino a che il post non viene pubblicato, anche se è ricavato dal titolo dello stesso e dalla data di pubblicazione con un semplice algoritmo. Un metodo semplice per ovviare a questo inconveniente sarebbe di scrivere al posto di {URL} un'espressione di DataBind del tipo:

<%# BlogUrls.Instance().Post(WeblogControlUtility.Instance()
.GetCurrentWeblogPost(this)) %>

Purtroppo, per ovvi motivi di sicurezza, non è possibile inserire espressioni di DataBind in un post (sarebbero codificate e rese innocue). Pertanto, non avendo accesso alle impostazioni di administrator della piattaforma, l'unica scelta sembrava quella di una doppia pubblicazione, con l'inserzione manuale dello snippet e dell'URL solo in seconda battuta.

Una leggera semplificazione, però, si può ottenere grazie ad un semplice plugin per Live Writer, che sia in grado di automatizzare parte della procedura ed evitare di dover inviare due volte il post (suggerimento di Paperino).

Per farlo da qui ho scaricato da qui Windows Live Writer SDK, l'ho installato ed ho dato un'occhiata alla documentazione ed al plugin di esempio (HelloWorldPlugin), da cui ho capito che per risolvere il mio problema avrei dovuto scrivere un Simple Content Source Plugin. Come source per il content avrei dovuto un Insert Dialog.

I passi per la creazione di un Content Source Plugin dalle caratteristiche indicate sono i seguenti:

  1. creare un nuovo progetto Class Library in Visual Studio;
  2. aggiungere una reference all'assembly WindowsLive.Writer.Api (che si trova nella stessa cartella dell'eseguibile di Windows Live Writer, ad es: C:\Programmi\Windows Live Writer);
  3. creare una nuova classe, nel mio caso TLCWPlugin, derivata dalla classe ContentSource;
  4. aggiungere a questa classe gli attributi WriterPluginAttribute e InsertableContentSourceAttribute e scrivere l'override del metodo CreateContent.

Se si aggiunge alle opzioni di compilazione la nei post-build event command line

XCOPY /D /Y /R "$(TargetPath)" "C:\Programmi\Windows Live Writer\Plugins\"

allora la dll generata sarà copiata direttamente nella directory dei plugin di Live Writer per essere provata.

Il codice risultante è (in VB.NET):

Imports System
Imports System.Windows.Forms
Imports WindowsLive.Writer.Api

<WriterPlugin("ce9a848e-c786-4e54-a0e2-1abff354e396", 
"Technorati Link Count Widget", ImagePath:="Technorati.png", _
Description:="Insert Technorati Link Count Widget in your post.", _
PublisherUrl:="http://www.webis.it")> _ <InsertableContentSource("Technorati Link Count Widget", _
SidebarText:="Link Count Widget")> _ Public Class TLCWPlugin Inherits ContentSource Public Overrides Function CreateContent( _
ByVal dialogOwner As System.Windows.Forms.IWin32Window, _
ByRef newContent As String) As System.Windows.Forms.DialogResult Using InsertForm As TLCWInsertForm = New TLCWInsertForm Dim risultato As DialogResult = InsertForm.ShowDialog If risultato = DialogResult.OK Then newContent = InsertForm.Stringa End If Return risultato End Using End Function End Class

Come si può vedere nell'attributo WriterPluginAttribute, oltre a id e nome, è possibile specificare anche altre informazioni, quali l'icona del plugin (una immagine embedded di dimensioni 20x18). Nell'attributo InsertableContentSource, inoltre, si può specificare un testo per la Sidebar diverso da quello del menù (c'è meno spazio).

Nel corpo del metodo CreateContent, invece, il codice non fa altro che aprire una finestra di dialogo con la form TLCWInsertForm, in cui sarà fatto tutto il lavoro.

screenshot del plugin in azione

Se la finestra è chiusa con DialogResult.OK (Insert), allora verrà inserito il nuovo contenuto, prelevandolo dalla proprietà pubblica Stringa della classe TLCWInsertForm.

Il codice per la proprietà è semplicemente:

    Private _Stringa As String

    Public Property Stringa() As String
        Get
            Return _Stringa
        End Get
        Set(ByVal Value As String)
            _Stringa = Value
        End Set
    End Property

(scritto ancora più velocemente grazie a questa macro di Francesco Balena, leggermente modificata, che trasforma field in proprietà)

Al caricamento della form viene eseguito il codice seguente, che carica (se presenti) le impostazioni memorizzate per il plugin, ossia l'URL del blog[1] e la presenza nell'header HTML del tag script:

Private Sub TLCWInsertForm_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load Me.DateTimePicker1.Value = Date.Today Me.Stringa = "" Me.LoadSettings() Me.TextBoxBlogUrl.Text = Me._blogUrl Me.CheckBoxJsInHeader.Checked = Me._checked Me.LabelNote.Visible = Not Me.CheckBoxJsInHeader.Checked End Sub
Private Sub LoadSettings()
    Dim fs As FileStream = Nothing
    Dim rd As StreamReader
    Me._blogUrl = Me._defaultBlogUrl
    Me._checked = Me._defaultChecked
    Try
        fs = New FileStream(Me._configPath & Path.DirectorySeparatorChar & _
Me._configFileName, FileMode.Open) rd = New StreamReader(fs) Me._blogUrl = rd.ReadLine().Trim If CBool(rd.ReadLine) = True Then Me._checked = True End If Catch ex As Exception Finally If fs IsNot Nothing Then fs.Close() End If End Try End Sub

Invece alla pressione di Insert, vengono effettuati controlli sulla presenza dei campi obbligatori, viene calcolato l'url in base alla data (di default è impostata quella di sistema) ed al titolo (attraverso la funzione UrlEncode), si imposta la proprietà Stringa e vengono salvate le impostazioni se sono cambiate.

Private Sub ButtonOK_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles ButtonOK.Click If DatiValidi() Then Dim url As String url = TextBoxBlogUrl.Text If Not url.EndsWith("/") Then url &= "/" End If url &= DateTimePicker1.Value.Year.ToString & "/" & _
DateTimePicker1.Value.Month.ToString("00") & "/" & _
DateTimePicker1.Value.Day.ToString("00") & "/" & _
UrlEncode(TextBoxPostTitle.Text, _
New Regex("([^A-Za-z0-9 ]+|\.| )", _
(RegexOptions.Singleline Or RegexOptions.Compiled)), "-"c, "_"c) & _
".aspx" Me.Stringa = String.Format(Me._technoratiString, url) If CheckBoxJsInHeader.Checked = False Then Me.Stringa = Me._technoratiJavascript & Me.Stringa End If If Not Me.SaveSettings() Then MsgBox("Error while saving your settings.") End If Else Me.DialogResult = Windows.Forms.DialogResult.None End If End Sub Private Function SaveSettings() Dim risultato As Boolean = True ' salva solo se le impostazioni sono cambiate If (Me._blogUrl <> TextBoxBlogUrl.Text) OrElse _
(Me._checked <> CheckBoxJsInHeader.Checked) Then Dim wr As StreamWriter = Nothing Try If Not Directory.Exists(Me._configPath) Then Directory.CreateDirectory(Me._configPath) End If wr = My.Computer.FileSystem.OpenTextFileWriter(Me._configPath & _
Path.DirectorySeparatorChar & Me._configFileName, False) wr.WriteLine(TextBoxBlogUrl.Text) wr.WriteLine(CheckBoxJsInHeader.Checked.ToString) Catch ex As Exception risultato = False Finally If wr IsNot Nothing Then wr.Close() End If End Try End If Return risultato End Function

Per quanto riguarda la funzione:

Private Function UrlEncode(ByVal titolo As String, _
ByVal pattern As Regex, _
ByVal spaceReplacement As Char, _
ByVal escapePrefix As Char) As String

è stato abbastanza semplice estrapolarla dal binario di Community Server, grazie a Reflector for .NET ed è disponibile insieme al codice completo qui.

Nota bene: per chi non potesse o non volesse mettere nell'header HTML il tag script, è presente anche una checkbox apposita, il cui valore rimane memorizzato per la volta successiva. Attenzione: questa feature deve essere utilizzata in modalità HTML Code, posizionando il cursore al di fuori di qualsiasi container HTML, altrimenti il tag script verrà semplicemente ignorato da Live Writer. Non sono riuscito, infatti, a trovare un modo per costringere il plugin ad aggiugere il content alla fine di tutto il testo (forse non esiste).

Il plugin è scaricabile liberamente da qui (TechnoratiLinkCountWidget.zip - 12KB), mentre il codice completo è qui (TLCWplugin.zip - 570KB)

View blog reactions


[1] L'URL del blog deve comprendere anche la subdirectory dove vengono archiviati gli articoli, ad esempio su dotnetside per il mio blog si avrebbe: http://www.dotnetside.org/blogs/lucab/archive
Un esercizio potrebbe essere di aggiungere alle opzioni del plugin un piccolo parser che costruisca l'URL in base ad un formato impostato dall'utente.
Windows Vista

Ho trovato alcuni siti interessanti su Windows Vista, che mi sembrano utili da consultare per cominciare a prendere confidenza con questo sistema operativo.

Windows Vista for beginners è un sito che costituisce un'utile guida alle nuove caratteristiche ed ai cambiamenti introdotti da questo sistema operativo rispetto a Windows XP. Il sito è in inglese ed è consultabile anche per sezioni (Tutorials, Where to find..., New Apps, Extra, ecc.). Ottimo per cominciare, come dice il nome del resto.

Molto interessante e ricca di suggerimenti è l'ampia sezione dedicata a Windows Vista del sito the How-To Geek. Gli How To sono elencati per categorie (Desktop Customisation, Managing Files and Folders, Network and Internet, Security, System Administration, Windows Aero Glass, Tips and Tweaks) e tra essi ce ne sono di molto utili e difficili da trovare altrove. Anche questo sito è in inglese.

PuntoDiVista è un blog monotematico su Windows Vista in italiano, costantemente aggiornato (più volte al giorno) con notizie di ogni tipo relative al nuovo sistema operativo.

I miei guai con Vista è un blog (in italiano) in cui l'autore ci racconta in diretta "le avventure e soprattutto le disavventure" del suo passaggio a Vista (e grazie al quale ho scoperto i primi due siti di questo post).

Technorati tags: ,

View blog reactions

Posted: May 14 2007, 02:10 AM by lucab | with no comments
Filed under:
VS Trophy

Box Visual Studio 2005 Professional EditionHo ricevuto da Giuseppe Marchi la segnalazione di questo concorso per sviluppatori .NET, con in palio due licenze di Visual Studio .NET 2005 Professional Edition.

La prima licenza viene assegnata per estrazione, tra l'elenco di utenti che hanno inviato almeno un tip, ossia un breve e semplice estratto di codice .NET, al sito web del concorso.

La seconda licenza viene assegnata da una giuria che valuta dei progetti inviati dagli utenti sempre allo stesso sito.

Partecipare non costa nulla, ma chi fosse interessato deve affrettarsi, perché l'estrazione avverrà il 19 maggio 2007.

Tutte le informazioni su http://www.vs-trophy.net

View blog reactions

Superfetch di Vista

Superfetch è una delle caratteristiche di Windows Vista per me più sorprendente, per come riesce a velocizzare il tempo necessario all'apertura dei programmi che uso sul mio PC.

Grazie al solito paperino, qui possiamo leggerne un'analisi approfondita ma allo stesso tempo molto semplice da capire (almeno per me Wink).

Nello stesso post, inoltre, si chiariscono alcune delle fesserie alcuni dei falsi miti che si possono leggere in giro a proposito di questa feature. Per smentirli è bastato semplicemente adottare un metodo che sembra sconosciuto ad alcuni tra i troppi esperti della materia: il metodo scientifico.

Technorati tags: ,

View blog reactions

Posted: May 08 2007, 02:31 AM by lucab | with no comments
Filed under:
Internet Explorer Developer Toolbar e Vista

Internet Explorer Developer Toolbar è una toolbar per IE6 e IE7 molto comoda per chi deve lavorare ad un sito web. È disponibile nella versione Beta 3, che può essere scaricata da qui, dove si trova anche un elenco completo delle feature. Qui invece se ne trova una descrizione dettagliata.

Oltre ai classici strumenti di navigazione e modifica del DOM e dei CSS presenti nella toolbar, trovo molto utili:

  • Tools->Resize: ridimensiona la finestra del browser permettendo di vedere come apparirebbe un sito a diverse risoluzioni;
  • Tools->ColorPicker: per "catturare" il colore di un qualsiasi punto della pagina (ed evitare di telefonare al grafico per farselo dire o aprire un programma apposta)
  • Validate: consente, tra l'altro, di testare dal punto di vista della validazione W3C la versione off line della pagina HTML (Local HTML) e del CSS (Local CSS) con un solo click.

Tra le cose che, secondo me, andrebbero riviste (del resto è una Beta), ci metto:

  • l'interfaccia un po' troppo invasiva (nella Beta 2 mi sembrava più discreta, questa non mi convince ancora);
  • la visualizzazione dei source DOM in cui i tag e gli stili sono tutti in maiuscolo (anche se non lo sono in Original).

Con Windows Vista, inoltre, l'installazione della IE Developer Toolbar (fornita come file .msi) mi ha dato alcuni problemi. Ho fatto doppio click sul file di installazione e tutto è sembrato l'icona della IE Developer toolbar svolgersi regolarmente. Alla fine in IE7 è apparsa l'icona della toolbar,  ma cliccandoci sopra non accadeva nulla. Anche seguendo il suggerimento di fare log off e log on (sempre da The Microsoft Internet Explorer Weblog) non sembrava sortire alcun effetto, come pure il riavvio della macchina.

Sono riuscito a risolvere solamente eseguendo un prompt dei comandi come amministratore e facendo partire da lì l'installazione della IE Developer Toolbar. Alla fine dell'installazione cliccando sul pulsante è apparso finalmente il pannello inferiore della toolbar.

Dato che la Beta 3 è stata rilasciata il 9 gennaio 2007, prima del lancio di Vista, credo che questo problema sarà risolto già nella prossima release.

View blog reactions

Localizzazione

Sto lavorando ad alcuni siti web che, tra l'altro, dovranno essere visualizzabili in diverse lingue. Con ASP.NET 2.0 il lavoro dello sviluppatore viene semplificato notevolmente, come è possibile capire leggendo questo articolo di Tiziana Loporchio e quest'altro di Giuseppe Marchi, grazie anche ai tool di Visual Studio 2005 e al Resource Refactoring Tool (dal 13/2/2007 è disponibile la 1.0).

Nel mio caso il problema sarebbe anzitutto di non rinunciare all'impostazione della cultura in automatico dalle impostazioni del browser, attraverso la configurazione nel file web.config del tag globalization (nella sezione system.web):

<globalization culture=”auto:it-IT” uiCulture=”auto:it”>

In questo modo un utente che avesse tra le impostazioni del suo browser una delle lingue supportate per quel sito, vedrebbe direttamente ogni pagina nella lingua impostata.

C'è però il caso di un utente che ha impostata una lingua non supportata, oppure che vorrebbe consultare il sito in una lingua diversa da quella impostata sul browser.

Ho pensato di risolvere il problema trovando nella masterpage uno spazio per degli ImageButton (magari le solite bandierine), che al click eseguano il codice seguente:

Protected Sub ImageButtonEnUs_Click(ByVal sender As Object, _
ByVal e As System.Web.UI.ImageClickEventArgs) Handles ImageButtonEnUs.Click
    If Session("lingua") IsNot Nothing Then
        Dim lingua As String = CStr(Session("lingua"))
        If lingua <> "en-US" Then
            Session("lingua") = "en-US"
            Response.Redirect(Me.Request.Url.PathAndQuery)
        End If
    End If
End Sub

A questo punto è necessario fare in modo che ogni pagina visitata dallo stesso utente venga visualizzata nella lingua selezionata. La soluzione migliore mi è sembrata quella di creare una classe ereditata da System.Web.UI.Page, da cui derivare tutte le pagine del sito, ed in essa scrivere un override del metodo InitializeCulture:

Public Class PaginaLocalizzata
    Inherits System.Web.UI.Page 

    Protected Overrides Sub InitializeCulture()
        If Session("lingua") IsNot Nothing Then
            Dim ci As New CultureInfo(CStr(Session("lingua")))
            Thread.CurrentThread.CurrentCulture = ci
            Thread.CurrentThread.CurrentUICulture = ci
        Else
            MyBase.InitializeCulture()
        End If
    End Sub

End Class

Probabilmente la cosa si può migliorare, però lo scopo è raggiunto: ogni pagina è visualizzata nella lingua impostata nel browser (o in quella di default), ma se l'utente decide di volerla visualizzare in una delle altre lingue supportate, basta un click e da quel momento il sito gli apparirà nella lingua selezionata.

Technorati tags: , , ,

View blog reactions

Partition manager di Vista

Ancora non conoscevo questa feature di Windows Vista: il nuovo partition manager, che consente di cambiare la dimensione delle partizioni senza riavviare, grazie alle funzionalità di shrink e extend.

Qui si trova una descrizione più dettagliata.

Technorati tags: ,

View blog reactions

Posted: May 03 2007, 12:32 AM by lucab | with no comments
Filed under:
Cambiare dinamicamente l'immagine di intestazione del blog

Una delle prime cose che ho fatto su questo blog è stato provare i diversi skin. La gestione del look del blog dà anche la possibilità di sovrascrivere il css, il che ad esempio è utile se si vuole cambiare un'immagine impostata come background di un elemento div.

E se volessi cambiare l'immagine visualizzata come background dell'intestazione scegliendola in maniera casuale, oppure a seconda dell'ora in cui si visualizza la pagina?

Ho pensato, ad esempio, di preparare 5 immagini diverse: 5 fotoritocchi dello stesso panorama (eseguiti malamente da me, ma appena si libera Nico[1] mi faccio aiutare) che, cambiandone la luce, danno le versioni "mattino.jpg", "giorno.jpg", "pomeriggio.jpg", "sera.jpg" e "notte.jpg", tra cui scegliere quale visualizzare a seconda dell'ora.

mattino giorno pomeriggio sera notte

Avendo a disposizione un server web, ho scritto una piccola applicazione che utilizza un HttpHandler.

Basta creare un progetto web con VS e, all'interno di questo, aggiungere un un HttpHandler, come illustrato in figura (ho usato VS Web Developer 2005 Express Edition):

Screenshot di VS Web Developer 2005 Express Edition

A questo punto dobbiamo scrivere il codice. Stiamo scrivendo un HttpHandler, ossia implementando l'interfaccia IHttpHandler, per cui dovremo specificare il metodo ProcessRequest e la proprietà IsReusable.

IsReusable può essere impostata a False o a True: come dice la parola stessa, indica se il nostro oggetto handler può essere riutilizzato (True) o se ogni volta se ne deve creare una nuova istanza (False). Poiché l'handler non andrà a modificare nulla, ma solo a leggere dati, il codice può essere considerato threadsafe, per cui la impostiamo a True.

ProcessRequest rappresenta cosa deve fare praticamente l'handler quando riceve una richiesta, cioè nel nostro caso deve inviare al client l'immagine opportuna in base all'ora del sistema. Ad esempio il codice in VB.NET potrebbe essere questo (non tenendo conto di stagioni, ora legale, ecc. Wink)

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

Adesso basta inviare al client il file binario che rappresenta l'immagine jpg scelta utilizzando Response.WriteFile riferito all'HttpContext (argomento della ProcessRequest).

Alla fine il codice completo è il seguente:

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

Imports System
Imports System.Web

Public Class ImmagineOraria : Implements IHttpHandler
    
    Const DIRIMMAGINI = "directoryimmagini/headerblog/"
    
    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

Nella dashboard del blog basta fare un override del css impostando (per il div di intestazione):

background-image: url(http://miowebserver/ImmagineOraria.ashx);

ed il gioco è fatto.

Per provare l'handler localmente prima di farne l'upload sul server, basta aggiungere al progetto una semplice pagina HTML che contenga nel body:

<img src="ImmagineOraria.ashx" alt="immagine"/>

Un'altra possibilità potrebbe essere quella di far scegliere l'immagine a caso tra quelle presenti all'interno di una cartella sul server. In questo caso il codice in VB potrebbe essere:

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

Imports System
Imports System.Web

Public Class ImmagineCasuale : Implements IHttpHandler
    
    Const DIRIMMAGINI = "directoryimmagini/headercasuale"
    
    Public Sub ProcessRequest(ByVal context As HttpContext) _
Implements IHttpHandler.ProcessRequest Dim nomiFileImmagine() As String = _
System.IO.Directory.GetFiles(context.Server.MapPath(DIRIMMAGINI), "*.jpg") 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 Public ReadOnly Property IsReusable() As Boolean _
Implements IHttpHandler.IsReusable Get Return True End Get End Property End Class


[1]Il mio amico Nico lavora come grafico nella mia stessa ditta e con Photoshop è in grado di realizzare in 2 minuti quello che riesco a fare in 1 ora, ma con risultati decisamente migliori. Del resto la tecnologia avanza, ma (come disse Vito a proposito di WPF nel corso di un evento) la grafica creata dagli sviluppatori fa sempre abbastanza schifo.

View blog reactions