404를 어떻게 잡을 수 있습니까?


93

다음 코드가 있습니다.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "HEAD";
request.Credentials = MyCredentialCache;

try
{
    request.GetResponse();
}
catch
{
}

특정 404 오류를 어떻게 잡을 수 있습니까? WebExceptionStatus.ProtocolError는 오류가 발생했음을 감지 만 할 수 있지만 오류의 정확한 코드를 제공하지는 않습니다.

예를 들면 :

catch (WebException ex)
{
    if (ex.Status != WebExceptionStatus.ProtocolError)
    {
        throw ex;
    }
}

충분히 유용하지 않습니다 ... 프로토콜 예외는 401, 503, 403이 될 수 있습니다.


13
NNNOOOOOOOOOOOOO! 포착하지 말고 System.Exception핸들러의 예외 텍스트에 의존 하지 마십시오 !
Aaronaught 2010-01-28

2
John Saunders의 대답이 가장 완벽했습니다. 나는 사람들이 악의로 그를 반대 투표했다고 생각합니다.
Aaronaught 2010-01-28

3
을 사용하지 마십시오 throw ex. 빈 호출 스택이있는 새 예외가 생성됩니다. 사용하십시오 throw.
krbnr 2014

1
나는 항상 이것이 좌절감을 느꼈습니다. 올바른 형식의 응답을 받고 프로토콜 오류 메시지가 확실히 올바른 형식 인 경우 예외가 발생해서는 안됩니다. 클래스는 사용자가 결과를 해석하고 그에 따라 행동 할 수 있도록해야합니다.
Jeremy Holovacs

@JeremyHolovacs 예외는 더 이상 최신 http 클라이언트에서 404와 같은 항목에 대해 발생하지 않습니다. "제어 흐름에 대한 예외를 사용하지 마십시오"건설 팀 살아 남기 위해 보이지 않았다WebRequest
매트 Kocaj을

답변:


113

를 사용하여 HttpStatusCode Enumeration특히,HttpStatusCode.NotFound

다음과 같은 것 :

HttpWebResponse errorResponse = we.Response as HttpWebResponse;
if (errorResponse.StatusCode == HttpStatusCode.NotFound) {
  //
}

어디
we입니다 WebException.


나만의 조회 목록을 만들지 않고도 개체에서 NUMBER를 가져올 수 있습니까? 다음과 같은 것을 갖고 싶습니다. int httpresponsecode = HttpStatusCode.ToInt () 또는 이와 유사한 것이므로 404
BerggreenDK

2
@BerggreenDK 당신이 할 수 있어야합니다 int httpresonsecode = (int) HttpStatusCode.NotFound
Trev

7
내 고대 downvote -1 부분 설명 : 어떤 이유로, 경우 코드는 NullReferenceException 발생 we.Response하지 않습니다 HttpWebResponse. 코드가 항상 그 유형을 가질 것이라고 가정하고 싶다면 간단히 캐스트해야합니다 : HttpWebResponse errorResponse = (HttpWebResponse)we.Response;. 이 명시 적으로 발생합니다 InvalidCastException불가능한 대신 신비의, 발생하는 경우 NullReferenceException.
John Saunders

내가 얻을 An object reference is required for the non-static field, method, or property 'WebException.Response'이 코드를 사용.
Jamie

122
try
{
    var request = WebRequest.Create(uri);
    using (var response = request.GetResponse())
    {
        using (var responseStream = response.GetResponseStream())
        {
            // Process the stream
        }
    }
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError &&
        ex.Response != null)
    {
        var resp = (HttpWebResponse) ex.Response;
        if (resp.StatusCode == HttpStatusCode.NotFound)
        {
            // Do something
        }
        else
        {
            // Do something else
        }
    }
    else
    {
        // Do something else
    }
}

10
lol @ IDisposable 경찰이며 using 블록에서 응답을 래핑하지 않은 모든 사람에게 -1을 제공합니다.
Rich

2
힘든 일이지만 누군가 는해야합니다. OTOH, 나는이 대답을 거의 추가하지 않았습니다. 왜냐하면 내가 다른 사람들에게 최고의 대답으로 만들기 위해 소리를 지르는 것처럼 보일 수 있기 때문입니다.
John Saunders

3
나는 실제로 upvoted했지만 한 가지 발견했습니다. 아마도 throw당신의 끝에 (재 투입) 이 있어야 합니다 catch. 그렇지 않으면 다른 유형의 WebException.
Aaronaught 2010-01-28

@John Saunders : 요청에 대해서도 사용하지 않는 이유는 무엇입니까?
Joel Etherton

1
@Joel : WebRequest구현하지 않습니다 IDisposable.
John Saunders

23

C # 6에서는 예외 필터를 사용할 수 있습니다 .

try
{
    var request = WebRequest.Create(uri);
    using (var response = request.GetResponse())
    using (var responseStream = response.GetResponseStream())
    {
        // Process the stream
    }
}
catch(WebException ex) when ((ex.Response as HttpWebResponse)?.StatusCode == HttpStatusCode.NotFound)
{
    // handle 404 exceptions
}
catch (WebException ex)
{
    // handle other web exceptions
}

내가 간과했던 매우 멋진 기능! 나는 다른 사람들이 일반 예외 처리기를 통과하게하면서 401 만 잡는 방법을 계속 찾고 있었다. 이것이 갈 길이다!
Lionet Chen 2017

12

나는 이것을 테스트하지 않았지만 작동합니다.

