Wie lese ich mit ASP.NET Core Werte aus dem Querystring?

135

Ich erstelle eine RESTful-API mit ASP.NET Core MVC und möchte Querystring-Parameter verwenden, um das Filtern und Paging einer Ressource anzugeben, die eine Sammlung zurückgibt.

In diesem Fall muss ich die im Querystring übergebenen Werte lesen, um zu filtern und die zurückzugebenden Ergebnisse auszuwählen.

Ich habe bereits herausgefunden, dass innerhalb der Controller- GetAktion der Zugriff eine HttpContext.Request.Queryzurückgibt IQueryCollection.

Das Problem ist, dass ich nicht weiß, wie es zum Abrufen der Werte verwendet wird. In Wahrheit dachte ich, der Weg wäre zum Beispiel die Verwendung von

string page = HttpContext.Request.Query["page"]

Das Problem ist, dass HttpContext.Request.Query["page"]keine Zeichenfolge zurückgegeben wird, sondern eine StringValues.

Wie benutzt man das IQueryCollection, um die Querystring-Werte tatsächlich zu lesen?

user1620696
quelle
1
Ich habe einen Beitrag dafür geschrieben, den Sie hier finden können: neelbhatt40.wordpress.com/2017/07/06/…
Neel

Antworten:

133

Sie können [FromQuery]ein bestimmtes Modell an den Querystring binden:

https://docs.microsoft.com/en-us/aspnet/core/mvc/models/model-binding

z.B

[HttpGet()]
public IActionResult Get([FromQuery(Name = "page")] string page)
{...}
Mike_G
quelle
5
Ich denke, das [FromQuery]Attribut kann auch weggelassen werden, da die .net-Bindung standardmäßig alle Formulareingaben und URL-Querystring-Parameter überprüft, außer dass Sie einen Grund haben, die Quelle einzuschränken.
Serpooshan
12
(Name = "Seite") ist nicht
erforderlich
Dies ist wichtig, wenn der Name des Querystring-Parameters strukturiert ist. Zum Beispiel 'object.propname'
Jose Capistrano
95

Sie können die ToString-Methode verwenden, bei IQueryCollectionder der gewünschte Wert zurückgegeben wird, wenn ein einzelner pageParameter angegeben wird:

string page = HttpContext.Request.Query["page"].ToString();

Wenn es mehrere Werte wie gibt, ?page=1&page=2ist das Ergebnis des ToString-Aufrufs1,2

Aber wie @ mike-g in seiner Antwort vorgeschlagen hat, sollten Sie besser die Modellbindung verwenden und nicht direkt auf das HttpContext.Request.QueryObjekt zugreifen .

Darin Dimitrov
quelle
6
Der ToString ist nicht erforderlich. Der Compiler wird es implizit umwandeln, wenn Sie den Abfragewert einer Zeichenfolge zuweisen.
Stefan Steiger
26

ASP.NET - Core automatisch binden form values, route valuesund query stringsnach dem Namen. Dies bedeutet, dass Sie dies einfach tun können:

[HttpGet()]
public IActionResult Get(int page)
{ ... }

MVC versucht, Anforderungsdaten nach Namen an die Aktionsparameter zu binden. Nachfolgend finden Sie eine Liste der Datenquellen in der Reihenfolge, in der die Modellbindung sie durchsucht

  1. Form values: Dies sind Formularwerte, die mithilfe der POST-Methode in die HTTP-Anforderung aufgenommen werden. (einschließlich jQuery POST-Anforderungen).

  2. Route values: Der vom Routing bereitgestellte Satz von Routenwerten

  3. Query strings: Der Abfragezeichenfolgen-Teil des URI.

Quelle: Funktionsweise der Modellbindung


Zu Ihrer Information, Sie können auch die automatischen und expliziten Ansätze kombinieren:

[HttpGet()]
public IActionResult Get(int page
     , [FromQuery(Name = "page-size")] int pageSize)
{ ... }
Spottedmahn
quelle
20

Sie können einfach ein Objekt wie folgt erstellen:

public class SomeQuery
{
    public string SomeParameter { get; set; }
    public int? SomeParameter2 { get; set; }
}

Und dann in Controller einfach so etwas machen:

[HttpGet]
public IActionResult FindSomething([FromQuery] SomeQuery query)
{
    // Your implementation goes here..
}

Noch besser ist, dass Sie ein API-Modell erstellen können aus:

[HttpGet]
public IActionResult GetSomething([FromRoute] int someId, [FromQuery] SomeQuery query)

zu:

[HttpGet]
public IActionResult GetSomething(ApiModel model)

