ส่งผ่านจำนวนตัวแปรของพารามิเตอร์สตริงการสืบค้นไปยังการดำเนินการของคอนโทรลเลอร์เดี่ยว

ฉันกำลังสร้าง API ที่มีตัวควบคุมที่มีการดำเนินการ GET เดียว:

[Route("api/xxxxx/{param1:int}/{param1:int}")]
public IHttpActionResult Get(int param1, int param2) {
    // method body...
}

URL จะอยู่ในรูปแบบต่อไปนี้:

/api/xxxxx/1/1?p1=5&p2=hello&p3=20161108
/api/xxxxx/1/1?p1=active

หมายเลขและชื่อของพารามิเตอร์สตริงการสืบค้นจะแตกต่างกันไป

ฉันต้องการส่งพารามิเตอร์สตริงการสืบค้นไปยังวิธีการควบคุม แต่ฉันไม่สามารถฮาร์ดโค้ดลงในลายเซ็นวิธีการได้ เนื่องจากชื่อและตัวเลขที่แตกต่างกัน มีวิธีการทำเช่นนี้หรือไม่? ฉันได้ลองโทร var qsParams = ControllerContext.Request.GetQueryNameValuePairs(); แล้ว แต่ได้รับข้อผิดพลาดไม่พบทรัพยากรเมื่อพยายามขอ URL ใด ๆ ด้วยสตริงการสืบค้น โดยพิจารณาจากแอตทริบิวต์ Route ที่แสดงด้านบน

ฉันพบทางเลือกหนึ่ง: ใช้ค่าเส้นทางแทนพารามิเตอร์สตริงการสืบค้น จากนั้นใช้ catch-all {*tags} และส่งผ่านเป็นพารามิเตอร์เมธอด:

[Route("api/xxxxx/{param1:int}/{param1:int}/{*tags}")]
public IHttpActionResult Get(int param1, int param2, string tags) {
    // method body...
}

ด้วย URL ในรูปแบบ

/api/xxxxx/1/1/5/john/20161108
/api/xxxxx/1/1/active

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

ดังนั้น ฉันจะส่งพารามิเตอร์สตริงการสืบค้นตัวแปรไปยังการดำเนินการของคอนโทรลเลอร์ได้อย่างไร ฉันพูดว่า "ส่ง" พารามิเตอร์ แต่ไม่จำเป็นต้องส่งผ่านเป็นพารามิเตอร์ของวิธีการ ตราบใดที่ฉันสามารถเข้าถึงพารามิเตอร์สตริงการสืบค้นจากเนื้อหาของวิธีการ ในขณะที่รับ URL ที่มีสตริงการสืบค้นเพื่อแก้ไขเป็น การกระทำที่เป็นปัญหา

แก้ไข:

เป็นที่น่าสังเกตว่าการสร้างวิธีดำเนินการหลายวิธีสำหรับชุดพารามิเตอร์ทุกชุดที่เป็นไปได้นั้นไม่ใช่ตัวเลือก

แก้ไข 2:

ฉันเห็นวิธีแก้ปัญหาโดยตรงสองวิธี หากเป็นไปได้:

  1. ส่งผ่านสตริงการสืบค้นทั้งหมดไปยังวิธีการดำเนินการเป็นพารามิเตอร์สตริงเดียว ฉันสามารถแยกสตริงการสืบค้นด้วยตนเองได้
  2. สามารถใช้ ControllerContext.Request.GetQueryNameValuePairs() ภายในเนื้อหาของเมธอดได้ โดยไม่ได้เพิ่มพารามิเตอร์ที่เกี่ยวข้องให้กับลายเซ็นของเมธอด

อย่างไรก็ตาม ฉันไม่รู้ว่าสองสิ่งนี้เป็นไปได้หรือไม่ แม้ว่าดูเหมือนว่าจะเป็นไปได้อย่างใดอย่างหนึ่งหรือทั้งสองอย่างก็ตาม


person neizan    schedule 08.11.2016    source แหล่งที่มา


คำตอบ (2)


หากคุณต้องการส่งเอนทิตีไปยังคอนโทรลเลอร์ของคุณ คุณสามารถรับมันได้โดย [FromBody] คิดว่าเอนทิตีเป็นวิธีที่ง่ายที่สุดในการส่งผ่าน

F.e.

[HttpPost]
[Route("api/xxxxx/send")]
public void SendReuqest([FromBody] Entity name)

