วิธีรับข้อมูลข้อผิดพลาดเมื่อ HttpWebRequest.GetResponse () ล้มเหลว


87

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

รหัส:

try
{
    HttpWebRequest webRequest = HttpWebRequest.Create(URL) as HttpWebRequest;
    webRequest.Method = WebRequestMethods.Http.Get;
    webRequest.Credentials = new NetworkCredential(Username, Password);
    webRequest.ContentType = "application/x-www-form-urlencoded";
    using(HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse)
    {
        if(response.StatusCode == HttpStatusCode.OK)
        {
            // Do stuff with response.GetResponseStream();
        }
    }
}
catch(Exception ex)
{
    ShowError(ex);
    // if the server returns a 500 error than the webRequest.GetResponse() method
    // throws an exception and all I get is "The remote server returned an error: (500)."
}

ความช่วยเหลือใด ๆ เกี่ยวกับเรื่องนี้จะได้รับการชื่นชมมาก


ฉันจะเพิ่มสิ่งนี้เสมอขอแนะนำให้ย่อเนื้อหาที่ห่อด้วยtryคำสั่ง ในกรณีของคุณทุกอย่างจนถึงusingบรรทัดอาจถูกเขียนไว้ภายนอก
SSHunter49

คำตอบ:


153

เป็นไปได้ไหมโดยใช้ HttpWebRequest และ HttpWebResponse

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

ดังนั้นคุณสามารถตรวจจับWebExceptionซึ่งเป็นสิ่งที่จะถูกโยนหากส่งคืนรหัสสถานะที่ไม่ใช่ 200 จากเซิร์ฟเวอร์และอ่านเนื้อหา:

catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    using (var reader = new StreamReader(stream))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
}
catch (Exception ex)
{
    // Something more serious happened
    // like for example you don't have network access
    // we cannot talk about a server exception here as
    // the server probably was never reached
}

ขอขอบคุณ! สิ่งสำคัญที่ควรทราบว่าสตรีมจากภายในคำสั่งการใช้จะไม่สามารถใช้งานได้นอกคำสั่งการใช้เนื่องจากตัวกำจัดของ WebResponse จะล้างออก สิ่งนี้ทำให้ฉันสะดุดไม่กี่นาที
ธ อริน

@ ธ อริน. "กระแส" จากคำสั่งแรกจะถูกส่งต่อไปยังคำสั่งถัดไป เช่นเดียวกับในคำสั่ง IF บรรทัดเดียวตัวอย่างเช่น if (something) do-stuff-here;
RealityDysfunction

1
GetRequestStreamและGetResponseสามารถโยนข้อยกเว้น ?
PreguntonCojoneroCabrón

@ PreguntonCojoneroCabrónใช่ดูเหมือนจะไม่ถูกต้องนัก โชคดีที่ Microsoft เปิดตัว HttpClient-class ซึ่งฉันสงสัยว่าส่วนใหญ่ใช้งานอยู่ในปัจจุบัน msdn.microsoft.com/en-us/library/…
Morten Nørgaard

8

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

Responseทรัพย์สินในWebExceptionจะเป็นชนิดFtpWebResponseที่คุณสามารถตรวจสอบของStatusCodeสถานที่ให้บริการที่จะเห็นซึ่งข้อผิดพลาด FTPคุณมี

นี่คือรหัสที่ฉันลงเอยด้วย:

    public static bool FileExists(string host, string username, string password, string filename)
    {
        // create FTP request
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + host + "/" + filename);
        request.Credentials = new NetworkCredential(username, password);

        // we want to get date stamp - to see if the file exists
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;

        try
        {
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            var lastModified = response.LastModified;

            // if we get the last modified date then the file exists
            return true;
        }
        catch (WebException ex)
        {
            var ftpResponse = (FtpWebResponse)ex.Response;

            // if the status code is 'file unavailable' then the file doesn't exist
            // may be different depending upon FTP server software
            if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                return false;
            }

            // some other error - like maybe internet is down
            throw;
        }
    }

4

ฉันเผชิญกับสถานการณ์ที่คล้ายกัน:

ฉันพยายามอ่านการตอบกลับดิบในกรณีที่เกิดข้อผิดพลาด HTTP ที่ใช้บริการ SOAP โดยใช้ BasicHTTPBinding

อย่างไรก็ตามเมื่ออ่านคำตอบโดยใช้GetResponseStream()พบข้อผิดพลาด:

ไม่สามารถอ่านสตรีมได้

ดังนั้นรหัสนี้ใช้ได้กับฉัน:

try
{
    response = basicHTTPBindingClient.CallOperation(request);
}
catch (ProtocolException exception)
{
    var webException = exception.InnerException as WebException;
    var rawResponse = string.Empty;

    var alreadyClosedStream = webException.Response.GetResponseStream() as MemoryStream;
    using (var brandNewStream = new MemoryStream(alreadyClosedStream.ToArray()))
    using (var reader = new StreamReader(brandNewStream))
        rawResponse = reader.ReadToEnd();
}

0

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

ตัวอย่างว่าโค้ดของคุณจะเป็นอย่างไรเมื่อใช้ Wrapper นี้ทำได้ง่ายๆ

    var response = httpClient.Get<SomeResponseObject>(request);
    
    if(response.StatusCode == HttpStatusCode.OK)
    {
        //do something with the response
        console.Writeline(response.Body.Id); //where the body param matches the object you pass in as an anonymous type.  
    }else {
         //do something with the error
         console.Writelint(string.Format("{0}: {1}", response.StatusCode.ToString(), response.ErrorMessage);

    }

การเปิดเผยข้อมูลทั้งหมด ไลบรารีนี้เป็นไลบรารี Wrapper แบบโอเพนซอร์สฟรีและฉันเป็นผู้เขียนไลบรารีดังกล่าว ฉันไม่ได้ทำเงินจากสิ่งนี้ แต่พบว่ามีประโยชน์อย่างมากในช่วงหลายปีที่ผ่านมาและมั่นใจว่าทุกคนที่ยังคงใช้คลาส HttpWebRequest / HttpWebResponse ก็เช่นกัน

ไม่ใช่สัญลักษณ์แสดงหัวข้อย่อยเงิน แต่รองรับการรับโพสต์ลบด้วยทั้งแบบ async และ non-async สำหรับรับและโพสต์รวมถึงคำขอและการตอบกลับของ JSON หรือ XML กำลังได้รับการบำรุงรักษาอย่างแข็งขัน ณ วันที่ 21 มิถุนายน พ.ศ. 2563


-3
HttpWebRequest myHttprequest = null;
HttpWebResponse myHttpresponse = null;
myHttpRequest = (HttpWebRequest)WebRequest.Create(URL);
myHttpRequest.Method = "POST";
myHttpRequest.ContentType = "application/x-www-form-urlencoded";
myHttpRequest.ContentLength = urinfo.Length;
StreamWriter writer = new StreamWriter(myHttprequest.GetRequestStream());
writer.Write(urinfo);
writer.Close();
myHttpresponse = (HttpWebResponse)myHttpRequest.GetResponse();
if (myHttpresponse.StatusCode == HttpStatusCode.OK)
 {
   //Perform necessary action based on response
 }
myHttpresponse.Close(); 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.