ฉันจะส่งพารามิเตอร์หลายตัวไปยัง ASP.Net Web API GET ได้อย่างไร


136

ฉันใช้. Net MVC4 Web API เพื่อ (หวังว่า) จะใช้ api RESTful ฉันต้องผ่านพารามิเตอร์สองสามตัวไปยังระบบและให้มันดำเนินการบางอย่างจากนั้นส่งคืนรายการของวัตถุเป็นผลลัพธ์ โดยเฉพาะฉันกำลังผ่านสองวันและกลับมาบันทึกที่อยู่ระหว่างพวกเขา ฉันยังติดตามระเบียนที่ส่งคืนเพื่อให้การโทรที่ตามมาไม่ได้รับการประมวลผลอีกครั้งในระบบ

ฉันได้พิจารณาแนวทางบางประการแล้ว:

  1. การทำให้พารามิเตอร์เป็นอนุกรมในสตริง JSON เดียวและแยกออกจากกันใน API http://forums.asp.net/t/1807316.aspx/1

  2. ส่งผ่านพารามิเตอร์ในสตริงการสืบค้น
    วิธีที่ดีที่สุดในการส่งพารามิเตอร์การค้นหาหลายรายการไปยัง api พักผ่อนคืออะไร

  3. การกำหนด params ในเส้นทาง: api / controller / date1 / date2

  4. การใช้ POST ที่ให้ฉันผ่านวัตถุโดยมีพารามิเตอร์

  5. ค้นคว้า ODATA ตั้งแต่ Web API (ปัจจุบัน) รองรับ ฉันยังไม่ได้ทำสิ่งนี้มากนักดังนั้นฉันจึงไม่คุ้นเคย

ดูเหมือนว่าวิธีปฏิบัติ REST ที่เหมาะสมจะระบุเมื่อมีการดึงข้อมูลคุณควรใช้ GET อย่างไรก็ตาม GET ก็ควรเป็น nullipotent (ไม่ก่อให้เกิดผลข้างเคียง) และฉันสงสัยว่าการใช้งานเฉพาะของฉันละเมิดว่าเนื่องจากฉันทำเครื่องหมายบันทึกในระบบ API ดังนั้นฉันจึงสร้างผลข้างเคียง

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

ในกรณีใด ๆ สำหรับการใช้งานเฉพาะของฉันตัวเลือกใด (ถ้ามี) ดูดีที่สุด?

คำตอบ:


10

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


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

ตอนนี้ฉันได้นำไปใช้เป็น POST เป็นส่วนใหญ่ด้วยเหตุผลที่คุณพูด - การกระทำเกิดขึ้นและผู้บริโภคตระหนักถึงพวกเขา รวมทั้งดูเหมือนว่าง่ายและยืดหยุ่นที่สุดเมื่อเทียบกับการส่งผ่านข้อมูลที่แตกต่างกัน
sig606

@ sig606: POST เป็นวิธีสำหรับฉัน แต่โปรโตคอลของคุณดูเหมือนจะไม่ปลอดภัย จะเกิดอะไรขึ้นหากมีสิ่งใดเกิดขึ้นและมีการเรียกบันทึกข้อมูลในฝั่งไคลเอ็นต์ แต่ไม่ได้รับการประมวลผลเนื่องจากข้อบกพร่อง คุณจะไม่ส่งคืนอีกต่อไปและลูกค้าจะเหลือข้อมูลที่สูญหาย
LukLed

ตอนนี้ API ของฉันคืนระเบียนหลังจากประมวลผลแล้วเท่านั้น ดังนั้นผู้บริโภคจะผ่านวันที่ API สองวัน บันทึกระหว่างวันที่สองวันนั้นจะได้รับการประมวลผลและทำเครื่องหมาย จากนั้นข้อมูลจะถูกส่งกลับไปยังผู้โทร ฉันคิดว่ามีบางอย่างเกิดขึ้นระหว่างการประมวลผลหรือหลังการประมวลผลก่อนถึงลูกค้าฉันมีปัญหา
sig606

141

AttributeRoutingผมคิดว่าวิธีที่ง่ายที่สุดก็คือการใช้งาน

มันชัดเจนภายในตัวควบคุมของคุณทำไมคุณถึงต้องการสิ่งนี้ในโลกของคุณ WebApiConfigไฟล์

