Come ben sappiamo, in linea generale una action di ASP.NET MVC può accettare qualsiasi tipo di parametro. Per esempio, nel caso in cui dobbiamo gestire una richiesta in cui ci viene fornito un'intervallo di date, è assolutamente possibile scrivere un metodo di questo tipo:
public ActionResult Search(DateTime from, DateTime to) { // .. codice qui .. }
E' poi compito del framework, e nello specifico dell'accoppiata value provider e model binder, trasformare il dato proveniente dal browser nei due oggetti DateTime; ciò avviene recuperando le informazioni dal contenuto della form, nel caso in cui la richiesta sia di tipo POST, o dalla querystring se ci troviamo al cospetto di una chiamata di tipo GET.
Quando i parametri sono sensibili alla culture dell'utente (come nel caso del tipo DateTime), bisogna prestare particolare attenzione al formato in cui vengono inviati, perché il comportamento del framework varia sensibilmente a seconda della tipologia della richiesta. Infatti, se in caso di POST, il parse avviene in base alla cultura dell'utente, quando la richiesta è in GET viene forzata la InvariantCulture, che prevede per le date il formato americano. Questa scelta ha una ragione di fondo, ossia che gli URL devono essere invarianti rispetto alla culture dell'utente che li genera, e pertanto è consigliabile utilizzare sempre una sola culture per interpretare le richieste.
Purtroppo, però, l'uso della invariant culture può creare problemi nel caso in cui generiamo un URL dall'input dell'utente che, verosimilmente, sarà in formato italiano. Per esempio, immaginiamo di invocare la action vista in precedenza con la seguente form:
@using (Html.BeginForm("Search", null, FormMethod.Get)) { <span>Data da:</span> @Html.TextBox("from")<br /> <span>Data a:</span> @Html.TextBox("to")<br /> <input type="submit" value="Cerca" /> }
Come possiamo notare, questa form è inviata in GET con i due parametri from e to in querystring e, in condizioni normali, trasformati in DateTime secondo la invariant culture. Il risultato sarà che, se per esempio inseriamo la data "10/07/2012", questa sarà interpretata erroneamente:
Per ovviare a questo problema, possiamo creare un value provider personalizzato. Si tratta di un'operazione assolutamente banale, perchè tutta la logica di parsing è contenuta nella classe base NameValueCollectionValueProvider, e quindi possiamo limitarci semplicemente a specificare in maniera esplicita la culture da utilizzare.
internal class CultureQueryStringValueProvider : NameValueCollectionValueProvider { public CultureQueryStringValueProvider( ControllerContext context, CultureInfo culture) : base(context.HttpContext.Request.QueryString, culture) { } }
Questo oggetto accetta nel costruttore un parametro di tipo CultureInfo, che sarà fornito dall'oggetto CultureQueryStringValueProviderFactory, responsabile di istanziarlo:
internal class CultureQueryStringValueProviderFactory : ValueProviderFactory { private CultureInfo _culture; public CultureQueryStringValueProviderFactory(CultureInfo culture) { if (culture == null) throw new ArgumentNullException("culture"); _culture = culture; } public override IValueProvider GetValueProvider( ControllerContext controllerContext) { return new CultureQueryStringValueProvider(controllerContext, _culture); } }
A questo punto non ci resta che l'ultimo passo, ossia sostituire, nel Global.asax, la nostra factory personalizzata a quella di default di ASP.NET MVC, specificando che vogliamo usare la culture italiana:
protected void Application_Start() { // rimuovo il value provider factory di default var toRemove = ValueProviderFactories.Factories .OfType<QueryStringValueProviderFactory>() .Single(); ValueProviderFactories.Factories.Remove(toRemove); // aggiungo il value provider custom var culture = CultureInfo.GetCultureInfo("it-IT"); ValueProviderFactories.Factories.Add( new CultureQueryStringValueProviderFactory(culture)); }
Se ora proviamo a ricaricare la pagina precedente, essa mostrerà le date interpretate correttamente.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Implementare il throttling in ASP.NET Core
Generare file PDF da Blazor WebAssembly con iText
Miglioramenti agli screen reader e al contrasto in Angular
Aggiungere interattività lato server in Blazor 8
Applicare il versioning ai nostri endpoint ASP.NET Core Minimal API
Utilizzare Azure AI Studio per testare i modelli AI
Miglioramenti nelle performance di Angular 16
Utilizzare database e servizi con gli add-on di Container App
Gestire liste di tipi semplici con Entity Framework Core
Eseguire query verso tipi non mappati in Entity Framework Core
Configurare dependabot per aggiornare le dipendenze di terze parti con GitHub Actions
Ottenere il contenuto di una cartella FTP con la libreria FluentFTP
I più letti di oggi
- annunciato #netstandard 2.1. .NET Core lo supporterà a partire da #netcore3, così come le prossime versione di #xamarin, #mono e #unity.il supporto per #netfx 4.8, invece, non ci sarà. https://aspit.co/bq2
- Annunciato Silverlight 4 RC e Windows Phone Developer Tools
- Speciale Razor: il nuovo view engine di WebMatrix e ASP.NET MVC
- Speciale Windows Store app: costruire app con WinRT per Windows 8
- Gestire lo stato all'interno di un class component di ReactJS
- Inserimenti bulk su database con la classe SqlBulkCopy di ADO.NET 2.0
- disponibile su MSDN la versione RTM di #VS2013 Update 2! https://aspit.co/auj #msTechEd