พารามิเตอร์สตริงข้อความค้นหาเพิ่มเติมใน ASP.NET Web API


212

ฉันต้องใช้วิธีการ WebAPI ต่อไปนี้:

/api/books?author=XXX&title=XXX&isbn=XXX&somethingelse=XXX&date=XXX

พารามิเตอร์สตริงแบบสอบถามทั้งหมดสามารถเป็นค่าว่างได้ นั่นคือผู้เรียกสามารถระบุจาก 0 ถึงพารามิเตอร์ทั้งหมด 5 ตัว

ในMVC4 เบต้าฉันเคยทำสิ่งต่อไปนี้:

public class BooksController : ApiController
{
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks(string author, string title, string isbn, string somethingelse, DateTime? date) 
    {
        // ...
    }
}

MVC4 RC ไม่ทำงานเช่นนี้อีกต่อไป หากฉันระบุพารามิเตอร์น้อยกว่า 5 พารามิเตอร์จะตอบกลับด้วย404คำพูด:

ไม่พบการกระทำใน 'หนังสือ' ของคอนโทรลเลอร์ที่ตรงกับคำขอ

ลายเซ็นวิธีการที่ถูกต้องคืออะไรที่จะทำให้มันทำงานเหมือนที่เคยทำโดยไม่ต้องระบุพารามิเตอร์ทางเลือกในการกำหนดเส้นทาง URL?


วาง [httpget] ในการดำเนินการ
user960567

2
หากฉันตั้งค่าพารามิเตอร์ทั้งหมดวิธีที่ได้รับเรียก; นอกจากนี้มันเริ่มต้นด้วยGetจึงถูกผูกไว้โดยอัตโนมัติด้วยHTTP GETวิธีการ ...
frapontillo

นี่คือการทำงานของการกำหนดเส้นทางเว็บ API, asp.net/web-api/overview/web-api-routing-and-actions/ …
960567

4
ใช่. ฉันรู้ว่ามันทำงานอย่างไร ฉันไม่สามารถให้มันทำงานภายใต้สถานการณ์พิเศษนี้ได้
frapontillo

วิธีนี้รวบรวมได้อย่างไร string?ไม่ใช่ประเภทที่ถูกต้อง คุณไม่สามารถประกาศstringว่าเป็นประเภทที่ไม่มีค่าเนื่องจากเป็นประเภทอ้างอิง
EkoostikMartin

คำตอบ:


307

ปัญหานี้ได้รับการแก้ไขใน MVC4 รุ่นปกติ ตอนนี้คุณสามารถทำได้:

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

และทุกอย่างจะทำงานนอกกรอบ


ฉันสามารถใช้ null ที่นี่เป็นค่าเริ่มต้นได้หรือไม่ ตัวอย่างเช่น: string author = null?
Boris Zinchenko

2
ใช่nullถือว่าเป็นการแสดงออกอย่างต่อเนื่องและดังนั้นจึงมีค่าเริ่มต้นที่ถูกต้อง
JDawg

ผมสงสัยว่าทำไมเราต้องพูดถึงค่าเริ่มต้นแม้สำหรับพารามิเตอร์ที่ไม่จำเป็นเป็นกล่าวที่นี่ ชนิดใด ๆ ใน C # มีค่าเริ่มต้นเสมอดังนั้นการกำหนดเส้นทางรันไทม์อาจใช้ค่าเริ่มต้นของประเภทนั้นหากไม่ได้รับจาก URI อะไรคือเหตุผลทางเทคนิคที่อยู่เบื้องหลังสิ่งนี้ ฉันแน่ใจว่าสิ่งนี้เกี่ยวข้องกับตัวยึดโมเดล
RBT

@RBT เพื่อให้สามารถจับคู่เส้นทางได้
James Westgate

ฉันใช้พารามิเตอร์วันที่และหากฉันเพิ่งตั้งค่าเป็นโมฆะไม่ทำงาน ดังนั้นฉันต้องตั้งค่าเป็นโมฆะและตั้งเป็นโมฆะเป็นค่าเริ่มต้นและใช้การตรวจสอบฝั่งเซิร์ฟเวอร์ตามและกลับข้อความผิดพลาดกลับ มันได้ผล
Atta H.

85

เป็นไปได้ที่จะส่งพารามิเตอร์หลาย ๆ แบบเป็นรุ่นเดียวตามที่วีเจย์แนะนำ สิ่งนี้ใช้ได้กับ GET เมื่อคุณใช้แอททริบิวพารามิเตอร์ FromUri สิ่งนี้บอกให้ WebAPI เติมโมเดลจากพารามิเตอร์เคียวรี

ผลลัพธ์คือแอ็คชั่นคอนโทรลเลอร์ที่สะอาดขึ้นโดยใช้เพียงพารามิเตอร์เดียว สำหรับข้อมูลเพิ่มเติมดู: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

public class BooksController : ApiController
  {
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks([FromUri]BookQuery query)
    {
      // ...
    }
  }

  public class BookQuery
  {
    public string Author { get; set; }
    public string Title { get; set; }
    public string ISBN { get; set; }
    public string SomethingElse { get; set; }
    public DateTime? Date { get; set; }
  }

มันยังรองรับพารามิเตอร์หลายตัวตราบใดที่คุณสมบัติไม่ขัดแย้งกัน

// GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
public string GetFindBooks([FromUri]BookQuery query, [FromUri]Paging paging)
{
  // ...
}

public class Paging
{
  public string Sort { get; set; }
  public int Skip { get; set; }
  public int Take { get; set; }
}

อัปเดต :
เพื่อให้แน่ใจว่าค่าเป็นตัวเลือกตรวจสอบให้แน่ใจว่าใช้ประเภทการอ้างอิงหรือ nullables (เช่น int?) สำหรับคุณสมบัติของรุ่น


