ASP.NET MVC 2 RTM ed un po’ di MVC 3 :)
Finalmente è stata rilasciata la versione definitiva di ASP.NET MVC 2. Il download è disponibile qui e soltanto per Visual Studio 2008 (di fatto Visual Studio 2010 integrerà già in sé la versione 2 di ASP.NET MVC).
Ovviamente non ci sono novità di rilievo in quanto la RC2 era già features complete. Ciò su cui si è sicuramente lavorato sono le performances, la stabilità ed un po’ di bugfixinig.
Ovviamente è appena stata rilasciata la versione 2 e già si parla della versione 3, infatti a questo indirizzo potete trovare la roadmap della prossima release, che riporto qui di seguito:
Now that ASP.NET MVC 2 is released, it's time to start planning for ASP.NET MVC 3. This roadmap will be updated with more information as we get further in our planning process.
Here is a list of some of the high-level areas of focus we're looking at.
- Productivity - ASP.NET MVC 3 should provide ways to make application developers more productive when building web applications.
- Tasked based helpers - These helpers focus on tasks that commonly come up when building web applications such as adding a CAPTCHA to a site or providing a sortable, pageable grid of data.
- Validation Improvements - Support for more validation attributes such as the new ones introduced in ASP.NET 4 as well as possibly a few new ones such as an email validation attribute.
- View Engine Options - We're experimenting with a new streamlined view engine syntax as well as making it easier to pull in community view engines such as Spark into a project.
- Command line tools - As we add new tooling for ASP.NET MVC to Visual Studio, we will look at providing command line alternatives for the same functionality
- Ajax - Modern applications make use of Ajax to provide a rich experience for their users. ASP.NET MVC 3 should make building such applications much easier.
- More Ajax helpers - New Ajax helpers may leverage libraries such as jQuery UI to provide widgets such as a calendar date picker, autocomplete, etc.
- Multiple Partial Updates - The existing Ajax helpers, such as Ajax.BeginForm and Ajax.ActionLink, only update one element in the page when receiving a partial view from an action method. Support for multiple partial updates would allow the Ajax helpers to receive multiple partial views and update multiple sections of the page with those views.
- Client Templates Support - Client templates enable you to format and display a single data item or set of data items by using a fragment of HTML. ASP.NET MVC 3 may provide the ability to connect client templates easily with an action method which returns and receives JSON data.
- Architecture - ASP.NET MVC 3 should contain architectural improvements which provide benefits such as improved extensibility that enables developers to more easily bend the framework to their will.
- Dependency Injection at all levels - We're looking at opening up more seams for applying the dependency injection when instantiating components of the framework. This would allow developers to hook into the creation of models during model binding, action filters, etc.
- MEF Controller Factory - MEF is a new library in .NET for building applications that can be incrementally extended without requiring modification. Enabling MEF by default within the default controller factory would allow for extensibility scenarios out of the box, while still allowing for 3rd party dependency injection frameworks to be used as alternatives to MEF.
- Application scaffolding - Scaffolding allows for quickly implementing simple Create, Read, Update, Delete pages against a model which provide a nice starting point for quickly getting data into an application during development.
- Performance - As always, we're looking at ways to make ASP.NET MVC 3 blazingly fast.
- Improved Caching Support - Enable caching of an child action when called via the RenderAction method. Also looking at donut caching and donut hole caching.
- More Control Over Session - Support for granular session state as well as turning session state on and off on a per action/controller basis.
Buon download.
Log4Net ed un buon logging
Il logging è una parte fondamentale dell’applicazione; se implementato correttamente ed inserito nei posti giusti può salvare da lunghi down applicativi e molto altro ancora.
Pur potendo una persona essere bravissima a scrivere del codice, purtroppo (o per fortuna, dipende dai punti di vista) la stabilità e le problematiche dell’applicazione non dipendono soltanto dallo sviluppatore. Di fatto può cadere la connessione verso il database, possono esserci problemi di rete verso la SAN, un update può destabilizzare l’applicativo, ma per l’utente finale la colpa sarà sempre dell’applicazione; del resto è un punto di vista comprensibile, in quanto ciò che interessa è usare l’applicazione e non le eventuali problematiche esterne che ne possono causare un crash.
Appreso il fatto che, qualsiasi sia il problema, sta a noi trovarlo, passando poi la palla a chi di dovere (sistemista, tecnico di rete, etc), è comunque utile sapere che proprio in questi casi il logging può aiutare a ridurre al minimo il tempo necessario per poter identificare un bug applicativo e/o un problema di infrastruttura.
Purtroppo io sono abituato ad aggiungere al Dictionary Data delle eccezioni alcune informazioni riguardo al contenuto della chiamata, come dei parametri o delle variabili calcolate (vedi qui); inoltre, per tutte le applicazioni web, mi piace essere a conoscenza dell’esatta richiesta che è stata effettuata, quindi, per entrare un po’ più nel dettaglio, per ogni errore voglio sapere:
- Url della richiesta;
- RawURL nel caso esista un sistema di routing o rewriting;
- UrlReferrer, se esiste;
- UserAgent, se esiste;
- UserHostName;
- Tutte le ServerVariables;
- Tutti i valori provenienti dalla Form;
- ServerName, nel caso mi trovi in un sistema di load balancing;
- ThreadLanguage;
Ovviamente tutte queste informazioni sono prensenti nel HttpContext, ma inserirle a mano ogni volta non è il massimo della comodità, così come non lo è crearsi una classe di helper perchè spesso il Logger può essere instanziato tramite un Framework di Inversion Of Control come Castle (che offre già una serie di facilities a riguardo). Per concludere, il Logger deve aggiungere da solo tutto ciò che è ripetitivo.
Purtroppo il Logger di default non salva queste informazioni (né le informazioni aggiuntive della collection data, né il contesto web), ma è comunque possibile realizzare un layout base che aggiunga all’output del Logger le informazioni necessarie.
Personalmente utilizzo come output un file xml (il discorso rimane lo stesso anche se si opta per un’altra soluzione) perchè è compatibile con il mio log viewer preferito, Log4View, che offre moltissime opzioni, tra cui la possibilità di effettuare logging tramite nettcp su un client remoto.
Chi segue il codice di Dexter può già trovare questa implementazione - che qui riporto solo per le parti relative all’argomento - al suo interno:
protected override void FormatXml(XmlWriter writer, LoggingEvent loggingEvent)
{
if (DexterEnvironment.Context.IsSafe)
{
try
{
loggingEvent.Properties["Url"] = DexterEnvironment.Context.CurrentRequestUri;
loggingEvent.Properties["UrlReferrer"] = DexterEnvironment.Context.CurrentUrlReferrer;
loggingEvent.Properties["UserAgent"] = DexterEnvironment.Context.CurrentUserAgent;
loggingEvent.Properties["UserHostName"] = DexterEnvironment.Context.CurrentUserHostName;
loggingEvent.Properties["ServerVariables"] = ServerVariables(DexterEnvironment.Context.CurrentServerVariables);
loggingEvent.Properties["Form"] = ServerVariables(DexterEnvironment.Context.CurrentForm);
loggingEvent.Properties["RawURL"] = DexterEnvironment.Context.CurrentRawUrl;//ctx.Request.RawUrl;
loggingEvent.Properties["ServerName"] = DexterEnvironment.Context.CurrentServerMachineName;
loggingEvent.Properties["ThreadLanguage"] = Thread.CurrentThread.CurrentCulture.DisplayName;
}
catch
{
//needed because the logging called from the appliction start che throw a new exception
//more info here:http://mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx
}
}
writer.WriteStartElement(mElmEvent);
writer.WriteAttributeString("logger", loggingEvent.LoggerName);
writer.WriteAttributeString("timestamp", XmlConvert.ToString(loggingEvent.TimeStamp, XmlDateTimeSerializationMode.Local));
writer.WriteAttributeString("level", loggingEvent.Level.DisplayName);
writer.WriteAttributeString("thread", loggingEvent.ThreadName);
if (!string.IsNullOrEmpty(loggingEvent.Domain))
writer.WriteAttributeString("domain", loggingEvent.Domain);
if (!string.IsNullOrEmpty(loggingEvent.Identity))
writer.WriteAttributeString("identity", loggingEvent.Identity);
if (!string.IsNullOrEmpty(loggingEvent.UserName))
writer.WriteAttributeString("username", loggingEvent.UserName);
writer.WriteStartElement(mElmMessage);
if (!Base64EncodeMessage)
Transform.WriteEscapedXmlString(writer, loggingEvent.RenderedMessage, InvalidCharReplacement);
else
{
byte[] bytes = Encoding.UTF8.GetBytes(loggingEvent.RenderedMessage);
string textData = Convert.ToBase64String(bytes, 0, bytes.Length);
Transform.WriteEscapedXmlString(writer, textData, InvalidCharReplacement);
}
writer.WriteEndElement();
PropertiesDictionary properties = loggingEvent.GetProperties();
if (properties.Count > 0)
{
writer.WriteStartElement(mElmProperties);
foreach (DictionaryEntry entry in properties)
{
writer.WriteStartElement(mElmData);
writer.WriteAttributeString("name", Transform.MaskXmlInvalidCharacters((string) entry.Key, InvalidCharReplacement));
string str2;
if (!Base64EncodeProperties)
str2 = Transform.MaskXmlInvalidCharacters(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value), InvalidCharReplacement);
else
{
byte[] inArray = Encoding.UTF8.GetBytes(loggingEvent.Repository.RendererMap.FindAndRender(entry.Value));
str2 = Convert.ToBase64String(inArray, 0, inArray.Length);
}
writer.WriteAttributeString("value", str2);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
if (loggingEvent.ExceptionObject != null)
{
StringBuilder exceptionString = new StringBuilder();
exceptionString.Append(loggingEvent.ExceptionObject);
exceptionString.Append(Environment.NewLine);
foreach (DictionaryEntry de in loggingEvent.ExceptionObject.Data)
{
exceptionString.Append(de.Key.ToString());
exceptionString.Append(": ");
exceptionString.Append(de.Value.ToString());
exceptionString.Append(Environment.NewLine);
}
if ((exceptionString.Length > 0))
{
writer.WriteStartElement(mElmException);
Transform.WriteEscapedXmlString(writer, exceptionString.ToString(), InvalidCharReplacement);
writer.WriteEndElement();
}
}
if (LocationInfo)
{
LocationInfo locationInformation = loggingEvent.LocationInformation;
writer.WriteStartElement(mElmLocation);
writer.WriteAttributeString("class", locationInformation.ClassName);
writer.WriteAttributeString("method", locationInformation.MethodName);
writer.WriteAttributeString("file", locationInformation.FileName);
writer.WriteAttributeString("line", locationInformation.LineNumber);
writer.WriteEndElement();
}
writer.WriteEndElement();
}
Come potete vedere tutto si svolge nel metodo FormatXml, dove è possibile aggiungere, rimuovere e leggere alcune informazioni. Nella prima parte vado ad inserire le informazioni inerenti il contesto web, quindi la url richiesta, il rawurl, useragent, etc, mentre più avanti renderizzo tutte le informazioni del Dictionary Data dell’eccezione.
Per poter utilizzare questa customizzazione è sufficiente specificare nel file di log4net la classe per il rendering delle informazioni, come mostrato di seguito:
<appender name="NHibernateFileLog" type="log4net.Appender.RollingFileAppender">
<file value="Logs/nHibernate.txt" />
<maximumFileSize value="1000KB" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="5" />
<layout type="Dexter.Shared.Log.Log4Net.XmlLayout">
</layout>
</appender>
Chi è interessato all’implementazione completa del XmlLayout può guardare qui.
Ciauz
Autoconfigurare Windows Live Writer
Quando il tempo necessario richiesto a fornire una determinata informazione eguaglia il tempo necessario allo sviluppo di un sistema di risposta automatico, forse è il caso di fare qualcosa :).
Da tale situazione è nata l’esigenza di creare un sistema che configurasse in automatico Windows Live Writer.
In quest’ ultimo periodo, insieme agli altri ragazzi, abbiamo rilasciato diverse versioni di Dexter ed abbiamo lavorato in particolar modo con l’integrazione su Windows Live Writer. Questo ha causato diversi reset della configurazione di WLW da parte di tutti gli utilizzatori (in realtà ora sono solo i beta tester) che, giustamente, mi chiedevano quale API Dexter implementasse e quale fosse la sua url.
Da qui è nata la decisione di creare un qualcosa che fornisse automaticamente a WLW le informazioni necessarie per autoconfigurarsi.
Grazie ad una dritta del buon Alessandro ho scoperto che è possibile fare ciò tramite un file RSD (Really Simple Discoverability 1.0), che non fa altro che esporre le informazioni necessarie dei providers implementati tramite una struttura xml.
La struttura seguente mostra il file del mio blog:
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
<service>
<engineName>Dexter Blog Engine</engineName>
<engineLink>http://dexterblogengine.codeplex.com/</engineLink>
<homePageLink>http://tostring.it/</homePageLink>
<apis>
<api name="MetaWeblog" blogID="1" preferred="false" apiLink="http://tostring.it/metaweblog.axd" />
</apis>
</service>
</rsd>
Come potete vedere è tutto piuttosto semplice, l’unica nota (oltre al dexter blog engine :P) è il nodo APIs, dove è possibile specificare le varie API esposte dal blog engine (nel mio caso solo i metaweblog API).
Nella home page del sito basta inserire il seguente tag ed il gioco è fatto:
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://tostring.it/MetaWeblogRsd.axd" />
Per quanto riguarda WLW, basta configurarlo specificando la Home Page: lui effettuerà il parser del markup in ricerca dell’apposito tag e si autoconfigurerà.
Di Seguito alcuni screenshots sulla procedura di configurazione
Enjoy your favorite blog engine (dexter)
Ciauz
Verificare se l’applicazione Silverlight in esecuzione è in FullTrust
Posted by imperugo in Silverlight on Tuesday 02 March 2010 at 9:00 AM
Silverlight 4 ha introdotto la possibilità di eseguire operazioni in OutOfBrowser anche in FullTrustMode. Inutile dire che questa è una delle features più interessanti della prossima release di SIlverlight, in quanto ci permette di poter accedere a risorse precedentemente non accessibili come Fotocamere, Hard Drives, Office Documents, etc.
Ovviamente però, oltre a specificare che l’applicazione richiede permessi elevati, è necessario che l’utente autorizzi l’applicazione ad eseguire operazioni anche fuori dalla propria sandbox. Dato che non c’è certezza che l’utente approvi o no tali operazioni è sicuaramente utile capire da codice se ciò è avvenuto e, nel caso, cambiare il comportamento dell’applicazione e/o gestirne eventuali errori.
Come prima cosa è necessario specificare che l’applicazione richiede permessi elevati; questo è possibile dalla finestra delle proprietà del progetto, come mostrato dallo screenshot seguente:
Per la parte codice ci basta verificare tramite l’apposità proprietà se l’utente ha acconsentito il FullTrust mode, come mostrato nello snippet seguente:
if(!App.Current.HasElevatedPermissions)
MessageBox.Show("You have to accept the Full Trust Mode!");
Ciauz
Installare un’applicazione Silverlight sul client via C#
Posted by imperugo in Silverlight on Monday 01 March 2010 at 9:00 AM
Nel post precedente avevo mostrato come verificare se l’applicaizone Silverlight fosse installata o meno sul client. L’idea di questo post è di mostrare come installare l’applicazione tramite un pulsante custom presente all’interno della pagina ed eseguire la procedura di installazione via C#.
Lo snippet seguente mostra l’evento OnClick del button per l’installazione:
private void InstallButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
if (!App.Current.IsRunningOutOfBrowser && App.Current.InstallState == InstallState.NotInstalled)
{
App.Current.Install();
}
}
Come avrete potuto notare, fin’ora tutte le informazioni necessarie per poter lavorare sono state esposte tramite la classe System.Windows.Application; grazie a quest’ultima, nei prossimi post si vedrà come verificare se l’applicazione è in esecuzione in fulltrust mode e, nel caso ne esista una più recente, come aggiornarla.
Ciauz
Ma dove sono finito? al Summit :D
Avevo annunciato una serie di posts che affrontavano un po’ la vita OutOfBrowser di un’applicazione sviluppata con Silverlight 4 ma poi, proprio quando la cosa si faceva più interessante, sono sparito.
Per vari motivi, e devo dire alcuni anche piacevoli, ho dovuto trascurare il blog. Un po’ perchè da questa settimana non sono più in MTV (dove ho passato più di tre anni bellissimi) e mi trovo a lavorare con quel “matto” di Mauro in Gaia, ed un po’ perchè sono stato all’MVP Summit in Microsoft, a Seattle.
Devo dire che quest’ultima è stata un’esperienza stupenda: girare per il Campus, conoscere Scott Guthrie, parlare via Twitter con Scott Hanselman mentre tiene una sessione…è stato emozionante. In più ho avuto l’occasione di conoscere di persona alcuni italiani che lavorano al campus, nello specifico Vittorio, Enzo (aka paperino) e Giorgio, che mi hanno offerto anche il pranzo e sono stati gentilissimi.
Putroppo non posso raccontare molto del Summit (è tutto sotto NDA), ma posso solo dire che l’esperienza è stata sopra le aspettative e che tutti gli Italians Boys (Raf, Alessandro, Alead, Janky, Davide Mauri, Andrea, Davide Zordan, Giorgio, Leone, Valter ed il mio super roommate Gian Maria) sono stati mitici.
Sotto Alcune foto.
Stay tuned!
ASP.NET MVC 2 RC2 – ci siamo quasi.
Causa cambio di lavoro, la scaletta dei posts si è incasinata ed alcune info (come questa) arrivano con alcuni giorni di ritardo; comunque sia Scott Guthrie, tramite il suo blog, ha annunciato il rilascio di ASP.NET MVC 2 RC2.
Essendo in dirittura di arrivo non ci sono grandi novità, ma più che altro bugfixing.
Di seguito i principali cambiamenti:
- Nuovo modello di validazione client side che, a differenza del precedente, non ha il compito di validare soltanto i dati di input provenienti dalla form, ma l’intero model;
- Nuovi helper strongly-typed con supporto alle lambda expression es: Html.EditorFor(m=>m.Orders[i]);
- Un nuovo template per gli editor Html.EditorFor() e Html.DisplayFor();
- L’Accountcontroller inserito nel template di default è stato semplificato;
- Inserita la nuova versione della libreria jQuery 1.4.1;
Come potete vedere le novità non sono numerose (l’elenco completo ed il download sono disponibili qui); la cosa sicuramente interessante è il performance tuning svolto in questa release, che dovrebbe portare ad un sensibile aumento delle prestazioni.
Al momento ASP.NET MVC 2 è compatibile soltanto con Visual Studio 2008 ma, con l’imminente uscita della RC di Visual Studio 2010, sarà possibile utilizzare questa release di MVC senza download aggiuntivi; di fatto Visual Studio 2010 RC avrà incluso ASP.NET MVC 2 RC2.
Ciauz
Verificare se un’applicazione Silverlight è installata sul client
Posted by imperugo in Silverlight on Wednesday 03 February 2010 at 9:00 AM
Continuando il percorso iniziato nel post precedente, oggi vorrei affrontare la parte di setup di un’applicazione Silverlight.
L’installazione può essere effettuata in due modi:
- Menu contestuale di Silverlight;
- Tramite C#;
Qualsiasi approccio si scelga è sempre necessario specificare che il progetto può essere installato sul client (di default le applicazioni Silverlight non posso essere installate sul client). Per far ciò ci basta accedere alle proprietà del progetto (tasto destro sul progetto –> proprietà) ed abilitare la modalità OutOfBrowser, come mostrato dallo screenshot seguente:
Come in ogni setup che si rispetti, prima è necessario verificare che l’applicazione interessata non sia già installata sul client, e questo è fattibile tramite l’apposita proprietà InstallState della classe application, come mostrato di seguito:
if(App.Current.InstallState == InstallState.Installed)
//TODO:Installed
else
//TODO:NotInstalled
Nel prossimo post vedremo cosa scrivere nei TODO per installare l’applicazione sul client tramite c#.
Stay tuned.
Un’interessare feature di Chrome
Non so come faccia, ma il fatto che Google Chrome riesca ad effettuare ricerche all’interno di un sito, sfruttando l’engine di ricerca presente all’interno del sito stesso e non Google search engine, è sicuramente una bella feature!
Un’altra cosa interessante è che in Dexter non ho fatto assolutamente nulla per dire a Chrome come effettuare le ricerche :).
Per provare basta fare: Dominio + Tab + Parola da cercare.
No Bad!




Recent Comments