Detect 404 without catching exceptions

2019-06-26 00:29发布

问题:

Simple function: Check if a webserver returns a non-200 HTTP status.

Private Function RemoteFileOk(ByVal Url As String) As Boolean
  Dim req As HttpWebRequest = TryCast(WebRequest.Create(Url), HttpWebRequest)
  req.Method = "HEAD"
  Dim rsp As HttpWebResponse = TryCast(req.GetResponse(), HttpWebResponse)
  Return (rsp.StatusCode = HttpStatusCode.OK)
End Function

I got it from this answer on "How to check if a file exits on an webserver by its URL?".

Unfortunately, it doesn't work: A System.Net.WebException is thrown, “The remote server returned an error: (404) Not Found” when the url points to a non-existent page. I would like to be able to probe the server with a HEAD request (or something similar) and then deal with the 404 without having to catch exceptions.

My fix looks like this:

Private Function RemoteFileOk(ByVal Url As String) As Boolean
  Dim req As HttpWebRequest = TryCast(WebRequest.Create(Url), HttpWebRequest)
  req.Method = "HEAD"
  Try
    Using rsp As HttpWebResponse = TryCast(req.GetResponse(), HttpWebResponse)
      Return (rsp.StatusCode = HttpStatusCode.OK)
    End Using
  Catch ex As WebException
    Return False
  End Try
End Function

But I never liked using try-catch statements when it seems they could be avoided.

Is there another, neater, way?

回答1:

You can update your code to use the new System.Net.Http API in .net 4.5 which doesn’t throw this vexing exception (see question’s comments). Tested to work under VS 2012u2.

Private Function RemoteFileOk(ByVal Url As String) As Boolean
    Using client As New HttpClient,
        responseTask As Task(Of HttpResponseMessage) = client.GetAsync(Url, HttpCompletionOption.ResponseHeadersRead)
        responseTask.Wait()
        Using response As HttpResponseMessage = responseTask.Result
            Return response.IsSuccessStatusCode
        End Using
    End Using
End Function

This answer was not available when the question was asked and, for many people, is not a solution because this API was introduced in .net 4.5.