ตัวอย่าง:

    [Route("api/YOURCONTROLLER/{paramOne}/{paramTwo}")]
    public string Get(int paramOne, int paramTwo)
    {
        return "The [Route] with multiple params worked";
    }

{}ชื่อต้องตรงกับพารามิเตอร์ของคุณ

ง่ายเหมือนที่ตอนนี้คุณมีสิ่งที่แยกต่างหากGETที่จัดการหลายพารามิเตอร์ในอินสแตนซ์นี้


12
มันเยี่ยมมาก คนส่วนใหญ่แนะนำให้ตั้งค่าเส้นทางในWebApiConfigไฟล์ แต่สิ่งนี้ดีกว่า
rhyek

4
แน่นอนเรา (คนส่วนใหญ่) แนะนำให้มีพื้นที่การจัดการแบบรวมศูนย์สำหรับการกำหนดค่าของคุณ ในกรณีของ Web APIs (Microsoft หรืออื่น ๆ ) รูปแบบการรวมศูนย์สำหรับ REST เป็นกุญแจสำคัญ การกำหนดเส้นทางแอตทริบิวต์น่ารัก แต่ก็ทำให้ข้อยกเว้นแบบครั้งเดียวดึงดูดเกินไป
David Betz

3
ตกลงฉันต้องอัปเดตคำตอบของฉันจริง มีวิธีที่ดีกว่าในการทำพารามิเตอร์หลายตัวด้วย GET โพสต์สิ่งนี้เมื่อฉันเป็น WebAPI ที่ใหม่กว่าตอนนี้ฉันไม่ได้ใช้ AttributeRouting (เว้นแต่ฉันไม่ต้องการสร้างคอนโทรลเลอร์ใหม่) และส่งพารามิเตอร์ทั้งหมดใน QueryString พวกเขาจะจับคู่โดยอัตโนมัติ อัปเดตเมื่อฉันมีโอกาสดังนั้นผู้คนจะไม่ใช้วิธีเก่ากว่านี้
Mark Pieszak - Trilon.io

มีวิธีการตั้งค่าRouteสำหรับพารามิเตอร์ที่มีชื่อ (เช่นพารามิเตอร์แบบสอบถาม) หรือไม่
Shimmy Weitzhandler

1
หากจำเป็นต้องใช้ชื่อวิธีการดำเนินการสามารถแก้ไขได้เพื่อรองรับ [เส้นทาง ("api / YOURCONTROLLER / Get / {paramOne} / {paramTwo}")] สตริงสาธารณะรับ (int paramOne, int paramTwo) {ส่งคืน "บางสิ่ง"; }
Dash

49

เพียงเพิ่มเส้นทางใหม่ให้กับWebApiConfigรายการ

ตัวอย่างเช่นการโทร:

