จะอ่านค่าจาก querystring ด้วย ASP.NET Core ได้อย่างไร?


136

ฉันกำลังสร้าง RESTful API หนึ่งรายการโดยใช้ ASP.NET Core MVC และฉันต้องการใช้พารามิเตอร์ querystring เพื่อระบุการกรองและการเพจบนทรัพยากรที่ส่งคืนคอลเล็กชัน

ในกรณีนั้นฉันต้องอ่านค่าที่ส่งผ่านในสตริงการสืบค้นเพื่อกรองและเลือกผลลัพธ์ที่จะส่งคืน

ฉันได้พบแล้วว่าภายในการควบคุมGetการดำเนินการในการเข้าถึงผลตอบแทนที่หนึ่งHttpContext.Request.QueryIQueryCollection

ปัญหาคือฉันไม่รู้ว่ามันใช้ในการดึงค่าอย่างไร ความจริงฉันคิดว่าวิธีที่จะทำคือใช้ตัวอย่างเช่น

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

ปัญหาคือHttpContext.Request.Query["page"]ไม่ส่งคืนสตริง แต่เป็นStringValuesไฟล์.

อย่างไรก็ตามเราจะใช้IQueryCollectionเพื่ออ่านค่าสตริงการสืบค้นได้อย่างไร?


1
ฉันเขียนโพสต์เดียวกันซึ่งคุณสามารถค้นหาได้ที่นี่: neelbhatt40.wordpress.com/2017/07/06/…
Neel

คำตอบ:


137

คุณสามารถใช้[FromQuery]เพื่อผูกโมเดลเฉพาะกับสตริงการสืบค้น:

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

เช่น

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

5
ฉันคิดว่า[FromQuery]แอตทริบิวต์สามารถถูก ommited ได้เช่นกันเนื่องจากการโยง. net จะตรวจสอบอินพุตแบบฟอร์มและพารามิเตอร์สตริงการสืบค้น URL ทั้งหมดตามค่าเริ่มต้นยกเว้นว่าคุณมีเหตุผลบางประการในการ จำกัด แหล่งที่มา
S.Serpooshan

12
(Name = "page") ไม่จำเป็น - มันจะผูกกับตัวแปรหากตั้งชื่อเหมือนกัน
a3uge

นี่เป็นสิ่งสำคัญหากชื่อพารามิเตอร์ querystring มีโครงสร้าง ตัวอย่างเช่น 'object.propname'
Jose Capistrano

96

คุณสามารถใช้วิธี ToString IQueryCollectionซึ่งจะส่งคืนค่าที่ต้องการหากpageระบุพารามิเตอร์เดียว:

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

หากมีหลายค่าเช่น?page=1&page=2ผลลัพธ์ของการเรียก ToString จะเป็น1,2

แต่ตามที่ @ mike-g แนะนำในคำตอบของเขาคุณควรใช้การผูกโมเดลดีกว่าและไม่ได้เข้าถึงHttpContext.Request.Queryวัตถุโดยตรง


6
ไม่จำเป็นต้องใช้ ToString คอมไพเลอร์จะส่งโดยปริยายหากคุณกำหนดค่าการสืบค้นให้กับสตริง ..
Stefan Steiger

26

ASP.NET หลักจะผูกอัตโนมัติform values, route valuesและquery stringsโดยใช้ชื่อ ซึ่งหมายความว่าคุณสามารถทำได้ง่ายๆ:

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

MVC จะพยายามผูกข้อมูลคำขอกับพารามิเตอร์การดำเนินการตามชื่อ ... ด้านล่างนี้คือรายการของแหล่งข้อมูลตามลำดับที่การเชื่อมโยงแบบจำลองดูผ่านพวกเขา

  1. Form values: นี่คือค่าฟอร์มที่ไปในคำขอ HTTP โดยใช้วิธีการ POST (รวมถึงคำขอ jQuery POST)

  2. Route values: ชุดค่าเส้นทางที่กำหนดโดยการกำหนดเส้นทาง

  3. Query strings: ส่วนสตริงการสืบค้นของ URI

ที่มา: การผูกโมเดลทำงานอย่างไร


FYI คุณยังสามารถรวมแนวทางอัตโนมัติและชัดเจนเข้าด้วยกัน:

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

20

คุณสามารถสร้างวัตถุเช่นนี้:

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

จากนั้นในตัวควบคุมเพียงแค่ทำสิ่งนั้น:

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

ยิ่งไปกว่านั้นคุณสามารถสร้างโมเดล API ได้จาก:

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

ถึง:

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

URL นี้จะใช้กับอะไร ฉันยังใหม่กับเรื่องนี้จึงไม่สามารถ "ย้อนกลับวิศวกร" ไปที่ URL ได้ น่าจะเป็นอย่างexample.com/somequery/…หรือไม่?
Christian

1
@Christian ถ้าคุณไม่เปลี่ยนรูปแบบใด ๆ ก็จะเป็น example.com/[controller]/[action]/{someid:int}?someparameter=1&someparameter2=2
LxL