public class ApiModel
{
    [FromRoute]
    public int SomeId { get; set; }
    [FromQuery]
    public string SomeParameter { get; set; }
    [FromQuery]
    public int? SomeParameter2 { get; set; }
}
Mariusz
quelle
Für welche URL würde dies gelten? Ich bin neu in diesem Bereich, daher kann ich die URL nicht rückwärts konstruieren. Wäre es so etwas wie example.com/somequery/… ?
Christian
1
@Christian, wenn Sie keine Konvention ändern, wäre es example.com/[controller‹/[action
weiblich
19

Hier ist ein Codebeispiel, das ich verwendet habe (mit einer .NET Core-Ansicht):

@{
    Microsoft.Extensions.Primitives.StringValues queryVal;

    if (Context.Request.Query.TryGetValue("yourKey", out queryVal) &&
        queryVal.FirstOrDefault() == "yourValue")
    {
    }
}
Pavel
quelle
2
Upvote für das Einfügen des FULL-Objektnamens (oder der korrekten using-Anweisung). Macht mich verrückt, wenn Leute nur den Objektnamen ohne vollständige Qualifikation oder zumindest mit einer using-Anweisung eingeben. Vielen Dank.
GranadaCoder
11

StringValuesist ein Array von Zeichenfolgen . Sie können Ihren Zeichenfolgenwert erhalten, indem Sie einen Index angeben, z HttpContext.Request.Query["page"][0].

Constantinos G.
quelle
1
Danke dir; Dies war die einzige Antwort, die die Frage tatsächlich beantwortete. (In meinem Fall kann ich keine Bindung verwenden, da ich eine komplexere Logik wie "Versuchen Sie zuerst die Abfragezeichenfolge, wenn diese fehlt, versuchen Sie die Sitzung und so weiter" habe.)
Marcel Popescu
7

IQueryCollectionhat ein TryGetValue()drauf, das einen Wert mit dem angegebenen Schlüssel zurückgibt. Wenn Sie also einen Abfrageparameter namens haben someInt, können Sie ihn folgendermaßen verwenden:

var queryString = httpContext.Request.Query;
StringValues someInt;
queryString.TryGetValue("someInt", out someInt);
var daRealInt = int.Parse(someInt);

Beachten Sie, dass der StringValuesTyp kein Problem darstellt , es sei denn, Sie haben mehrere Parameter mit demselben Namen .

Steamrolla
quelle
Wenn Sie StringValues.ToString () aufrufen, können Sie diese Antwort direkt in einen String umwandeln, wenn Sie dies benötigen.
eltiare
Zukünftige Leser: voll qualifizierter Name "Microsoft.AspNetCore.Http.IQueryCollection queryString = this.Request.Query;" Meins war in "Assembly Microsoft.AspNetCore.Http.Features, Version = 3.1.0.0" und "Microsoft.Extensions.Primitives.StringValues" (meins war in "Assembly Microsoft.Extensions.Primitives, Version = 3.1.2.0,")
GranadaCoder
3

Wenn Sie in .net Core auf Querystring zugreifen möchten, verwenden Sie es in unserer Ansicht wie folgt

@Context.Request.Query["yourKey"]

Wenn wir uns an einem Ort befinden, an dem @Context nicht verfügbar ist, können wir es wie folgt injizieren

@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
@if (HttpContextAccessor.HttpContext.Request.Query.Keys.Contains("yourKey"))
{
      <text>do something </text>
}

auch für Cookies

HttpContextAccessor.HttpContext.Request.Cookies["DeniedActions"]
M.Ali El-Sayed
quelle
2
Der ganze Code ist nicht erforderlich. Verwenden Sie einfach @ Context.Request.Query ["yourKey"]
Shadi Namrouti
Ja @ShadiNamrouti Sie haben Recht, wo \ @Context verfügbar ist. Wir können es wie \ @ Context.Request.Query ["yourKey"] verwenden, aber wenn wir uns im Controller befinden, müssen wir den HttpContextAccessor.HttpContext einfügen.
M.Ali El-Sayed
2

Ich habe eine bessere Lösung für dieses Problem,

  • request ist Mitglied der abstrakten Klasse ControllerBase
  • GetSearchParams () ist eine Erweiterungsmethode, die in der folgenden Hilfsklasse erstellt wurde.

var searchparams = await Request.GetSearchParams();

Ich habe eine statische Klasse mit wenigen Erweiterungsmethoden erstellt

public static class HttpRequestExtension
{
  public static async Task<SearchParams> GetSearchParams(this HttpRequest request)
        {
            var parameters = await request.TupledParameters();

            try
            {
                for (var i = 0; i < parameters.Count; i++)
                {
                    if (parameters[i].Item1 == "_count" && parameters[i].Item2 == "0")
                    {
                        parameters[i] = new Tuple<string, string>("_summary", "count");
                    }
                }
                var searchCommand = SearchParams.FromUriParamList(parameters);
                return searchCommand;
            }
            catch (FormatException formatException)
            {
                throw new FhirException(formatException.Message, OperationOutcome.IssueType.Invalid, OperationOutcome.IssueSeverity.Fatal, HttpStatusCode.BadRequest);
            }
        }



public static async Task<List<Tuple<string, string>>> TupledParameters(this HttpRequest request)
{
        var list = new List<Tuple<string, string>>();


        var query = request.Query;
        foreach (var pair in query)
        {
            list.Add(new Tuple<string, string>(pair.Key, pair.Value));
        }

        if (!request.HasFormContentType)
        {
            return list;
        }
        var getContent = await request.ReadFormAsync();

        if (getContent == null)
        {
            return list;
        }
        foreach (var key in getContent.Keys)
        {
            if (!getContent.TryGetValue(key, out StringValues values))
            {
                continue;
            }
            foreach (var value in values)
            {
                list.Add(new Tuple<string, string>(key, value));
            }
        }
        return list;
    }
}

Auf diese Weise können Sie einfach auf alle Ihre Suchparameter zugreifen. Ich hoffe das wird vielen Entwicklern helfen :)

Shanjee
quelle
Vermisse ich etwas - wo ist FhirException definiert, in welchem ​​Namensraum befindet sich Task <SearchParams>?
Doug Thompson - DouggyFresh
1

Einige der Kommentare erwähnen dies ebenfalls, aber asp net core erledigt all diese Arbeit für Sie.

Wenn Sie eine Abfragezeichenfolge haben, die dem Namen entspricht, ist diese im Controller verfügbar.

https: // myapi / some-endpoint / 123? someQueryString = YayThisWorks

[HttpPost]
[Route("some-endpoint/{someValue}")]
public IActionResult SomeEndpointMethod(int someValue, string someQueryString)
    {
        Debug.WriteLine(someValue);
        Debug.WriteLine(someQueryString);
        return Ok();
    }

Ausgaben:

123

YayThisWorks

Jordanien
quelle