public IEnumerable<SampleObject> Get(int pageNumber, int pageSize) { ..

เพิ่ม:

config.Routes.MapHttpRoute(
    name: "GetPagedData",
    routeTemplate: "api/{controller}/{pageNumber}/{pageSize}"
);

จากนั้นเพิ่มพารามิเตอร์ไปยังการโทร HTTP:

GET //<service address>/Api/Data/2/10 

10
นี่เป็นคำตอบเดียวที่แสดงรายการชิ้นส่วนทั้งหมด ฉันหวังว่าจะมีคนอธิบายวิธีใช้api/controller?start=date1&end=date2URI ของสไตล์ให้ดีขึ้น
Hot Licks

@Hot Licks คำตอบของ Andrew Veriga ทำงานได้ดีกับอาร์กิวเมนต์สตริงข้อความค้นหา เป็นหลักคุณผูกชื่อสตริงแบบสอบถามเพื่อคุณสมบัติคลาสและส่งพวกเขาไปยังวิธีการของคุณ วิธีการของคุณจะใช้อาร์กิวเมนต์คลาสเดียวที่ทำเครื่องหมายด้วยแอตทริบิวต์ [FromUri] และจะมีอาร์กิวเมนต์สตริงแบบสอบถามของคุณเป็นคุณสมบัติ
David Peterson

สิ่งที่ยอดเยี่ยม ขอบคุณ!
Hugo Nava Kopp

สวัสดี @HotLicks และ Graham คุณคิดว่าคุณสามารถตอบคำถามนี้ได้หรือไม่? ขอบคุณstackoverflow.com/questions/57565318/…

45

ฉันต้องใช้ RESTfull api ซึ่งฉันต้องผ่านพารามิเตอร์ ฉันทำสิ่งนี้โดยส่งพารามิเตอร์ในสตริงการสืบค้นในรูปแบบเดียวกับที่อธิบายโดยตัวอย่างแรกของ Mark "api / controller? start = date1 & end = date2"

ในตัวควบคุมฉันใช้เคล็ดลับจากการแยก URL ใน C #?

// uri: /api/courses
public IEnumerable<Course> Get()
{
    NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
    var system = nvc["System"];
    // BL comes here
    return _courses;
}

ในกรณีของฉันฉันกำลังเรียก WebApi ผ่าน Ajax ดู:

$.ajax({
        url: '/api/DbMetaData',
        type: 'GET',
        data: { system : 'My System',
                searchString: '123' },
        dataType: 'json',
        success: function (data) {
                  $.each(data, function (index, v) {
                  alert(index + ': ' + v.name);
                  });
         },
         statusCode: {
                  404: function () {
                       alert('Failed');
                       }
        }
   });

ฉันหวังว่านี่จะช่วยได้...


2
ผมคิดว่าคุณไม่ได้ใช้เพราะ WebAPI ParameterBinding แผนที่จะสตริงการสืบค้นของคุณเพื่อพารามิเตอร์วิธี API ของคุณโดยอัตโนมัติ ...
EMP

1
ใช่วิธีที่ดีกว่าคือการใช้และแอตทริบิวต์เช่น [เส้นทาง ("api / DbMetaData / {system} / {searchString}")] จากนั้นเพิ่มพารามิเตอร์ที่มีให้กับ Get (ระบบสตริง, สตริง searchString) แล้วเรียกด้วย " ... api / DbMetaData / mysystem / mysearchstring "
Nigel Findlater

ฉันใช้ตัวอย่างของเขาใน WebApi C # MVC ของฉันและทำงานได้ดี ตัวอย่างเช่น +1
Si8

38

ฉันพบทางออกที่ยอดเยี่ยมในhttp://habrahabr.ru/post/164945/

public class ResourceQuery
{
   public string Param1 { get; set; }
   public int OptionalParam2 { get; set; }
}

public class SampleResourceController : ApiController
{
    public SampleResourceModel Get([FromUri] ResourceQuery query)
    {
        // action
    }
}

5
เบาะแสที่นี่คือ [FromUri]
เดินผ่าน

2
แม้ว่าบทความจะเป็นภาษารัสเซีย แต่ @tranceporter นั้นถูกต้อง "FromUri" ดูเหมือนเป็นวิธีที่ดีในการรับพารามิเตอร์จาก url บทความอื่นที่อาจเป็นประโยชน์: asp.net/web-api/overview/formats-and-model-binding/ …
Greg

นี่คือสิ่งที่ฉันทำมานานแล้วและมันก็ใช้งานได้ดีมาก! ฉันขอแนะนำวิธีแก้ปัญหานี้ด้วย
David Peterson

หากคุณโทรหาวิธีช่วยเหลืออื่น (ไม่ใช่Get) คุณยังสามารถใช้งานได้[FromUri]หรือไม่? ฉันไม่สามารถทำงานได้
jocull

8

ใช้GETหรือPOSTจะมีการอธิบายอย่างชัดเจนโดย@LukLed เกี่ยวกับวิธีที่คุณสามารถส่งผ่านพารามิเตอร์ได้ฉันขอแนะนำให้ใช้วิธีที่สอง (ฉันไม่รู้เกี่ยวกับODATAมากนัก)

1. การเรียงพารามิเตอร์ภายในเป็นสตริง JSON เดียวและเลือกแยกกันใน API http://forums.asp.net/t/1807316.aspx/1

นี่ไม่ใช่มิตรกับผู้ใช้และเป็นมิตรกับ SEO

2. ผ่านพารามิเตอร์ในสตริงการสืบค้น วิธีที่ดีที่สุดในการส่งพารามิเตอร์การค้นหาหลายรายการไปยัง api พักผ่อนคืออะไร

นี่เป็นวิธีที่นิยมกว่าปกติ

3. กำหนดพารามิเตอร์ในเส้นทาง: api / controller / date1 / date2

นี่ไม่ใช่วิธีการที่ดีอย่างแน่นอน สิ่งนี้ทำให้บางคนรู้สึกว่าdate2เป็นทรัพยากรย่อยdate1และไม่เป็นเช่นนั้น ทั้งสองdate1และdate2มีพารามิเตอร์การค้นหาและมาในระดับเดียวกัน

ในกรณีง่ายๆฉันจะแนะนำ URI เช่นนี้

api/controller?start=date1&end=date2

แต่โดยส่วนตัวฉันชอบรูปแบบ URI ด้านล่าง แต่ในกรณีนี้เราต้องเขียนโค้ดที่กำหนดเองเพื่อแมปพารามิเตอร์

api/controller/date1,date2

อันที่จริงคำอธิบายเหล่านี้มาจากต้นกำเนิดของฉัน ฉันคิดว่า LukLed ปรับแท็กและลิงก์ URL ให้เป็นประกาย
sig606

เท่าที่ SEO ในกรณีนี้มันจะไม่ใช้ รหัสนี้จะเป็น "เซิร์ฟเวอร์ต่อเซิร์ฟเวอร์" ดังนั้นฉันจะไม่สนใจว่าโลกภายนอกเคยค้นพบมัน อันที่จริงฉันต้องทำให้แน่ใจว่าขั้นตอนการรักษาความปลอดภัยที่เหมาะสมถูกนำมาใช้เพื่อหลีกเลี่ยงการเข้าถึงแบบสุ่ม ฉันต้องทำลำดับ JSON สำหรับส่วนอื่นของระบบ (ดูเหมือนจะเป็นข้อผิดพลาดที่พยายามโพสต์รายการใหญ่ของ obj ดังนั้นฉันต้องทำให้เป็นอันดับสตริง) ดังนั้นมันจะไม่ยืดมากในกรณีนี้ .
sig606

1
ฉันหวังว่าคุณมีคำตอบอยู่แล้วทำไมคุณถามคำถาม?
VJAI

2
ขออภัยสำหรับการตอบกลับช้านี้มาร์ก ฉันได้ลองใช้โซลูชันสองสามข้อ แต่ไม่แน่ใจว่าเป็นวิธีที่ดีที่สุดและพยายามใช้วิธีมาตรฐานอุตสาหกรรมดังนั้นฉันจึงโพสต์ที่นี่ดังนั้น
sig606

1
@ Mark ทำอะไรต่อไปนี้เหมือนกัน: stackoverflow.com/questions/9681658/ ...... ?
RredCat


3
 [Route("api/controller/{one}/{two}")]
    public string Get(int One, int Two)
    {
        return "both params of the root link({one},{two}) and Get function parameters (one, two)  should be same ";
    }

ทั้งพารามิเตอร์ของลิงก์รูท ({หนึ่ง}, {สอง}) และรับฟังก์ชั่นพารามิเตอร์ (หนึ่งสอง) ควรเหมือนกัน


2

ฉันรู้ว่ามันเก่าจริง ๆ แต่ฉันต้องการสิ่งเดียวกันเมื่อเร็ว ๆ นี้และนี่คือสิ่งที่ฉันพบ ...

    public HttpResponseMessage Get([FromUri] string var, [FromUri] string test) {
        var retStr = new HttpResponseMessage(HttpStatusCode.OK);
        if (var.ToLower() == "getnew" && test.ToLower() == "test") {
            retStr.Content = new StringContent("Found Test", System.Text.Encoding.UTF8, "text/plain");
        } else {
            retStr.Content = new StringContent("Couldn't Find that test", System.Text.Encoding.UTF8, "text/plain");
        }

        return retStr;
    }

ดังนั้นในที่อยู่ของคุณ / URI / ...

http (s): // myurl / API / MyController / var = getnew และทดสอบ = ทดสอบ

ผล: "การทดสอบที่พบ"


http (s): // myurl / API / MyController / var = getnew และทดสอบ = อะไร

ผลลัพธ์: "ไม่พบการทดสอบนั้น"


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

1
ฉันต้องสร้าง API ของกิจกรรมที่ใช้โดยแอปปฏิทินของบุคคลที่สามซึ่งใช้วิธีการนี้ ฉันดีใจที่พบคำตอบนี้!
clayRay


0
    public HttpResponseMessage Get(int id,string numb)
    {
        //this will differ according to your entity name
        using (MarketEntities entities = new MarketEntities())
        {
          var ent=  entities.Api_For_Test.FirstOrDefault(e => e.ID == id && e.IDNO.ToString()== numb);
            if (ent != null)
            {
                return Request.CreateResponse(HttpStatusCode.OK, ent);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Applicant with ID " + id.ToString() + " not found in the system");
            }
        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.