QuiBrowser.it runs on dexter

Print Content | More

Chi segue i commit di Dexter su codeplex, sicuramente avrà notato che il progetto non è morto, tutt’altro.

In questi giorni, oltre al solito lavoro su Dexter, ho lavorato al porting del blog di QuiBrowser che, da ieri, gira sulla “mia” piattaforma. La versione installata è ben diversa da quella utilizzata nel mio blog: di fatto l’ho praticamente “riscritta”, con conseguente ritardo (l’ennesimo) nel rilascio di una build.
Tra le novità introdotte in questa versione (di cui parlerò in seguito) c’è la skin, realizzata sfruttando le principali caratteristiche messe a disposizione dall’HTML5: canvas, tag semantici, trasparenze, ombre, font custom, etc.

Il risultato:

23-03-2011 22-34-24

 

Per chi fosse interessato all’argomento consiglio di buttarci un occhio.
Ci sono un po’ di problemini con il server (tempi di risposta alti), ma presto passerà ad Azure Open-mouthed smile


Un super mega grazie ad Alessandro che mi ha aiutato come sempre in questa folle impresa: un mito!


Dexter , HTML5 , Azure , Blog

0 comments

Web Camps 2011

Print Content | More

Il 15 marzo in Italia si terrà il Web Camps, organizzato da Microsoft Italia, al quale ho la fortuna di partecipare come speaker; nello specifico terrò due sessioni, la prima riguardante HTML5 e CSS3, la seconda un’introduzione ad Orchard, il nuovo CMS Open Source di casa Microsoft.

 logo_MicrosoftWebCamps

Per gli appassionati del web direi che è un must! Agenda ed iscrizioni sono disponibili qui


Eventi , HTML5 , CSS3

0 comments

WebCast su HTML5 e CSS3

Print Content | More

Buona visione Smile

10-02-2011 09-22-32

10-02-2011 09-24-24


Webcast

0 comments

AAA - Cercasi Dev!

Print Content | More

Recentemente sono stato contattato da due società di Bari che stanno facendo recruiting di dev su tecnologia Microsoft. I requirements sono i principali: .NET Framework, Visual Studio etc.

Chi è interessato può contattare me direttamente qui.

Ciauz


Recruiting

0 comments

Recuperare il content type

Print Content | More

Stufo dei soliti switch per recuperare il content type di un file, mi sono deciso a dare una sbirciata in rete per verificare se esistesse un qualcosa che mi potesse restituire il content type dato un file name.
Ovviamente, come quasi sempre in questi casi, qualcun’altro si è posto la mia stessa domanda ed ha trovato una soluzione a tale problema Smile.

Di fatto, nel .NET Framework è possibile utilizzare la classe Registry per andare a recuperare la nostra informazione, come mostrato dall’extension method seguente:

/// <summary>
///     Retrieve the mimetype for the specified filename.
/// </summary>
/// <param name = "fileName">Name of the file.</param>
/// <returns></returns>
public static string GetMimeType (this string fileName ) {
    string mime = "application/octetstream";
    string ext = Path.GetExtension ( fileName ).ToLower ( );
    RegistryKey rk = Registry.ClassesRoot.OpenSubKey ( ext );
    if ( rk != null && rk.GetValue ( "Content Type" ) != null ) {
        mime = rk.GetValue ( "Content Type" ).ToString ( );
    }
    return mime;
}

Ciauz

FONTE : http://petrocel.wordpress.com/2008/01/09/how-to-get-the-content-typemimetype-of-a-file-c/


Extension Methods , HttpHandler

0 comments

Controller omonimi in ASP.NET MVC

Print Content | More

Oggi mi è capitato di dover gestire una nuova problematica in un’applicazione ASP.NET MVC. Nello specifico mi trovavo nella condizione di avere due controller con lo stesso nome; il primo era all’interno della struttura principale dell’applicazione, il secondo dentro un Area di MVC.

Il problema è identificabile e risolvibile a livello di routing; di fatto se si prova a guardare i seguenti controller (dai namespace è facilmente identificabile l’area):

namespace Dexter.Web.UI.Areas.Admin.Controllers {
  public class HomeController : BackOfficeControllerBase {
    [AcceptVerbs ( HttpVerbs.Get )]
    [OutputCache ( VaryByParam = "id" , Duration = 600 )]
    public ActionResult Index ( string id ){
      return View();
    }
  }
}


