ASP.NET Core:recupero dei valori delle stringhe di query

ASP.NET Core:recupero dei valori delle stringhe di query

Il framework ASP.NET Core analizza automaticamente le stringhe di query (ad esempio ?name=Dune&year=2021 ) in HttpContext.Request.Query e mappa i valori della stringa di query ai parametri di azione (se li hai aggiunti).

Puoi ottenere i valori della stringa di query mappata aggiungendo parametri di azione, come questo:

[HttpGet("search")]
public IActionResult Search(string name, int year)
Code language: C# (cs)

Oppure puoi utilizzare direttamente HttpContext.Request.Query (utile in molti scenari):

string name = HttpContext.Request.Query["name"];
Code language: C# (cs)

Questo può restituire null (se manca la chiave), una singola stringa o una stringa separata da virgole (ad esempio "Dune,Matrix") se sono presenti più valori per la chiave.

Mappatura automatica della stringa di query

Il framework eseguirà automaticamente il mapping della stringa di query ai parametri dell'azione. Tenta di convertire nel tipo corretto e quindi eseguirà la convalida rispetto a tutte le annotazioni di dati che hai aggiunto (come [Obbligatorio]). Nella maggior parte dei casi, dovresti sfruttare questa mappatura automatica invece di utilizzare direttamente HttpContext.Request.Query.

Nota:esegue un confronto senza distinzione tra maiuscole e minuscole quando si tenta di mappare le chiavi della stringa di query sui nomi di parametri/proprietà.

Parametri primitivi

Ecco un esempio di aggiunta di parametri primitivi al metodo di azione:

[HttpGet("search")]
public IActionResult Search(string name, int year, DateTime lastUpdated)
{
	Console.WriteLine($"name={name} year={year} lastUpdated={lastUpdated}");
	//rest of method
}
Code language: C# (cs)

Ecco una richiesta con una stringa di query:

GET /movies/search/?name=Dune&year=2021&lastUpdated=2021-11-12Code language: plaintext (plaintext)

Il framework analizzerà la stringa di query e ne mapperà i valori ai parametri primitivi. Ecco cosa produce:

name=Dune year=2021 lastUpdated=11/21/2021 12:00:00 AMCode language: plaintext (plaintext)

Parametro modello

Puoi incapsulare i parametri in una classe modello:

public class MovieQuery
{
	public string Name { get; set; }
	public int Year { get; set; }
}
Code language: C# (cs)

Aggiungi questa classe del modello MovieQuery come parametro sul metodo di azione e utilizza l'attributo [FromQuery]:

[HttpGet("search")]
public IActionResult Search([FromQuery] MovieQuery movieQuery)
{
	Console.WriteLine($"name={movieQuery.Name} year={movieQuery.Year}");
	//rest of method
}
Code language: C# (cs)

Ecco una richiesta con una stringa di query:

GET /movies/search/?name=Dune&year=1984Code language: plaintext (plaintext)

Il framework analizzerà la stringa di query e mapperà i valori al modello MovieQuery. Ecco cosa produce:

name=Dune year=1984Code language: plaintext (plaintext)

Devi usare [FromQuery] con un parametro del modello?

Sì, altrimenti riceverai una risposta di errore 415 – Tipo di supporto non supportato quando tenta di mappare la stringa di query.

