ตรวจสอบว่า HttpStatusCode แสดงถึงความสำเร็จหรือล้มเหลว


94

สมมติว่าฉันมีตัวแปรต่อไปนี้:

System.Net.HttpStatusCode status = System.Net.HttpStatusCode.OK;

ฉันจะตรวจสอบได้อย่างไรว่านี่เป็นรหัสสถานะความสำเร็จหรือรหัสล้มเหลว

ตัวอย่างเช่นฉันสามารถทำสิ่งต่อไปนี้:

int code = (int)status;
if(code >= 200 && code < 300) {
    //Success
}

ฉันสามารถมีรายการสีขาวบางประเภท:

HttpStatusCode[] successStatus = new HttpStatusCode[] {
     HttpStatusCode.OK,
     HttpStatusCode.Created,
     HttpStatusCode.Accepted,
     HttpStatusCode.NonAuthoritativeInformation,
     HttpStatusCode.NoContent,
     HttpStatusCode.ResetContent,
     HttpStatusCode.PartialContent
};
if(successStatus.Contains(status)) //LINQ
{
    //Success
}

ทางเลือกเหล่านี้ไม่มีทางเลือกใดที่ทำให้ฉันมั่นใจและฉันหวังว่าจะมีคลาส. NET หรือวิธีการที่สามารถทำงานนี้ให้ฉันได้เช่น:

bool isSuccess = HttpUtilities.IsSuccess(status);

คุณต้องทำint code = (int)Response.StatusCodeจากตรงนั้นคุณจะต้องสร้างEnumเช็คของคุณเองที่นี่สำหรับตัวอย่างการทำงานstackoverflow.com/questions/1330856/…
MethodMan

คุณมีโอกาสที่จะใช้HttpClientชั้นเรียนหรือไม่?
dcastro

1
@dcastro ไม่ฉันขอโทษ ฉันใช้API ระดับสูงที่อาจ (หรือไม่ก็ได้) ใช้เป็นการภายใน API เปิดเผยรหัสสถานะของการตอบกลับ แต่ไม่เปิดเผยภายในHttpResponseMessageเช่น
Matias Cicero

@MatiCicero แย่เกินไป: / คุณสามารถใช้การใช้งานซ้ำได้ตลอดเวลาHttpResponseMessage.IsSuccessStatusCode(ดูคำตอบของฉัน) ซึ่งเหมือนกับวิธีแรกของคุณHttpStatusCodeทุกประการและทำให้เป็นวิธีการขยายในประเภท
dcastro

คำตอบ:


177

หากคุณกำลังใช้HttpClientชั้นเรียนคุณจะได้รับHttpResponseMessageคืน

คลาสนี้มีคุณสมบัติที่มีประโยชน์ที่เรียกว่าIsSuccessStatusCodeซึ่งจะทำการตรวจสอบให้คุณ

using (var client = new HttpClient())
{
    var response = await client.PostAsync(uri, content);
    if (response.IsSuccessStatusCode)
    {
        //...
    }
}

ในกรณีที่คุณสงสัยคุณสมบัตินี้จะใช้งานเป็น:

public bool IsSuccessStatusCode
{
    get { return ((int)statusCode >= 200) && ((int)statusCode <= 299); }
}

ดังนั้นคุณสามารถใช้อัลกอริทึมนี้ซ้ำได้หากคุณไม่ได้ใช้HttpClientโดยตรง

คุณยังสามารถใช้EnsureSuccessStatusCodeเพื่อโยนข้อยกเว้นในกรณีที่การตอบกลับไม่สำเร็จ


1
FYI: เป็น 'response.IsSuccessful' สำหรับฉัน
Topher เกิด

