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
Path addizionali per gli asset in ASP.NET Core MVC
Esportare ed analizzare le issue di GitHub con la CLI e GraphQL
Filtering sulle colonne in una QuickGrid di Blazor
Creare una libreria CSS universale: Clip-path
Creare una libreria CSS universale - Rotazione degli elementi
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Gestire eccezioni nei plugin di Semantic Kernel in ASP.NET Core Web API
Utilizzare Copilot con Azure Cosmos DB
Estrarre dati randomici da una lista di oggetti in C#
Le novità di Angular: i miglioramenti alla CLI
Usare i servizi di Azure OpenAI e ChatGPT in ASP.NET Core con Semantic Kernel
Paginare i risultati con QuickGrid in Blazor
I più letti di oggi
- Simulare Azure Cosmos DB in locale con Docker
- Utilizzare il metodo Index di LINQ per scorrere una lista sapendo anche l'indice dell'elemento
- .NET Conference Italia 2023 - Milano e Online
- .NET Conference Italia 2024 - Milano
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!