Utilizzare [FromQuery(Name =“qualcosa”] quando il nome del parametro è diverso

Diciamo che le richieste verranno inviate con stringhe di query utilizzando nomi diversi dai parametri/proprietà a cui stai mappando. In tal caso, puoi utilizzare l'attributo [FromQuery(Name =“something”)] per modificare la mappatura per un parametro/proprietà specifico.

Ad esempio, supponiamo che tu riceva richieste con una stringa di query simile a questa:

?movie.name=Dune&movie.year=1984Code language: plaintext (plaintext)

Puoi farlo mappare su "nome" e "anno" in questo modo:

public class MovieQuery
{
	[FromQuery(Name = "movie.name")]
	public string Name { get; set; }

	[FromQuery(Name = "movie.year")]
	public int Year { get; set; }
}
Code language: C# (cs)

Ciò risulterà nella seguente mappatura:

  • nome.film => MovieQuery.Nome
  • anno.film => Anno.FilmQuery.

Più valori per la stessa chiave

Le chiavi della stringa di query possono avere più valori. Ecco un esempio. La chiave dell'anno ha due valori:

GET /movies/search/?name=Dune&year=2021&year=1984

Quando questa richiesta arriva, verrà analizzata in HttpContext.Request.Query, che avrà questo aspetto:

{
	"name" = ["Dune"]
	"year" = ["2021", "1984"]
}Code language: plaintext (plaintext)

Solo il primo valore della chiave verrà automaticamente mappato su un parametro/proprietà (ad esempio int year sarebbe impostato su 2021).

Inoltre, i valori sono in realtà oggetti StringValues. Queste sono raccolte specializzate di stringhe. Ci sono alcune cose da sapere sul funzionamento di StringValues, che descriverò di seguito nel contesto dell'utilizzo di HttpContext.Request.Query.

HttpContext.Request.Query[“key”] restituirà valori separati da virgole

Se più anni vengono inviati nella stringa di query:

GET /movies/search/?name=Dune&year=2021&year=1984Code language: plaintext (plaintext)

E stai usando l'indicizzatore per ottenere il valore:

string year = HttpContext.Request.Query["year"];
Code language: C# (cs)

Restituirà gli anni come valore separato da virgole:

"2021,1984"Code language: plaintext (plaintext)

Non è lo stesso che inviare un elenco separato da virgole nella stringa di query:

GET /movies/search/?name=Dune&year=2021,1984Code language: plaintext (plaintext)

Quando più valori vengono inviati in questo modo, "2021,1984" vengono trattati come un unico valore in HttpContext.Request.Query, non due valori diversi. Alcuni sviluppatori potrebbero preferire gestire più valori in questo modo, invece di aggiungere ripetutamente la stessa chiave. Tutto dipende da come utilizzerai i valori.

Utilizza HttpContext.Request.Query[“key”][0] per ottenere il primo valore

Per ottenere il primo valore, usa:

HttpContext.Request.Query["key"][0]
Code language: C# (cs)

Fallo se non stai utilizzando la mappatura automatica e desideri solo il primo valore.

Nota:controlla sempre se la chiave esiste se stai utilizzando l'indicizzatore in questo modo.

Utilizzo della raccolta StringValues

StringValues ​​è una raccolta. Quando hai a che fare con più valori, non è necessario convertire StringValues ​​in una stringa e gestire la stringa separata da virgole (ad esempio "2021,1984"). Per semplificare le cose, puoi utilizzare la funzionalità di raccolta di StringValues.

  • Puoi scorrere i valori.
foreach(var value in HttpContext.Request.Query["year"])
{
	Console.WriteLine(value);
}
Code language: C# (cs)
  • Puoi controllare quanti valori ci sono.
HttpContext.Request.Query["year"].Count
Code language: C# (cs)
  • Puoi ottenere un array di stringhe.
string[] years = HttpContext.Request.Query["year"].ToArray();

var movies = movieRepository.SearchForYears(years);
Code language: C# (cs)

Verifica se è stata fornita una chiave della stringa di query

Quando è richiesta la chiave

Aggiungi la chiave richiesta come parametro (o proprietà su un modello) e applica l'attributo [Richiesto].

using System.ComponentModel.DataAnnotations;

[HttpGet("search")]
public IActionResult Search([Required] string name)
Code language: C# (cs)

Quando la chiave non viene fornita nella stringa di query, verrà restituita una risposta di errore di convalida (400 – Richiesta non valida ):

"errors": {
        "name": [
            "The name field is required."
        ]
    }Code language: plaintext (plaintext)

Quando la chiave è opzionale

Il modo più semplice per verificare se è stata fornita una chiave è verificare se la chiave esiste:

HttpContext.Request.Query.ContainsKey("oscarWins")
Code language: C# (cs)

In alcuni casi, potresti invece voler usare tipi nullable. Se la chiave non è stata fornita, il suo valore sarà null.

[HttpGet("search")]
public IActionResult Search(string name, int? oscarWins)
{
	if (oscarWins.HasValue)
	{
		//use oscarWins to filter
	}
	else
	{
		//don't use oscarWins to filter
	}

	//rest of method
}
Code language: C# (cs)

Nota:non utilizzare tipi non annullabili. Se la chiave non esiste, il valore verrà impostato su default(thatType), che potrebbe corrispondere a un valore legittimo (come 0 per int). Quindi non è un modo affidabile per verificare se è stata passata una chiave.