หวังว่าจะเข้าใจปัญหาของคุณถูกต้อง

person Xivo    schedule 08.11.2016
comment
ฉันไม่มี POST มีแต่ GET นอกจากนี้ ดูเหมือนว่าจะเปลี่ยนปัญหาไปที่เอนทิตีเท่านั้น นั่นคือตอนนี้กรอบงานจะพยายามแมปพารามิเตอร์กับเอนทิตี แต่เอนทิตีจะต้องกำหนดพารามิเตอร์เป็นคุณสมบัติ ดังนั้นเอนทิตีจะต้องมีชื่อและจำนวนคุณสมบัติที่แตกต่างกันเพื่อแมป ซึ่งเป็นปัญหาเดียวกันกับเมื่อก่อน แต่ตอนนี้กำลังพยายามระบุในคลาสเอนทิตี อย่างไรก็ตาม ฉันไม่ได้ใช้ Entity Framework - person neizan; 08.11.2016

ฉันกำลังโพสต์คำตอบสำหรับเอกสารทางเลือกอื่นที่ฉันคิดขึ้นมา ฉันรู้ว่าสิ่งเหล่านี้บางส่วน (ทั้งหมด?) จะแฮ็กได้ อย่างไรก็ตาม...

คำตอบ
ใช้วิธี GetQueryNameValuePairs นี่เป็นสิ่งแรกสุดที่ฉันลอง แต่ฉันต้องมีบางอย่างที่แตกต่างออกไปในแอตทริบิวต์เส้นทางหรือลายเซ็นวิธีการ เนื่องจากฉันได้รับข้อผิดพลาด "ไม่พบ" มาก่อน อย่างไรก็ตาม ตอนนี้มันทำงานได้อย่างสมบูรณ์แล้ว นี่ทำให้คำถามและคำตอบทั้งหมดนี้เป็นเรื่องที่น่าสงสัยสำหรับฉัน

URL ตัวอย่าง:

/api/xxxxx/1/1?p1=5&p2=john&p3=20161108

การกระทำ:

[Route("api/xxxxx/{param1:int}/{param1:int}")]
public IHttpActionResult Get(int param1, int param2) {
    var qsParams = ControllerContext.Request.GetQueryNameValuePairs();
    // rest of method body...
}

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

URL ตัวอย่าง:

/api/xxxxx/1/1?qs=p1~5|p2~john|p3~20161108

การกระทำ:

[Route("api/xxxxx/{param1:int}/{param1:int}")]
public IHttpActionResult Get(int param1, int param2, string qs) {
    string[] qsParamsArray = qs.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
    IDictionary<string, string> qsParams = new Dictionary<string, string>();
    foreach (string p in qsParamsArray) {
        string[] kv = p.Split(new string[] { "~" }, StringSplitOptions.None);
        if (String.IsNullOrWhiteSpace(kv[0])) {
            return NotFound();
        }
        qsParams.Add(kv[0], kv[1]);
    }
    // Use qsParams as desired...
}

ตัวเลือก 2
ใส่พารามิเตอร์สตริงการสืบค้นในเส้นทางแทนสตริงการสืบค้น ต้องอาศัยการเรียงลำดับพารามิเตอร์

URL ตัวอย่าง:

/api/xxxxx/1/1/5/john/20161108

การกระทำ:

[Route("api/xxxxx/{param1:int}/{param1:int}/{*tags}")]
public IHttpActionResult Get(int param1, int param2, string tags) {
    // parse the "tags" parameter here...
    // rest of method body...
}

ตัวเลือก 3
ฮาร์ดโค้ดจำนวนสูงสุดของพารามิเตอร์ทางเลือกที่มีชื่อทั่วไป และพารามิเตอร์สตริงการสืบค้นเฉพาะสำหรับทั้งชื่อและค่าของพารามิเตอร์

URL ตัวอย่าง:

/api/xxxxx/1/1?name1=p1&value1=5&name2=p2&value2=john&name3=p3&value3=20161108

การกระทำ:

[Route("api/xxxxx/{param1:int}/{param1:int}")]
public IHttpActionResult Get(
    int param1, 
    int param2, 
    string name1 = null, 
    string value1 = null, 
    string name2 = null, 
    string value2 = null, 
    string name3 = null, 
    string value3 = null, 
    string name4 = null, 
    string value4 = null, 
    ..., 
    string nameNMAX = null, 
    string valueNMAX = null
) {
    // method body...
}
person neizan    schedule 08.11.2016