ASP.NET Core ile sorgu dizesindeki değerler nasıl okunur?


136

ASP.NET Core MVC kullanarak bir RESTful API oluşturuyorum ve bir koleksiyon döndüren bir kaynakta filtreleme ve sayfalama belirtmek için sorgu dizesi parametrelerini kullanmak istiyorum.

Bu durumda, döndürülecek sonuçları filtrelemek ve seçmek için sorgu dizesinde geçirilen değerleri okumam gerekir.

GetErişmenin denetleyici eyleminin içinde HttpContext.Request.Querybir tane döndürdüğünü zaten öğrendim IQueryCollection.

Sorun şu ki, değerleri almak için nasıl kullanıldığını bilmiyorum. Doğrusu, yapmanın yolunun örneğin

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

Sorun şu ki HttpContext.Request.Query["page"], bir dizge değil, a StringValues.

Her neyse, IQueryCollectionsorgu dizesi değerlerini okumak için nasıl kullanılır ?


1
Burada bulabileceğiniz aynısı için bir gönderi yazdım: neelbhatt40.wordpress.com/2017/07/06/…
Neel

Yanıtlar:


137

[FromQuery]Belirli bir modeli sorgu dizesine bağlamak için kullanabilirsiniz :

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

Örneğin

[HttpGet()]
public IActionResult Get([FromQuery(Name = "page")] string page)
{...}

5
[FromQuery].Net bağlaması tüm form girişlerini ve url sorgu dizesi parametrelerini varsayılan olarak kontrol edeceğinden özniteliğin ihmal edilebileceğini düşünüyorum , ancak kaynağını sınırlamak için bir nedeniniz olması dışında.
S.Serpooshan

12
(Ad = "sayfa") gereksiz - aynı şekilde adlandırılırsa değişkene bağlanır
a3uge

Sorgu dizesi parametre adı yapılandırılmışsa bu önemlidir. Örneğin 'object.propname'
Jose Capistrano

96

IQueryCollectionTek bir pageparametre belirtilirse istenen değeri döndürecek ToString yöntemini kullanabilirsiniz :

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

gibi birden çok değer varsa ?page=1&page=2, ToString çağrısının sonucu1,2

Ancak @ mike-g'nin cevabında önerdiği gibi, doğrudan HttpContext.Request.Querynesneye erişmek yerine model bağlamayı kullanmanız daha iyi olur .


6
ToString gerekli değildir. Eğer bir dizeye sorgu değeri atarsanız derleyici üstü kapalı biçimde kullanacaklar ..
Stefan Steiger

26

ASP.NET Çekirdek otomatik bağlayacaktır form values, route valuesve query stringsadıyla. Bu, bunu kolayca yapabileceğiniz anlamına gelir:

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

MVC, istek verilerini eylem parametrelerine ada göre bağlamayı deneyecek ... aşağıda, model bağlamanın bunlara baktığı sırada veri kaynaklarının bir listesi bulunmaktadır.

  1. Form values: Bunlar, POST yöntemi kullanılarak HTTP isteğine giren form değerleridir. (jQuery POST istekleri dahil).

  2. Route values: Yönlendirme tarafından sağlanan yol değerleri kümesi

  3. Query strings: URI'nin sorgu dizesi kısmı.

Kaynak: Model bağlama nasıl çalışır?


Bilginize, otomatik ve açık yaklaşımları da birleştirebilirsiniz:

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

20

Bunun gibi bir nesne oluşturabilirsiniz:

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

Ve sonra denetleyicide şöyle bir şey yapın:

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

Daha da iyisi, API modelini şunlardan oluşturabilirsiniz:

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

için:

[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; }
}

Bunun geçerli olacağı bir URL nedir? Bu konuda yeniyim, bu nedenle URL’ye "geriye dönük mühendislik" yapamam. Example.com/somequery/… gibi bir şey olur mu?
Christian

1
@Christian, herhangi bir kuralı değiştirmezseniz, example.com/[controller]/[action]/{someid:int}?someparameter=1&someparameter2=2
LxL

19