try
{
    // TODO: Make request.
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError) {
        HttpWebResponse resp = ex.Response as HttpWebResponse;
        if (resp != null && resp.StatusCode == HttpStatusCode.NotFound)
        {
            // TODO: Handle 404 error.
        }
        else
            throw;
    }
    else
        throw;
}

@John Saunders-OP 코드를 최적화하지 않고 수정했습니다.
MiffTheFox

@John-아마도 나는 그들이 catchOP와 똑같은 코드를 가지고 있었기 때문에 블록 을 복사 / 붙여 넣기를 기대했을 수도 있습니다. OP의 코드 때문에이 질문에 대해 정말로 반대해야합니다.
MiffTheFox

1
@John 우리가 여기서 잊어 버린 것은 샘플 코드입니다. 이것은 GetResponse를 사용하는 방법이 아니라 404에 대한 또 다른 방법 인 경우입니다. -1은 좀 거친 것 같습니다. 질문에 답한 미프에게 +1.
David Basarab

@John 나는 당신이 코멘트에서 지적하는 것이 좋다고 생각합니다. 다운 투표를 보는 방식은 주어진 코드로 문제가 해결되지 않는 경우입니다. 반대표를 제거 해주셔서 감사합니다.
David Basarab

@John-좋아, 나는 잡힌 것 외에 모든 것을 제거했다.
MiffTheFox

4

당신이 잡을 경우 생각 WebException이를 가 ... 내가 어떤 사람을 아는에 관심이있을 거라고 나는 순간에 알고있는 유일한 방법이다 (404) 인 경우를 판별하는 데 사용할 수있는 거기에 몇 가지 정보가 ...

catch(WebException e) {
    if(e.Status == WebExceptionStatus.ProtocolError) {
        var statusCode = (HttpWebResponse)e.Response).StatusCode);
        var description = (HttpWebResponse)e.Response).StatusDescription);
    }
}

2

이 snipit을 확인하십시오. GetResponse는 WebRequestException을 발생시킵니다. 그것을 포착하면 응답에서 상태 코드를 얻을 수 있습니다.

try {
   // Create a web request for an invalid site. Substitute the "invalid site" strong in the Create call with a invalid name.
     HttpWebRequest myHttpWebRequest = (HttpWebRequest) WebRequest.Create("invalid site");

    // Get the associated response for the above request.
     HttpWebResponse myHttpWebResponse = (HttpWebResponse) myHttpWebRequest.GetResponse();
    myHttpWebResponse.Close();
}
catch(WebException e) {
    Console.WriteLine("This program is expected to throw WebException on successful run."+
                        "\n\nException Message :" + e.Message);
    if(e.Status == WebExceptionStatus.ProtocolError) {
        Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
        Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
    }
}
catch(Exception e) {
    Console.WriteLine(e.Message);
}

이것은 http://msdn.microsoft.com/en-us/library/system.net.webexception.status.aspx 에서 왔습니다 .


2

적절한 예외 유형을 포착하십시오 WebException.

try
{
    var request = (HttpWebRequest) WebRequest.Create(String.Format("http://www.gravatar.com/avatar/{0}?d=404", hashe));

    using(var response = (HttpWebResponse)request.GetResponse())
        Response.Write("has avatar");
}
catch(WebException e) 
{
  if(e.Response.StatusCode == 404) 
    Response.Write("No avatar");
}

@John Saunders 나는 거기에서 당신과 토론하지 않습니다. 그러나 그것은 질문이 아니 었습니다. 그는 404를 캡처하는 가장 좋은 방법을 물었습니다. 가능한.
Nick Craver

@John Saunders : 고정, "이게 가장 효율적인 경우"가 질문에 적용되는 것으로 가정합니다.
Nick Craver

에 액세스하기 전에 e.Responseas 를 캐스팅 HttpWebResponse해야했습니다 StatusCode.
Lankymart

2

응답 상태에 대해서는 MSDN 에서 참조하십시오 .

...
catch(WebException e) {
  Console.WriteLine("The following error occured : {0}",e.Status);  
}
...

2
@John Saunders-MSDN (샘플을 복사 한 ...)에 전달하게되어 기쁩니다. 이 코드의 목적은 가능한 한 효율적이지 않고 StatusCode의 사용법을 표시하는 것입니다.
Dror

2
@ 존 손더스 - 난 그냥 :-) 당신을 위해, 내가 보여주고 싶었다 부분 만 남아
인 Dror

2

이것을 브라우징하는 VB.NET 사람들을 위해, 나는 그것이 진정으로 404 인 경우에만 예외를 잡을 수 있다고 믿는다.

Try
    httpWebrequest.GetResponse()
Catch we As WebException When we.Response IsNot Nothing _
                              AndAlso TypeOf we.Response Is HttpWebResponse _
                              AndAlso (DirectCast(we.Response, HttpWebResponse).StatusCode = HttpStatusCode.NotFound)

    ' ...

End Try

1

WebRequest 클래스를 사용하여 서버에 POST 또는 GET 데이터를 전송하면 예외 유형은 WebException이됩니다. 다음은 파일을 찾을 수 없음 예외에 대한 코드입니다.

        //Create a web request with the specified URL
            string path = @"http://localhost/test.xml1";
            WebRequest myWebRequest = WebRequest.Create(path);

       //Senda a web request and wait for response.
                try
                {
                    WebResponse objwebResponse = myWebRequest.GetResponse();
                    Stream stream= objwebResponse.GetResponseStream();

                }
                catch (WebException ex) {
                    if (((HttpWebResponse)(ex.Response)).StatusCode == HttpStatusCode.NotFound) {
                        throw new FileNotFoundException(ex.Message);
                    }

                }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.