4
ใช่ แต่มัณฑนากร [FromUri] เพียงอย่างเดียวดูเหมือนจะไม่สนับสนุนพารามิเตอร์เสริม
John Meyer

6
@JohnMeyer คุณถูกต้องโดยใช้ [FromUri] ไม่ตอบคำถามเดิมโดยตรง โดยพื้นฐานแล้วกล่าวว่าเติมข้อมูลโมเดลเหล่านี้ด้วยค่าจาก Uri คุณสมบัติของแบบจำลองจะต้องเป็นโมฆะหรือชนิดการอ้างอิงเพื่อให้สามารถรองรับได้ เพิ่มข้อมูลเพิ่มเติม
แอนดรู C

@AndrewC - คุณสามารถอธิบายรายละเอียดเกี่ยวกับเวลาที่ / ทำไมคุณจำเป็นต้องใช้ nullables เพื่อให้แน่ใจว่าค่าเป็นตัวเลือกหรือไม่ หากคุณไม่ได้ทำให้ค่าเป็นโมฆะ (สำหรับอดีตคุณสมบัติint Skip) และไม่มีพารามิเตอร์แบบสอบถามสำหรับคุณสมบัติที่ระบุวิธีการควบคุม API จะยังคงตรงกับคำขอประสบความสำเร็จและค่าสำหรับSkipจะเป็นค่าเริ่มต้นสำหรับประเภทนั้น หรือ 0 ในกรณีนี้
Clark

2
@Clark - หากไม่มีการใช้ประเภท nullable คุณจะไม่ทราบว่าผู้ใช้ไม่ได้ระบุค่าและรับค่าชนิด uninitialized (0 สำหรับ int) หรือถ้าผู้ใช้ระบุ 0 โดยใช้ nullable คุณจะแน่ใจว่าผู้ใช้ได้ปล่อยทิ้งไว้ไม่ได้กำหนด ดังนั้นคุณสามารถใช้ค่าเริ่มต้นของคุณอย่างปลอดภัยในการดำเนินการควบคุม หากคุณดูที่ Take จากตัวอย่างด้านบนสิ่งที่ควรทำหากได้รับ 0 สำหรับ Take ผู้ใช้หมายถึงการขอบันทึก 0 รายการหรือไม่ได้ระบุไว้ดังนั้นคุณควรจดบันทึกทั้งหมด โดยทั่วไปถ้าคุณต้องการประเภทค่า (int, บูล ฯลฯ ) เป็นทางเลือกก็ควรเป็นโมฆะ
แอนดรู C

70

ใช้ค่าเริ่มต้นเริ่มต้นสำหรับพารามิเตอร์ทั้งหมดด้านล่าง

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

1
นี่เป็นขั้นตอนที่ถูกต้อง แต่สำหรับสิ่งหนึ่ง: DateTimeไม่เป็นโมฆะ ฉันได้ลองใช้DateTime?แทนแล้ว แต่ MVC ไม่แมปคำขอกับวิธีการที่กำหนดถ้าฉันตั้งค่าพารามิเตอร์บางอย่างเท่านั้นในคำขอ HTTP ของฉัน
frapontillo

คุณสามารถส่งวันที่เป็นสตริงและแยกวิเคราะห์ภายในฟังก์ชันคอนโทรลเลอร์ของคุณโดยใช้ฟังก์ชัน DateTime.Parse ()
มูฮัมหมัดอามิน

1
@MuhammadAmin, DateTimeไม่ได้เป็นnullableชนิดข้อมูล รหัสของคุณไม่ควรรวบรวมที่คุณจะไม่สามารถที่จะกำหนดค่าพารามิเตอร์ของชนิดnull DateTimeบางทีคุณควรเปลี่ยนไปหรือใช้ค่าที่แตกต่างกันสำหรับการเริ่มต้นเช่นDateTime? DateTime.Now
Ivaylo Slavov

1
@IvayloSlavov DateTime.Now ไม่ใช่ค่าคงที่เวลารวบรวมดังนั้นจึงไม่สามารถกำหนดเป็นพารามิเตอร์เริ่มต้นได้
GiriB

@GiriB คุณพูดถูก Datetime.Nowไม่สามารถใช้ในการเริ่มต้นพารามิเตอร์เริ่มต้นฉันยืนแก้ไข
Ivaylo Slavov

1

หากคุณต้องการส่งผ่านพารามิเตอร์หลายตัวคุณสามารถสร้างแบบจำลองแทนการส่งผ่านพารามิเตอร์หลายตัว

ในกรณีที่คุณไม่ต้องการที่จะผ่านพารามิเตอร์ใด ๆ แล้วคุณสามารถข้ามเช่นกันในนั้นและรหัสของคุณจะดูเรียบร้อยและสะอาด


1
สิ่งนี้เป็นจริงเฉพาะสำหรับพารามิเตอร์ POST ในคำขอร่างกาย - พารามิเตอร์ใน URL ยังสามารถอ้างอิงเป็นอาร์กิวเมนต์ได้ทีละรายการ
นาธาน

1

ไม่สามารถระบุค่าเริ่มต้นสำหรับพารามิเตอร์ที่ไม่ได้ประกาศ ' optional'

 Function GetFindBooks(id As Integer, ByVal pid As Integer, Optional sort As String = "DESC", Optional limit As Integer = 99)

ในตัวคุณ WebApiConfig

 config.Routes.MapHttpRoute( _
          name:="books", _
          routeTemplate:="api/{controller}/{action}/{id}/{pid}/{sort}/{limit}", _
          defaults:=New With {.id = RouteParameter.Optional, .pid = RouteParameter.Optional, .sort = UrlParameter.Optional, .limit = UrlParameter.Optional} _
      )

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