คำตอบของคุณมีประโยชน์มาก แต่ตอนนี้ได้ผลเช่น if (response.IsCompletedSuccessfully) {//}
salman

12

คลาส HttpResponseMessage มีคุณสมบัติ IsSuccessStatusCode โดยดูที่ซอร์สโค้ดจะเป็นเช่นนี้ตามที่ usr ได้แนะนำไว้แล้ว 200-299 น่าจะดีที่สุดที่คุณสามารถทำได้

public bool IsSuccessStatusCode
{
    get { return ((int)statusCode >= 200) && ((int)statusCode <= 299); }
}

11

คำตอบที่ได้รับการยอมรับทำให้ฉันรำคาญเล็กน้อยเนื่องจากมีตัวเลขวิเศษ (แม้ว่าจะอยู่ในมาตรฐาน) ในส่วนที่สอง และส่วนแรกไม่ใช่รหัสสถานะจำนวนเต็มธรรมดาทั่วไปแม้ว่าจะใกล้เคียงกับคำตอบของฉันก็ตาม

คุณสามารถบรรลุผลลัพธ์เดียวกันโดยการสร้างอินสแตนซ์ HttpResponseMessage ด้วยรหัสสถานะของคุณและตรวจสอบความสำเร็จ จะโยนข้อยกเว้นของอาร์กิวเมนต์หากค่าน้อยกว่าศูนย์หรือมากกว่า 999

if (new HttpResponseMessage((HttpStatusCode)statusCode).IsSuccessStatusCode)
{
    // ...
}

สิ่งนี้ไม่ได้กระชับ แต่คุณสามารถทำให้เป็นส่วนขยายได้


สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉันเนื่องจากฉันมีเพียง HttpStatusCode ไม่ใช่ข้อความตอบกลับ เก่งมาก!
Todd Vance

5
"คำตอบที่ได้รับการยอมรับทำให้ฉันรำคาญเล็กน้อยเนื่องจากมีตัวเลขวิเศษ (แม้ว่าจะอยู่ในเกณฑ์มาตรฐานก็ตาม)" - ไม่ใช่ "เวทมนตร์" หากเป็นแบบมาตรฐานเข้าใจดีและไม่มีวันเปลี่ยนแปลง ไม่มีอะไรผิดปกติกับการใช้รหัสโดยตรง ถ้าคุณมีIsSuccessStatusCodeดีมากให้ใช้มัน (ตามที่คำตอบที่ยอมรับบอกไว้) มิฉะนั้นอย่าเพิ่มปมของคุณเองโดยใช้สิ่งที่เป็นนามธรรมเว้นแต่คุณจะทำการตรวจสอบนี้ทั่วทุกแห่ง
Ed S.

1
มีในใจว่าอินสแตนซ์จะใช้หนึ่งในคุณสมบัติของมันต้องใช้เวลามากกว่าการตรวจสอบเงื่อนไขที่สองตรรกะกับHttpResponseMessage int
มิโรเจ

10

การเพิ่มคำตอบ @TomDoesCode หากคุณใช้ HttpWebResponse คุณสามารถเพิ่มวิธีการขยายนี้:

public static bool IsSuccessStatusCode(this HttpWebResponse httpWebResponse)
{
    return ((int)httpWebResponse.StatusCode >= 200) && ((int)httpWebResponse.StatusCode <= 299);
}

8

ฉันเป็นส่วนหนึ่งของวิธีการขยายที่สามารถค้นพบได้

public static class HttpStatusCodeExtensions
{
    public static bool IsSuccessStatusCode(this HttpStatusCode statusCode)
    {
        var asInt = (int)statusCode;
        return asInt >= 200 && asInt <= 299;
    }
}

ตราบใดที่เนมสเปซของคุณอยู่ในขอบเขตการใช้งานก็จะเป็นstatusCode.IsSuccessStatusCode()เช่นนั้น


วิธีการขยายนั้นยอดเยี่ยม แต่ฉันสับสน - สิ่งนี้ไม่ได้ทำเช่นเดียวกับคุณสมบัติ IsSuccessStatusCode ของ HTTPResponseMessage ที่ใช้กับ HTTPClient หรือ IHTTPClientFactory ใช่หรือไม่ @DCastro ยังแสดงให้เราเห็นว่ามีการใช้งานเช่นนี้ใน. NET เมื่อใด / ทำไมฉันจึงใช้วิธีการขยายเช่นนี้สำหรับรหัสสถานะ HTTP ในช่วง 2xx
sfors กล่าวว่าคืนสถานะ Monica

4
@sfors ใช่ แต่ถ้าคุณมีHttpStatusCodeขอบเขตเท่านั้นล่ะ? มีไลบรารีมากมายที่ไม่ได้ใช้หรือแสดงHttpResponseMessageแต่ให้รหัสสถานะแก่คุณ
bojingo

3

ขึ้นอยู่กับทรัพยากร HTTP ที่คุณเรียกใช้ โดยปกติแล้ว2xxช่วงจะถูกกำหนดให้เป็นช่วงของรหัสสถานะความสำเร็จ นั่นเป็นข้อตกลงที่ชัดเจนว่าไม่ใช่ทุกเซิร์ฟเวอร์ HTTP ที่จะปฏิบัติตาม

ตัวอย่างเช่นการส่งแบบฟอร์มบนเว็บไซต์มักจะส่งคืนการเปลี่ยนเส้นทาง 302

หากคุณต้องการคิดค้นวิธีการทั่วไปcode >= 200 && code < 300แนวคิดนี้น่าจะเป็นภาพที่ดีที่สุดของคุณ

หากคุณกำลังเรียกใช้เซิร์ฟเวอร์ของคุณเองคุณควรตรวจสอบให้แน่ใจว่าคุณได้สร้างมาตรฐาน200แล้ว


2

นี่คือส่วนขยายของคำตอบก่อนหน้านี้ที่หลีกเลี่ยงการสร้างและการรวบรวมขยะในภายหลังของวัตถุใหม่สำหรับการเรียกแต่ละครั้ง

public static class StatusCodeExtensions
{
    private static readonly ConcurrentDictionary<HttpStatusCode, bool> IsSuccessStatusCode = new ConcurrentDictionary<HttpStatusCode, bool>();
    public static bool IsSuccess(this HttpStatusCode statusCode) => IsSuccessStatusCode.GetOrAdd(statusCode, c => new HttpResponseMessage(c).IsSuccessStatusCode);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.