19

นี่คือตัวอย่างโค้ดที่ฉันใช้ (ด้วยมุมมอง. NET Core):

@{
    Microsoft.Extensions.Primitives.StringValues queryVal;

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

2
โหวตให้รวมชื่ออ็อบเจ็กต์แบบเต็ม (หรือใช้คำสั่งที่ถูกต้อง) ทำให้ฉันรู้สึกแย่เมื่อมีคนใส่ชื่อวัตถุโดยไม่มีคุณสมบัติครบถ้วนหรืออย่างน้อยก็ใช้คำสั่ง ขอบคุณ
granadaCoder

11

StringValuesเป็นอาร์เรย์ของสตริง HttpContext.Request.Query["page"][0]คุณจะได้รับค่าสตริงของคุณโดยให้ดัชนีเช่น


1
ขอบคุณ; นี่เป็นคำตอบเดียวที่ตอบคำถามได้จริง (ในกรณีของฉันฉันไม่สามารถใช้การเชื่อมโยงได้เพราะฉันมีตรรกะที่ซับซ้อนกว่าเช่น "ลองใช้สตริงการสืบค้นก่อนหากไม่มีให้ลองใช้เซสชันไปเรื่อย ๆ ")
Marcel Popescu

7

IQueryCollectionมีTryGetValue()อยู่ที่ส่งคืนค่าด้วยคีย์ที่กำหนด ดังนั้นหากคุณมีพารามิเตอร์การค้นหาที่เรียกว่าsomeIntคุณสามารถใช้ได้ดังนี้:

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

โปรดสังเกตว่าหากคุณไม่มีพารามิเตอร์หลายตัวที่มีชื่อเดียวกันStringValuesประเภทนี้ก็ไม่ใช่ปัญหา


หากต้องการเพิ่มคำตอบนี้ถ้าคุณเรียก StringValues ​​ToString () คุณสามารถส่งไปยังสตริงได้โดยตรงหากนั่นคือสิ่งที่คุณต้องการ
eltiare

ผู้อ่านในอนาคต: ชื่อแบบเต็ม "Microsoft.AspNetCore.Http.IQueryCollection queryString = this.Request.Query;" Mine อยู่ใน "Assembly Microsoft.AspNetCore.Http.Features, Version = 3.1.0.0," และ "Microsoft.Extensions.Primitives.StringValues" (ของฉันอยู่ใน "Assembly Microsoft.Extensions.Primitives, Version = 3.1.2.0,")
granadaCoder

3

ใน. net core หากคุณต้องการเข้าถึง querystring ในมุมมองของเราให้ใช้มันเช่น

@Context.Request.Query["yourKey"]

หากเราอยู่ในตำแหน่งที่ @Context ไม่สามารถใช้งานได้เราสามารถฉีดได้เช่น

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

สำหรับคุกกี้ด้วย

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

2
ไม่จำเป็นต้องใช้รหัสนั้นทั้งหมด เพียงใช้ @ Context.Request.Query ["yourKey"]
Shadi Namrouti

ใช่ @ShadiNamrouti คุณอยู่ในมุมมองที่ถูกต้องโดยที่ \ @Context สามารถใช้งานได้เราสามารถใช้มันได้เช่น \ @ Context.Request.Query ["yourKey"] แต่ถ้าเราอยู่ในตัวควบคุมเราจำเป็นต้องฉีด HttpContextAccessor.HttpContext
M.Ali El-Sayed

2

ฉันมีทางออกที่ดีกว่าสำหรับปัญหานี้

  • คำขอเป็นสมาชิกของ ControllerBase คลาสนามธรรม
  • GetSearchParams () เป็นวิธีการขยายที่สร้างขึ้นในคลาสผู้ช่วยร้อง

var searchparams = await Request.GetSearchParams();

ฉันได้สร้างคลาสแบบคงที่โดยใช้วิธีการขยายไม่กี่วิธี

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

ด้วยวิธีนี้คุณสามารถเข้าถึงพารามิเตอร์การค้นหาทั้งหมดของคุณได้อย่างง่ายดาย ฉันหวังว่านี่จะช่วยนักพัฒนาหลาย ๆ คน :)


ฉันขาดอะไรไป - FhirException ถูกกำหนดไว้ที่ไหนพื้นที่ชื่อใดที่ Task <SearchParams> พบใน?
Doug Thompson - DouggyFresh

1

ความคิดเห็นบางส่วนกล่าวถึงเรื่องนี้เช่นกัน แต่ asp net core ทำงานทั้งหมดนี้ให้คุณ

หากคุณมีสตริงการสืบค้นที่ตรงกับชื่อจะพร้อมใช้งานในคอนโทรลเลอร์

https: // myapi / บางปลายทาง / 123 = someQueryString YayThisWorks

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

เพื่อถ่ายทอด:

123

YayThisWorks

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.