eventi comments edit

Sicuramente è meno conosciuta rispetto alle più famose PDC o TechEd, ma non di livello inferiore; infatti per chi è appassionato di architettura e metodologie può incontrare nomi di tutto rispetto come i seguenti:

QCon è una conferenza che si tiene a San Francisco questo novembre, è organizzata interamente dalle community per le community; l’agenda  è ricchissima e tratta argomenti sicuramente interessanti per Technical Team Leader, Architects e Project Managers.

Per chi è interessato ed ha la fortuna di andare, trova maggiori info può trovarle qui.

asp.net comments edit

Mentre pianificavo il deploy di una nuova versione di Dexter, mi è venuto in mente di realizzare un HttpModule che bloccasse l’accesso al sito a tutti clients non provenienti da un determinanto indirizzo IP, reindirizzandoli verso una pagina temporanea che comunicava all’utente che era in corso un aggiornamento.

Fin qui nulla di particolare, un semplice HttpModule che  verifica IPAddress del client e, nel caso questo non sia presente nella “white list”, effettua un semplice redirect.

Ma cosa accade nel caso in cui un crawler di un search engine passi in quel determinato momento?

Una buona soluzione è quella di comunicare al bot che il sito non è momentaneamente disponibile e di rimandare la fase di crawling.

Per far ciò una possibile soluzione consiste nell’effettuare il redirect di ogni pagina verso un’altra, ed impostare uno status code differente, così che il search engine non sostituisca nell’indice il contenuto della pagina richiesta con quello della pagina temporanea.

Ma quale status code è più adatto a questo tipo di operazione?

Leggendo da W3C, un possibile status code sarebbe il “503 Service Unavailable”, ma questo non è customizzabile come spiegato qui:

The 503 error cannot be customized because they are handled in the kernel mode by HTTP.sys. This means that user-mode routines cannot be run.

Una soluzione alternativa è effettuare un “302 Found” ad una pagina html custom, che verrà esclusa dall’indicizzazione tramite l’apposito file Robots.txt.

Il redirect con status code 302 indica al client che il contenuto è stato spostato solo temporaneamente verso il nuovo indirizzo, e che successivamente potrà trovarlo nuovamente al vecchio url.

Questo permette di reindirizzare il client verso una pagina esclusa dall’indicizzazione.

Di seguito potete trovare il codice e l’apposita area di configurazione del HttpModule.

public class MaintenanceModule : IHttpModule
{
    #region IHttpModule Members

    public void Dispose()
    {
    }

    public void Init(HttpApplication context)
    {
        if (MaintenanceConfiguration.Instance.EnableMaintenance)
            context.BeginRequest += context_BeginRequest;
    }

    #endregion

    private void context_BeginRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;

        if (context.Request.Url.AbsolutePath == MaintenanceConfiguration.Instance.AbsolutePagePath)
            return;

        if (MaintenanceConfiguration.Instance.AllowedIP.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Contains(context.Request.UserHostAddress))
            return;

        context.Response.StatusCode = 302;
        context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        context.Response.AddHeader("Location", MaintenanceConfiguration.Instance.AbsolutePagePath);
    }
}

 

/// <summary>
/// Maintenance Configuration class.
/// </summary>
public static class MaintenanceConfiguration
{
    private static readonly MaintenanceConfigurationSection section;

    /// <summary>
    /// Initializes the <see cref="MaintenanceConfiguration"/> class.
    /// </summary>
    static MaintenanceConfiguration()
    {
        section = ConfigurationManager.GetSection("dexter.maintenance.configurationSection") as MaintenanceConfigurationSection;

        if (section == null)
            throw new MaintenanceSettingException("Maintenance section not found in the configuration file.");
    }

    /// <summary>
    /// Gets the instance of MaintenanceConfigurationSection class.
    /// </summary>
    /// <value>The instance.</value>
    public static MaintenanceConfigurationSection Instance
    {
        get { return section; }
    }
}

/// <summary>
/// Log Configuration Section class.
/// </summary>
public sealed class MaintenanceConfigurationSection : ConfigurationSection
{
    [ConfigurationProperty("enableMaintenance", DefaultValue = false, IsRequired = true)]
    public bool EnableMaintenance
    {
        get { return (bool) this["enableMaintenance"]; }
        set { this["enableMaintenance"] = value; }
    }

    [ConfigurationProperty("allowedIP", IsRequired = true)]
    public string AllowedIP
    {
        get { return (string) this["allowedIP"]; }
        set { this["allowedIP"] = value; }
    }

    [ConfigurationProperty("absolutePagePath", IsRequired = true)]
    public string AbsolutePagePath
    {
        get { return (string) this["absolutePagePath"]; }
        set { this["absolutePagePath"] = value; }
    }
}