namespace Dexter.Web.UI.Controllers {
  public class HomeController : BackOfficeControllerBase {
    [AcceptVerbs ( HttpVerbs.Get )]
    [OutputCache ( VaryByParam = "id" , Duration = 600 )]
    public ActionResult Index ( string id ){
      return View();
    }
  }
}

per la seguente Route:

routes.MapRoute (
    "Default" ,
    "{controller}/{action}/{id}" ,
    new {controller = "Home" , action = "Index" , id = UrlParameter.Optional}
);

ed ad associarla all’url http://www.miosito.com/Home/Index, si può capire come MVC non sia in grado di identificare correttamente quale dei due controller Home deve essere invocato per tale richiesta, e si trova “obbligato” a sollevare un’eccezione come la seguente:

Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.

The request for 'Home' has found the following matching controllers:
Dexter.Web.UI.Controller.HomeController
Dexter.Web.UI.Areas.Admin.Controllers.HomeController

Nulla di allarmante, il problema è facilmente risolvibile specificando il namespace contenente il Controller corretto nella registrazione della Route, come mostrato di seguito:

routes.MapRoute (
    "Default" ,
    "{controller}/{action}/{id}" ,
    new {controller = "Home" , action = "Index" , id = UrlParameter.Optional} ,
    new string[] {"Dexter.Web.UI.Controller"}
);

A questo punto l’engine di MVC sa quale controller invocare e può esaudire correttamente la richiesta web.


ASP.NET , MVC , Routing

0 comments

Visual Studio e le varie tipologi di progetti.

Print Content | More

In quest’ultimo periodo sto lavorando parecchio su Dexter e sto migrando parte del codice all’ultima release di ASP.NET MVC. Tra le varie branch, merge, update, etc, mi è capitato che il progetto web non fosse più “riconosciuto” da Visual Studio come un progetto MVC, con la scomoda conseguenza che i menù contestuali non mi offrivano più le funzioni di AddView, AddArea, etc.

Nulla di grave, ma avere la possibilità di aggiungere una View direttamente dal controller nell’esatta cartella (il tutto con un solo click) è piuttosto comodo.
Ovviamente il problema era sicuramente nel file .csproj, si trattava solo di capire cosa mancava per riattivare gli “aiuti” di Visual Studio per MVC.
Per comprendere cosa andare a toccare all’interno del file di progetto, ne ho creato uno nuovo da VS e sono andato a correggere a mano il file .csproj

A questo punto è entrato in gioco WinMerge, con cui sono andato a confrontare i due file e mi sono accorto che un nodo dell’xml è diverso tra i due. Nello specifico si trattava del nodo <ProjectTypeGuids> che contiene una serie di guid separati dalla virgola che hanno lo scopo di descrivere a Visual Studio la tipologia, il liguanggio e l’output del progetto.
Trattandosi la mia applicazione di un WAP (Web Application Project) fatto con ASP.NET MVC 3 e scritto in C#, il contenuto di questo tag deve essere così:

<ProjectTypeGuids>{E53F8FEA-EAE0-44A6-8774-FFD645390401};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

Per sapere il significato di ogni GUID riporto qui una tabella che ho creato dopo un po’ di ricerche in rete:

Windows (C#) {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
Windows (VB.NET) {F184B08F-C81C-45F6-A57F-5ABD9991F28F}
Windows (Visual C++) {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}
Web Application {349C5851-65DF-11DA-9384-00065B846F21}
Web Site {E24C65DC-7377-472B-9ABA-BC803B73C61A}
ASP.NET MVC 3 {E53F8FEA-EAE0-44A6-8774-FFD645390401}
WCF {3D9AD99F-2412-4246-B90B-4EAA41C64699}
WPF {60DC8134-EBA5-43B8-BCC9-BB4BC16C2548}
XNA (Windows) {6D335F3A-9D43-41b4-9D22-F6F17C4BE596}
XNA (XBox) {2DF5C3F4-5A5F-47a9-8E94-23B4456F55E2}
XNA (Zune) {D399B71A-8929-442a-A9AC-8BEC78BB2433}
Silverlight {A1591282-1198-4647-A2B1-27E5FF5F6F3B}

Come potete vedere la parte riguardante MVC è {E53F8FEA-EAE0-44A6-8774-FFD645390401}: una volta reinserito questo GUID all’interno del mio file .csproj tutto è tornato a funzionare per il meglio.

Ciauz


ASP.NET , MVC , Visual Studio , Visual Studio 2010

0 comments

Configurare Azure Tools su SQL Server

Print Content | More

Ultimamente sto lavorando parecchio con il cloud computing, ed ho avuto modo di parlarne nello specifico sia ai TechDays/WPC che in alcuni progetti interni all’azienda.

Non voglio star qui a scrivere di cosa è il cloud e quando vada scelto (magari lo farò in un post futuro), piuttosto vorrei parlare di un piccolo tip riguardante i tools di sviluppo per Windows Azure.
Di fatto, se si vuole sviluppare per questa piattaforma, è necessario scaricare (da qui) ed installare sulla propria macchina di sviluppo dei tools che permettono di “simulare” in locale l’environment che si avrà in produzione.
Senza andare troppo in profondità, ci basta sapere che i tools di Azure “wrappano” tutte le chiamate verso il client all’interno di un database Sql Server (il che è molto importante, in quanto ci permette di effettuare unit test sulle chiamate con estrema semplicità) che deve essere installato sulla macchina locale; di fatto, se non avete installato Sql sulla macchina e provate a lanciare un qualsiasi worker role o web role, riceverete dal Framework una bellissima eccezione tipo la seguente:

“Windows Azure Tools: Failed to initialize the Development Storage service. Unable to start Development Storage. Failed to start Development Storage: the SQL Server instance ‘localhost\SQLExpress’ could not be found. Please configure the SQL Server instance for Development Storage using the ‘DSInit’ utility in the Windows Azure SDK.”

Questo accade perchè l’environment locale di Azure cerca di accedere all’istanza di default di SQLExpress che, come nel mio caso, potrebbe non essere installata sulla macchina.

Per chi, come me, ha l’esigenza di sviluppare su Windows Azure Platform e non vuole installare SQL Express sulla propria macchina perchè ha già installato una versione differente di SQL (2008 R2 Developer Edition nel mio caso), può tranquillamente farlo eseguendo con privilegi amministrativi “Windows Azure SDK Command Prompt” (lo trovate all’interno del menu programmi), digitando il seguente comando:

DSInit /sqlInstance:. /forceCreate

Ovviamente se si ha un nome d’istanza differente si può sostituire il “.”, che equivale a localhost, con il proprio nome, impostato durante l’installazione di SQL Server.
A questo punto verrà creato un database con tutto il necessario per poter utilizzare i tools di Azure sulla propria macchina, senza dover passare per SQL Express.

Azure rulez!


Azure , Sql , Configurazione

0 comments

Gestione dello schema database tramite NHibernate

Print Content | More

Dopo mesi di assenza, finalmente trovo di nuovo il tempo di “bloggare”, e la mia intenzione, questa volta, è di parlare di NHibernate (fresco di GA), di cui sto facendo un uso abbastanza “spinto” in un progetto.
Nello specifico ho avuto l’esigenza di dover gestire con NHibernate la creazione del database - e fin qui nulla di speciale - ma con l’obbligo di creare anche delle funzioni SQL per i vari databases supportati.

Uno dei principali requirements dell’applicazione è il supporto a ben tre versioni differenti di Sql Server più due di Oracle; per come sono strutturati il dominio ed il database, per poter effettuare determinate queries ho dovuto far uso di alcune funzioni lato database, in quanto non riproducibili tramite Object Query Language.

Fortunatamente NHibernate permette di utilizzare delle funzioni SQL Custom all’interno delle proprie queries sia se si fa uso di HQL, sia di Criteria API che di Linq.
Il loro utilizzo è veramente semplice; per prima cosa è necessario creare un proprio dialect, che erediti da quello più adatto al nostro database, e registrare le funzioni all’interno del suo costruttore, come mostrato dal codice seguente:

internal class SqlServer2008Dialect : MsSql2008Dialect {
    
    /// <summary>
    /// Initializes a new instance of the <see cref="SqlServer2008Dialect"/> class.
    /// </summary>
    public SqlServer2008Dialect ( ) {

        string monthFunction = string.Format("{0}.IsMonth", NHConfiguration.Instance.DatabaseSchema);
        string yearFunction = string.Format("{0}.IsYear", NHConfiguration.Instance.DatabaseSchema);

        base.RegisterFunction ( "IsMonth" , new StandardSQLFunction ( monthFunction , NHibernateUtil.Int32 ) );
        base.RegisterFunction ( "IsYear" , new StandardSQLFunction ( yearFunction , NHibernateUtil.Int32 ) );
    }
}

A questo punto possiamo utilizzare la funzione all’interno delle nostre query in maniera molto semplice:

Session.CreateQuery ( "from Article p where IsMonth( p.PublishDate ) = :month and IsYear( p.PublishDate ) = :year" )
    .SetParameter("month",month)
    .SetParameter("year", year)
    .SetFirstResult(pageIndex * pageSize)
    .SetFirstResult(pageIndex * pageSize)
    .SetMaxResults(pageSize)
    .SetReadOnly(!enableTracking)
    .List<Article>();

Come già detto in apertura, una delle caratteristiche dell’applicazione è la creazione ed aggiornamento del database tramite Nhibernate, il che si traduce nell’aggiungere gli scripts di creazione delle funzioni SQL lato codice; tuttavia, essendo lo schema del database impostato lato configurazione, è necessario manipolare gli scripts prima che questi siano “dati in pasto” a NHibernate per la creazione dello schema.

Gli steps da seguire sono pochi e piuttosto semplici, a dimostrazione dell’ottima struttura e flessibilità offerta da NHibernate. Per prima cosa è necessario preparare gli scripts di creazione e cancellazione delle funzioni SQL, tipo la seguente:

--SCRIPT DI CREAZIONE

CREATE FUNCTION [IsMonth]
       (
@date datetime
       )
       RETURNS int

       WITH EXECUTE AS CALLER
AS
BEGIN
  IF @date IS NULL RETURN 0
    RETURN Datepart(mm,@date)
END

GO

CREATE FUNCTION [IsYear]
(
  @date datetime
)
RETURNS int

WITH EXECUTE AS CALLER
  AS
  BEGIN
    IF @date IS NULL RETURN 0
      RETURN Datepart(yy,@date)
  END

GO

--SCRIPT DI CANCELLAZIONE

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[IsMonth]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
    DROP FUNCTION [IsMonth]
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[IsYear]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT'))
    DROP FUNCTION [IsYear]
GO

È importante rimuovere gli schema del database tipo “dbo” dallo script, in modo da poter aggiungere lo schema desiderato a runtime.

A questo punto va preparato un file XML di mapping che conterrà questi scripts, come mostrato di seguito:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <database-object>
        <create>
      <!-- Inserire qui gli script di creazione -->
        </create>
        <drop>
      <!-- Inserire qui gli script di cancellazione -->
        </drop>
    </database-object>
</hibernate-mapping>

Da qui in poi è sufficiente eseguire una Regular Expression per poter aggiungere lo schema proveniente dal nostro file di configurazione e, solo a questo punto, è possibile passare a NHibernate il codice di XML contenente gli scripts di creazione e cancellazione delle funzioni.

db.Dialect<SqlServer2008Dialect>();
db.Driver<SqlClientDriver>();
databaseObjects = Resources.DatabaseObjects.MsSQL2008;

if (databaseObjects != null)
    databaseObjects = Regex.Replace(databaseObjects, @"(\[.*\])", string.Format("[{0}].$1", dbSchema));

if (!string.IsNullOrEmpty(databaseObjects)){
    //configuration è la configuration di NHibernate
    configuration.AddXmlString ( databaseObjects);
}

Anche in scenari in cui non si abbia l’esigenza di dover supportare diverse tipologie di database, consiglio sempre, quando possibile, di lasciare l’onere della creazionde del database all’ORM, in modo da poter creare e cancellare lo schema del database durante l’esecuzione dei nostri integration tests con molta semplicitià.

Ciauz


Nhibernate , Sql , Oracle , ORM , Database

0 comments

23, 24 e 25 novembre TechDays-WPC!

Print Content | More

Attendee02In estremo ritardo (causa “troppissimo” lavoro) volevo postare alcune info su un mio prossimo speech. Infatti tra poco meno di due settimane ci saranno i TechDays, ed io avrò la fortuna di partecipare come speaker.
Per chi non lo sapesse, TechDays-WPC è sicuramente tra le più importanti conferenze tecniche disponibili in Italia; è una conferenza organizzata da Microsoft e OverNet Education, e si terrà nei giorni 23, 24 e 25 novembre qui a Milano.

Agenda, prezzi, orario ed informazioni sono disponibili sul sito ufficiale dell’evento. Per chi verrà a vedermi parlerò di Windows Azure e delle problematiche riguardanti la migrazione da On Premise a On The Cloud.

Vi aspetto!


Eventi , TechDays , WPC , Azure

0 comments