İşte kullandığım bir kod örneği (.NET Core görünümüyle):

@{
    Microsoft.Extensions.Primitives.StringValues queryVal;

    if (Context.Request.Query.TryGetValue("yourKey", out queryVal) &&
        queryVal.FirstOrDefault() == "yourValue")
    {
    }
}

2
FULL nesne adını (veya doğru kullanım ifadesini) eklemek için oy verin. İnsanlar tam olarak nitelenmemiş veya en azından bir kullanım ifadesi olmadan sadece nesne adını koyduğunda beni deli ediyor. Teşekkürler.
granadaCoder

11

StringValuesdizelerden oluşan bir dizidir . Bir dizin sağlayarak dize değerinizi alabilirsiniz, örn HttpContext.Request.Query["page"][0].


1
Teşekkür ederim; soruyu gerçekten cevaplayan tek cevap buydu. (Benim durumumda, bağlamayı kullanamıyorum çünkü "önce sorgu dizesini dene, eksikse oturumu dene ve benzeri" gibi daha karmaşık bir mantığım var.)
Marcel Popescu

7

IQueryCollectionBir sahiptir TryGetValue()Üzerinde getiriyi verilen anahtarla bir değer. Yani, adında bir sorgu parametreniz varsa someInt, bunu şu şekilde kullanabilirsiniz:

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

Aynı adda birden çok parametreniz olmadığı sürece, StringValuestürün bir sorun teşkil etmediğine dikkat edin .


Bu yanıta eklemek için, StringValues.ToString () 'i çağırırsanız, ihtiyacınız olan buysa, bunu doğrudan bir dizeye çevirebilirsiniz.
eltiare

Gelecek okuyucular: tam nitelikli ad "Microsoft.AspNetCore.Http.IQueryCollection queryString = this.Request.Query;" Benimki "Assembly Microsoft.AspNetCore.Http.Features, Version = 3.1.0.0" ve "Microsoft.Extensions.Primitives.StringValues" içindeydi (benimki "Assembly Microsoft.Extensions.Primitives, Sürüm = 3.1.2.0" içindeydi)
granadaCoder

3

.net çekirdeğinde, bizim görüşümüzde sorgu dizesine erişmek istiyorsanız, aşağıdaki gibi kullanın

@Context.Request.Query["yourKey"]

@Context'in mevcut olmadığı bir konumdaysak, onu şu şekilde enjekte edebiliriz

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

ayrıca çerezler için

HttpContextAccessor.HttpContext.Request.Cookies["DeniedActions"]

2
Tüm bu koda gerek yok. @ Context.Request.Query ["yourKey"] kullanın
Shadi Namrouti

Evet @ShadiNamrouti, \ @Context'in mevcut olduğu görünümde haklısınız, bunu \ @ Context.Request.Query ["yourKey"] gibi kullanabiliriz ancak denetleyicideysek HttpContextAccessor.HttpContext'i enjekte etmemiz gerekir.
M.Ali El-Sayed

2

Bu sorun için daha iyi bir çözümüm var.

  • istek, ControllerBase soyut sınıfının bir üyesidir
  • GetSearchParams (), aşağıdaki yardımcı sınıfta oluşturulan bir genişletme yöntemidir.

var searchparams = await Request.GetSearchParams();

Birkaç uzantı yöntemiyle statik bir sınıf oluşturdum

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;
    }
}

bu şekilde tüm arama parametrelerinize kolayca erişebilirsiniz. Umarım bu birçok geliştiriciye yardımcı olur :)


Eksik bir şey mi var - FhirException nerede tanımlanmış, Task <SearchParams> hangi ad alanında bulunuyor?
Doug Thompson - DouggyFresh

1

Bazı yorumlar da bundan bahsediyor, ancak asp net core tüm bunları sizin için yapıyor.

Adla eşleşen bir sorgu dizeniz varsa, denetleyicide mevcut olacaktır.

https: // MyAPI / Bazı-uç nokta / 123 someQueryString = YayThisWorks

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

Çıkışlardan:

123

YayThisWorks

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.