Scaricare tutti i video delle sessioni del Build
Per chi come me è in overflow da news tecnologiche, e non vuole perdersi neanche un minuto del Build, ecco gli step da seguire per scaricarsi tutte le sessioni:
- Creare una folder dove verranno scaricati i video (nell’esempio è chiamata build11);
- Creare un file .ps1 (downloadall.ps1 nell’esempio) ed editarlo con il notepad incollando il seguente codice:
cd "C:\build11"
[Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
$a = ([xml](new-object net.webclient).downloadstring("http://channel9.msdn.com/Events/BUILD/BUILD2011/RSS/wmvhigh"))
$a.rss.channel.item | foreach{
$url = New-Object System.Uri($_.enclosure.url)
$file = $url.Segments[-1]
$file
if (!(test-path $file))
{
(New-Object System.Net.WebClient).DownloadFile($url, $file)
}
}
- avviare Powershell e digitare Set-ExecutionPolicy unrestricted (necessario all’esecuzione dello script);
- avviare lo script da powershell c:\build11\downloadall.ps1
Il tutto è basato su questo post che si appoggia a sua volta in un post di Scott Hanselman.
Buon download.
Come è fatto un datacenter di Azure?
È sicuramente una domanda che ci siamo fatti in molti e sfortunatamente solo pochi avranno la possibilità di darci un’occhiata da vicino.
Dove non si può arrivare fisicamente c’è internet ![]()
Buona visione.
Idle timeout in IIS e Azure
Come era facilmente intuibile da uno dei miei ultimi post, ultimamente sto lavorando ad un’applicazione “hostata” su Windows Azure. Oltre ai “problemi” di continuous deployment descritti qui, ho riscontrato un altro piccolo problema riguardante la configurazione di IIS.
IIS ha un’interessante configurazione (idle timeout) nata allo scopo di ridurre al minimo le risorse utilizzate dalle applicazioni web; tale configurazione consiste nello “spegnere” un sito web, nel caso non vi siano richieste da parte di utenti per un tempo di 20 minuti.
Questo valore è ovviamente configurabile dalla console di IIS e lo si può ridurre, aumentare o addirittura disabilitare. Nel caso ci si trovi nell’ambito di un’installazione locale, è sufficiente cambiare la configurazione dell’application pool che “hosterà” il nostro sito web.
Ma se ci si trova in Windows Azure?
In Azure non è possibile accedere in terminal server alla macchina contenente il nostro sito e cambiare l’Idle Timeout. Esiste però un escamotage che abilita tale accesso al server sul cloud; tale “hack” risulterebbe in ogni caso inutile, in quanto al riavvio della macchina virtuale (ma anche alla creazione di una nuova istanza) sarebbe necessario reimpostare di nuovo il valore, obbligandoci così a collegarci nuovamente in terminal server.
Fortunatamente all’interno del package di Azure possiamo definire dei task di avvio, che verranno eseguiti ad ogni riavvio della macchina virtuale (o alla creazione di una nuova istanza). All’interno di questi task possiamo eseguire applicazioni, comandi DOS e quant’altro possa servirci per far funzionare la nostra applicazione.
In questo post Steve Marx spiega come eseguire dei task e, proprio in questo esempio, mostra come cambiare il timeout di default di IIS.
Per prima cosa è necessario modificare il file ServiceDefinition.csdef ed inserire il seguente codice:
<Startup>
<Task commandLine="Tasks\startup.cmd" executionContext="elevated" taskType="simple" />
</Startup>
Per questo esempio il task type sarà di tipo simple, ma in un futuro post vedremo le differenti tipologie ed eventuali scenari di utilizzo.
Da qui in poi è sufficiente creare un file .cmd con all’interno il comando DOS per per disabilitare il timeout di IIS, come mostrato di seguito.
%windir%\system32\inetsrv\appcmd set config -section:applicationPools
-applicationPoolDefaults.processModel.idleTimeout:00:00:00
A questo punto l’applicazione hostata in Azure sarà sempre reattiva, anche in caso di poco traffico (molto comodo in fase di testing).
Ciauz
Google Sitelinks
È già da diverso tempo - almeno un anno - che mi chiedo come sia possibile gestire (magari tramite il markup) le varie sezioni che Google propone per alcuni siti a fronte di una ricerca. Vuoi per pigrizia, vuoi per mancanza di tempo, non ho mai indagato fino a pochi giorni fa, quando ho scoperto che non è possibile gestire tali sezioni J.
Lo screenshot seguente mostra meglio cosa intendo io per “sezioni”, che Google chiama Sitelinks:

Questa frase “At the moment, sitelinks are automated.” mi toglie tutte le speranze di poter organizzare i Sitelinks a mio piacimento, salvo che per un aspetto: rimuovere due brutti ceffi (mimì e cocò) dal risultato della ricerca per il mio dominio :D.
Come tutti i sistemi automatici, anche quelli fatti da Google possono sbagliare; fortunatamente BigG (soprannome di Google) offre la possibilità di segnalare possibili malfunzionamenti.
Accedendo al pannello di controllo per i webmaster (qui), è possibile specificare i link da rimuovere tra i SiteLinks per specifiche ricerche.
Ora mi aspetto che, entro 90 giorni, le due brutte persone dovrebbero sparire dai miei Sitelinks.
ASP.NET MVC in Azure
Ultimamente sto lavorando parecchio per migrare un’applicazione MVC3 su Azure. Una delle cose che trovo più noiose in Azure è il dover ricreare il package di deploy per ogni singola modifica; questo vuol dire che se si vuole cambiare un testo in una View occorre rifare il package e ripubblicarlo.
Devo dire che, lato Azure, è più che comprensibile come comportamento. Essendo questo basato su macchine virtuali, nel momento in cui una di queste “cade” o l’utente ha la necessità di aumentare la forza lavoro, l’infrastruttura di Azure non fa altro che caricare una nuova macchina virtuale e deployare il package all’interno, perdendo però un’eventuale modifica fatta su un file (come la View dell’esempio precedente).
Proprio per questo motivo, tutto ciò che necessita di essere modificato frequentemente e deve essere accessibile da tutte le istanze attive di Azure dovrebbe risiedere nel blob storage.
Dato che il progetto a cui sto lavorando è in continua evoluzione, e le view cambiano più è più volte nell’arco di una giornata, ho deciso di far “pescare” le View ad MVC direttamente dal blob storage di Azure e non dal filesystem della macchina virtuale, evitando così la scomodità di dover “rideployare” continuamente l’applicazione.
Con questo scenario il vantaggio è notevole, posso caricare un singolo file della View in pochi secondi con un qualsiasi tool (io personalmente uso Cerebrata Cloud Storage Studio, ma ne esistono molti altri gratuiti come questo).
Fortunatamente tutto questo è facilmente implementabile, senza dover modificare la nostra applicazione. Di fatto ci basta registrare un nostro VirtualPathProvider all’interno del Global.asax.cs ed il gioco è fatto.
Proviamo a dare un’occhiata al codice:
using System;
using System.Collections;
using System.Web.Caching;
using System.Web.Hosting;
using Dexter.Storage;
namespace Dexter.Web.Mvc.ViewEngines {
public class DexterVirtualPathProvider : VirtualPathProvider {
readonly IStorageProvider storageProvider;
public DexterVirtualPathProvider ( IStorageProvider storageProvider ) {
this.storageProvider = storageProvider;
}
public override bool FileExists ( string virtualPath ) {
var fullPath = storageProvider.GetPublicUrl ( virtualPath );
if (storageProvider.FileExist ( fullPath ))
return true;
return Previous.FileExists ( virtualPath );
}
public override VirtualFile GetFile ( string virtualPath ) {
var fullPath = storageProvider.GetPublicUrl ( virtualPath );
if (storageProvider.FileExist ( fullPath ))
return new DexterVirtualFile ( virtualPath, storageProvider );
return Previous.GetFile ( virtualPath );
}
public override CacheDependency GetCacheDependency ( string virtualPath , IEnumerable virtualPathDependencies , DateTime utcStart ) {
return null;
}
}
public class DexterVirtualFile : VirtualFile {
readonly IStorageProvider storageProvider;
public DexterVirtualFile ( string virtualPath , IStorageProvider storageProvider ) : base ( virtualPath ) {
this.storageProvider = storageProvider;
}
public override Stream Open ( ) {
var fullPath = storageProvider.GetPublicUrl ( VirtualPath );
return storageProvider.GetFile ( fullPath ).OpenRead ( );
}
}
}
Ovviamente in questo codice non c’è nessuna reference verso Azure, ma l’implementazione di IStorageProvider si occupa di accedere al blob del could. La cosa carina di quest’implementazione è che permette di “manipolare” il path delle view in un unico punto con un effort molto basso.
La registrazione sulla nostra HttpApplication avviene in questo modo:
public void ApplicationStart ( ) {
//....
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider ( new DexterVirtualPathProvider(azureStorageProvider) );
}
Da questo momento in poi le view verranno lette direttamente dal blob storage.
Alcuni miei articoli
Nel periodo pre-ferie, ho dedicato un po’ del mio tempo libero a studiare un po’ le novità che ci circonderanno da qui a breve e, da buon blogger (non è molto vero in quest’ultimo periodo), ne sono nati tre articoli che riporto qui di seguito:
- Implementare il pinning all’interno del proprio sito web (permalink);
- Web Worker e File API in HTML5 (permalink);
- IE9 Mobile e HTML5 su WP7 Mango (permalink);
Il mio preferito rimane sicuramente quello sui Web Worker e File API, anche se devo dire che il porting di IE9 su Mango mi ha davvero impressionato ![]()
Buon lettura
Web Developer in quel di Milano
Recentemente sono stato contattato per due posizioni aperte come Web Developer in zona Milano, se qualcuno di voi è interessato mi può contattare liberamente da qui.
Analizzare il traffico di rete per le chiamate https con Fiddler
Oggi ho avuto la necessità di analizzare del traffico di rete la cui Request partiva dalla mia macchina, per poi finire verso un webserver Java hostato in https su di un webserver Apache. Essendo esposto in BasicHttpBinding, il suo utilizzo è risultato da subito molto semplice; un semplice AddServiceReference da VisualStudio e poche righe di codice per cominciare a comunicare con la piattaforma esterna.
Tale comunicazione è avvenuta senza problemi al primo colpo, ma il dato restituito non conteneva tutte le informazioni che mi sarei aspettato per quella chiamata. Purtroppo dall’altra parte mi son sentito dire che il problema risiedeva nei miei proxy e che il parser dell’xml restituito dal servizio era errato.
Fortunatamente non ho mai avuto problemi di questo tipo con i proxy creati tramite svcutil, quindi mi sono messo ad analizzare i pacchetti di rete tra la mia macchina ed i servizi in questione. Durante tale analisi ho riscontrato due problemi:
- Il traffico di rete tra la mia macchina ed i servizi avveniva tramite una connessione sicura https;
- Le chiamate venivano effettuate tramite un’applicazione web che non viene tracciata di default tramite fiddler;
Entrambi i punti sono facilmente risolvibili. Per la parte https è necessario installare l’ultima versione di Fiddler (scaricabile da qui) ed attivare la relativa opzione nei suoi setting, come mostrato dagli screenshots seguenti:
Maggiori info riguardo Fiddler e https sono disponibili qui.
Per quanto riguarda invece il problema di monitorare il traffico in uscita da un’applicazione web, è sufficiente cambiare l’identity dell’application pool con cui viene eseguital’applicazione ed impostare lo stesso utente con cui gira Fiddler (quindi l’utente loggato). A questo punto come per magia verrà mostrato anche il traffico della vostra web application.
La “vicenda” si è conclusa dimostrando che i servizi non restituivano le informazioni aspettate ![]()
Usare IExceptionFilter per loggare le eccezioni.
In un post precedente (vedi qui) ho già introdotto il concetto di ActionFilter e alcune opportunità che ci offre. In questo post vorrei mostrare come realizzarne uno custom per loggare le eccezioni.
Per prima cosa è bene sapere che ogni ActionFilter deve ereditare da FilterAttribute, che è la classe base per tutti i Filter che si utilizzano in ASPNET MVC e, se si vogliono catturare tutti gli errori non gestiti, è necessario implementare anche l’interfaccia IExceptionFilter.
Lo snippet seguente mostra l’implementazione dell’ActionFilter:
public class LoggerFilterAttribute : FilterAttribute, IExceptionFilter {
readonly ILogger logger;
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Web.Mvc.FilterAttribute"/> class.
/// </summary>
public LoggerFilterAttribute ( ) {
logger = new Logger()
}
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Web.Mvc.FilterAttribute"/> class.
/// </summary>
public LoggerFilterAttribute ( ILogger logger ) {
this.logger = logger;
}
/// <summary>
/// Called when an exception occurs.
/// </summary>
/// <param name="context">The filter context.</param>
public void OnException ( ExceptionContext context ) {
logger.Error ( context.Exception.Message, context.Exception );
throw new HttpException(500,context.Exception.Message,context.Exception);
}
}
A questo punto è sufficiente decorare i nostri Controller, o ancora meglio registrare il Filter come Global per poterlo sfruttare:
[LoggerFilterAttribute()]
public class HomeController : ControllerBase {
public ActionResunt Index(){
//DO SOMETHING
}
}
Ciauz
Gestione dei DateTime ed i vari TimeZone
Posted by imperugo in Nhibernate on Monday 16 May 2011 at 9:50 AM
Tra le varie problematiche che ho incontrato nello sviluppare Dexter, ce n’è una il cui rimedio è divenuto indispensabile nella maggior parte delle applicazioni, ossia una gestione un po’ più avanzata del DateTime all’interno dell’applicazione.
Durante la migrazione tra i vari server, ho riscontrato un problema con i vari DateTime di ciascuno di essi; essendo dislocati in aree geografiche diverse, restituivano infatti valori nettamente differenti per via del fuso orario dal server vecchio a quello nuovo.
Il primo server su cui risiedeva il mio blog era su un provider il cui fuso orario era impostato su EST, che differisce di tre ore rispetto all’orario del nuovo server che è impostato sulla PST. Questa differenza ha causato un’errata visualizzazione degli orari dei post sul mio blog, che risultavano sfalzati di tre ore
Oltre a sistemare tutti i valori memorizzati nel database con una query, ho deciso di affrontare e risolvere il problema in modo da non avere una dipendenza del fuso orario nelle date memorizzate, essendo quindi libero di gestire l’output dell’ora nel TimeZone a me più congeniale.
Per prima cosa ho realizzato uno UserType per NHibernate che convertisse tutte le date in ingresso verso il databse in formato UTC e, in fase di idratazione della entity, le convertisse nel TimeZone da me configurato. Questa operazione, in codice, si traduce più o meno così:
[Serializable]
internal class DateTimeUtc : IUserType {
#region IUserType Members
/// <summary>
/// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
/// </summary>
/// <param name="x">The <see cref="System.Object"/> to compare with this instance.</param>
/// <param name="y">The y.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public new bool Equals ( object x , object y ) {
if ( ReferenceEquals ( x , y ) ) {
return true;
}
if ( x == null || y == null ) {
return false;
}
return x.Equals ( y );
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <param name="x">The x.</param>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public int GetHashCode ( object x ) {
return x == null
? typeof ( DateTime ).GetHashCode ( ) + 473
: x.GetHashCode ( );
}
/// <summary>
/// Retrieve an instance of the mapped class from a JDBC resultset.
/// Implementors should handle possibility of null values.
/// </summary>
/// <param name="rs">a IDataReader</param>
/// <param name="names">column names</param>
/// <param name="owner">the containing entity</param>
/// <returns></returns>
/// <exception cref="T:NHibernate.HibernateException">HibernateException</exception>
public object NullSafeGet ( IDataReader rs , string[] names , object owner ) {
object obj = NHibernateUtil.DateTime.NullSafeGet ( rs , names[ 0 ] );
if ( obj == null ) {
return null;
}
var dbValue = ( DateTime ) obj;
SiteConfiguration configuration = DexterContainer.Resolve <IConfigurationRepository> ( ).Configuration;
dbValue = configuration != null
? System.TimeZoneInfo.ConvertTimeFromUtc ( dbValue , configuration.TimeZone )
: dbValue.ToUniversalTime ( );
return dbValue;
}
/// <summary>
/// Write an instance of the mapped class to a prepared statement.
/// Implementors should handle possibility of null values.
/// A multi-column type should be written to parameters starting from index.
/// </summary>
/// <param name="cmd">a IDbCommand</param>
/// <param name="value">the object to write</param>
/// <param name="index">command parameter index</param>
/// <exception cref="T:NHibernate.HibernateException">HibernateException</exception>
public void NullSafeSet ( IDbCommand cmd , object value , int index ) {
if ( value == null ) {
( ( IDataParameter ) cmd.Parameters[ index ] ).Value = DBNull.Value;
}
else {
var myValue = ( DateTime ) value;
SiteConfiguration configuration = DexterContainer.Resolve<IConfigurationRepository> ( ).Configuration;
if ( configuration != null ) {
myValue = myValue.Kind == DateTimeKind.Unspecified
? System.TimeZoneInfo.ConvertTimeToUtc ( myValue , configuration.TimeZone )
: myValue.ToUniversalTime ( );
}
else {
myValue.ToUniversalTime ( );
}
( ( IDataParameter ) cmd.Parameters[ index ] ).Value = myValue;
}
}
/// <summary>
/// Return a deep copy of the persistent state, stopping at entities and at collections.
/// </summary>
/// <param name="value">generally a collection element or entity field</param>
/// <returns>a copy</returns>
public object DeepCopy ( object value ) {
return value;
}
/// <summary>
/// During merge, replace the existing (<paramref name="target"/>) value in the entity
/// we are merging to with a new (<paramref name="original"/>) value from the detached
/// entity we are merging. For immutable objects, or null values, it is safe to simply
/// return the first parameter. For mutable objects, it is safe to return a copy of the
/// first parameter. For objects with component values, it might make sense to
/// recursively replace component values.
/// </summary>
/// <param name="original">the value from the detached entity being merged</param>
/// <param name="target">the value in the managed entity</param>
/// <param name="owner">the managed entity</param>
/// <returns>the value to be merged</returns>
public object Replace ( object original , object target , object owner ) {
return original;
}
/// <summary>
/// Reconstruct an object from the cacheable representation. At the very least this
/// method should perform a deep copy if the type is mutable. (optional operation)
/// </summary>
/// <param name="cached">the object to be cached</param>
/// <param name="owner">the owner of the cached object</param>
/// <returns>
/// a reconstructed object from the cachable representation
/// </returns>
public object Assemble ( object cached , object owner ) {
return cached;
}
/// <summary>
/// Transform the object into its cacheable representation. At the very least this
/// method should perform a deep copy if the type is mutable. That may not be enough
/// for some implementations, however; for example, associations must be cached as
/// identifier values. (optional operation)
/// </summary>
/// <param name="value">the object to be cached</param>
/// <returns>a cacheable representation of the object</returns>
public object Disassemble ( object value ) {
return value;
}
/// <summary>
/// The SQL types for the columns mapped by this type.
/// </summary>
/// <value></value>
public SqlType[] SqlTypes {
get {
return new[] {
new SqlType ( DbType.DateTime )
};
}
}
/// <summary>
/// The type returned by <c>NullSafeGet()</c>
/// </summary>
/// <value></value>
public Type ReturnedType {
get { return typeof ( DateTime ); }
}
/// <summary>
/// Are objects of this type mutable?
/// </summary>
/// <value></value>
public bool IsMutable {
get { return false; }
}
#endregion
}
Una volta affrontato il problema del salvataggio della data, rimaneva soltanto quello riguardante i filtri delle query che, per i campi DateTime, dovevano effettuare una conversione in formato UTC più o meno in questo modo:
Purtroppo mi è capitato più volte di dimenticarmi di effettuare quel ToUniversalDateTime all’assegnazione del parametro di una query, con l’ovvio problema di avere risultati sballati in fase di visualizzazione.
Fortunatamente con la versione 3.2 di NHibernate è stato rivisto parzialmente il Driver di SqlServer, che ora espone un metodo "AdjustCommand” subito prima dell’ExecuteQuery. Il codice seguente mostra come effettuare automaticamente la conversione dal DateTimeKind.Local al DateTimeKind.Utc:
public class DexterSqlClientDriver : SqlClientDriver {
public override void AdjustCommand ( System.Data.IDbCommand command ) {
foreach (var parameter in command.Parameters.Cast<SqlParameter> ( ).Where ( x => x.SqlDbType == SqlDbType.DateTime && ( x.Value is DateTime ) )) {
var dateTimeValue = (( DateTime )parameter.Value).ToUniversalTime ( );
parameter.Value = dateTimeValue;
}
}
}
A questo punto, il codice di esecuzione della query si semplifica ancor di più poiché il developer non deve sapere, o ricordarsi, che il formato della data sul database è differente, in quanto la conversione avviene in automatico.
Il risultato è il seguente:
Comodo no?
Recent Comments