public class MaintenanceSettingException : Exception
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MaintenanceSettingException"/> class.
    /// </summary>
    /// <param name="message">The message.</param>
    public MaintenanceSettingException(string message) : base(message)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="MaintenanceSettingException"/> class.
    /// </summary>
    /// <param name="message">The message.</param>
    /// <param name="innerException">The inner exception.</param>
    public MaintenanceSettingException(string message, Exception innerException) : base(message, innerException)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="MaintenanceSettingException"/> class.
    /// </summary>
    /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
    /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
    /// <exception cref="T:System.ArgumentNullException">
    /// The <paramref name="info"/> parameter is null.
    /// </exception>
    /// <exception cref="T:System.Runtime.Serialization.SerializationException">
    /// The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0).
    /// </exception>
    public MaintenanceSettingException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}
<dexter.maintenance.configurationSection 
            enableMaintenance="true" 
            allowedIP="127.0.0.1" 
            absolutePagePath="/Maintenance.aspx" />

Ciauz

asp.net comments edit

Molte persone mi hanno chiesto quale server utilizzo per hostare il mio blog realizzato in MVC.
In realtà, per hostare un’applicazione basata sul Framework ASP.NET MVC non è necessario aver installato quest’ultimo sul web server: ma basta avere il .NET Framework 3.5 SP1 e copiare le DLL di ASP.NET MVC (System.Web.Mvc, System.Web.Routing, System.Web.Abstractions) nell’apposita folder Bin, come spiegato dal PM di MVC Phil Haack.

Un’altra cosa necessaria è configurare correttamente IIS per sfruttare il Routing introdotto con la SP1 del .NET Framework 3.5.

Di seguito riporto una serie di link che spiegano come effettuare il deploy e la configurazione di ASP.NET MVC.

  • Deploy di un’applicazione MVC link.
  • Configurare IIS6 per MVC link.
  • Configurare IIS7 per MVC link.

Ciauz

various comments edit

Come già detto in passato, Dexter è un blog engine sviluppato interamente in ASP.NET MVC, NHibernate e con altre caratteristiche interessanti che trovate elencate qui.

È un po’ che ci sto lavorando sopra, ed è quasi pronta una versione accettabile che presto aprirà i battenti su Codeplex a tutti gli interessati.
Proprio in questo weekend, insieme a Salvo (anche lui sviluppatore di Dexter), ho caricato una nuova build sul blog, con un ottimo bugfixing ed alcune features, come il ReCaptcha, Castle e xVal  per la validazione client-side, ecc.
Proprio quest’ultimo ha qualche “problemino” che stiamo cercando di risolvere, oltre al backoffice in cui mancano proprio delle sezioni.

L’idea è di riuscire a pubblicare una versione funzionante di Dexter su Codeplex per fine mese, ma più probabilmente questo avverrà a settembre.
Ovviamente ringrazio tutte le persone che mi hanno segnalato problemi ed aspetto sempre feedback.

Ciauz

orm comments edit

Forse sarà una settimana intensa di RTM (Release to Manufacturing), ma intanto godiamoci la version 2.1 di NHibernate appena annunciata da Ayende qui.

Come detto da lui è consigliato fare l’upgrade alla nuova versione che corregge numerosi Bug.

Il download lo trovate qui.

Enjoy.

.net comments edit

Segnalo una serie di interessantissimi webcast sulle problematiche di utilizzo di WCF in applicazioni WPF di Michele Leroux Bustamante, autrice di diversi libri su Windows Communication Foundation e sul .NET Framework 3.5, come Learning WCF.
Oltre ad essere dei bellissimi webcast, in quanto Michelle è veramente brava nello spiegare le problematiche e come affrontarle, possono risultare molto utili anche per chi non si trovi a sviluppare applicazioni WPF ma applicazioni web.

Personalmente ritengo molto interessante il webcast sul “Proxy Life Time” ed “Exception Handling Proxy”.

L’elenco completo dei webcast ed il materiale sono disponibili qui.

various comments edit

Apprendo dal blog di Janky, che sono usciti i prezzi ufficiali per la piattaforma Azure di Microsoft (Windows Azure, SQL Azure e dei .NET Services).
più in dettaglio:

Windows Azure:
Compute @ $0.12 / hour
Storage @ $0.15 / GB stored
Storage Transactions @ $0.01 / 10K

SQL Azure:
Web Edition – Up to 1 GB relational database @ $9.99
Business Edition – Up to 10 GB relational database @ $99.99

.NET Services:
Messages @ $0.15/100K message operations , including Service Bus messages and Access Control tokens.

Bandwidth across all three services will be charged at $0.10 in / $0.15 out / GB.

Altre info qui e qui.

Ciauz