Link to home
Start Free TrialLog in
Avatar of sybe
sybe

asked on

Disregarding a "500 internal server error" in a webservice

My application uses an external webservice. That webservice has two methods: checksubscription and activatesubscription. The checksubscription method gives no problems, but the activatesubscription is problematic. That is because a subscription can only activated once, and on a second effort, the webservice returns an error. That is fine, the error is returned as xml. However, the http-headers also return a "500 internal server error". That is according to the specs:

http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383529

But I can not get past the "500 internal server error" to read the xml

My code is basically this:

-------------------------
Dim oRequest As HttpWebRequest = WebRequest.Create(sUrl)
' then create and add the xml for the request
Try
    Dim oResponse As HttpWebResponse = oRequest.GetResponse()
    ' code to process the response
Catch ex As Exception
    ' return the error message
End Try
---------------------------

The http-headers create an exception on "oRequest.GetResponse()". In the Catch, the oResponse is not defined. Is it possible to ignore an error? Like in good old VBScript "On Error Resume Next" (which I wanted to stop using).

Avatar of Mlanda T
Mlanda T
Flag of South Africa image

By delcaring "oResponse" outside the Try block, it will be accessible in the Catch

Dim oRequest As HttpWebRequest
Dim oResponse As HttpWebResponse

' then create and add the xml for the request
Try
    oRequest = WebRequest.Create(sUrl)
    oResponse = oRequest.GetResponse()
    ' code to process the response
Catch ex As Exception
    ' return the error message
End Try
The issue with the "the http-headers also return a '500 internal server error'" is not standard behaviour. A successful call to a web service should not return an error... remember that by a 'successful call to a web service' in this case we dont mean that the activatesubscription method should succeed.. whether the subscription is activated or not.. the web service should return appropriate state information.. e.g. maybe return a boolean which is true if activation was ok.. otherwise false is not... that sort of thing. The HTTP 500 error suggests a totally different issue... could be programming errors or improper error handling in the web service, or otherwise some or other error on the web service host. But the HTTP500 error cannot be used to signify that the subscription could not be activated.

To ignore the error, you just do nothing in the catch block, and execution will continue ot the statements after the Try..Catch block.
Avatar of sybe
sybe

ASKER

That creates "Object reference not set to an instance of an object."
On which line?
Avatar of sybe

ASKER

"System.NullReferenceException: Object reference not set to an instance of an object."

-> Select Case oResponse.StatusCode

oResponse is not an object
Dim oResponse As HttpWebResponse
    Try
        oResponse = oRequest.GetResponse()
    Catch ex As Exception

    End Try
    ProcessResponse(oResponse)
    oResponse.Close()



Private Sub ProcessResponse(ByVal oResponse As HttpWebResponse)
    Select Case oResponse.StatusCode

    End Select

End Sub

Open in new window

Seems the problem is occuring before the WebRequest is created. You have unfortunately left out some code here... However, before accessing oResponse in ProcessResponse, you need ot check whether it is nothing or not.

Private Sub ProcessResponse(ByVal oResponse As HttpWebResponse)

    If oResponse isnot nothing then

        Select Case oResponse.StatusCode

        End Select

    End If

End Sub


I have included a script below that you may perhaps copy some ideas from:

        Dim oRequest As WebRequest
        Dim oResponse As HttpWebResponse

        ' then create and add the xml for the request
        Try

            oRequest = WebRequest.Create("http://www.google.com/")
            oResponse = oRequest.GetResponse()

            Select Case oResponse.StatusCode

                Case HttpStatusCode.OK

                    Dim sr As New StreamReader(oResponse.GetResponseStream)
                    MsgBox(sr.ReadToEnd())
                    sr.Close()

                Case Else

                    MsgBox("Request returned status: " & [Enum].GetName(GetType(HttpStatusCode), oResponse.StatusCode))

            End Select

        Catch ex As Exception

            ' return the error message
            MsgBox(ex.ToString)

        End Try
Avatar of sybe

ASKER

Thank you.

The problem is that an error is generated on
oResponse = oRequest.GetResponse()    'message: The remote server returned an error: (500) Internal Server Error."

If that error is caught, oResponse gives "Object reference not set to an instance of an object.", so nothing can be done with it.

I want to read the xml-message returned, but the 500-error seems to prevent that.



Yes. The error HTTP 500 error indicates an error on the web service that you are calling. In the code snippet I gave you for example, try accessing http://www.google1.com/ (which does not exist)... you will find that an exception is thrown on that same line.

You need to talk to who ever administers the web service host and they should resolve the problem. That error, like I said earlier, is most likely due to something broken on that end... and not in your code.

You can handle that error by parsing the text in the exception... so on this line you try to maybe check if the error is a 500 error and handle it accrodingly...

' return the error message
'MsgBox(ex.ToString)
if ex.message.contains("(500) Internal Server Error") then msgbox("This was a HTTP500 error")
Avatar of sybe

ASKER

I agree that the problem in this case isn't on my part.

But anyway, I'd like to get the xml returned, and that does not seem possible with WebRequest.GetResponse().
Ironically I adapted some Classic ASP code, and that *is* able to get the xml:


Private Function GetXMLClassic() As String
    Dim oXMLHttpRequest
    Dim sReturn As String
    oXMLHttpRequest = CreateObject("Microsoft.XMLHTTP")
    If bHTTPLogin Then
        oXMLHttpRequest.Open("POST", sUrl, False, sHTTPUserName, sHTTPPassWord)
    Else
        oXMLHttpRequest.Open("POST", sUrl, False)
    End If
    oXMLHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8")
    oXMLHttpRequest.Send("" & oClientXML.InnerXml)

    sReturn = oXMLHttpRequest.responseText
    oXMLHttpRequest = Nothing
    Return sReturn
End Function

Open in new window

It should be easy to get teh returned XML... see the example I gave you.... try it out.. it returns the HTML for the Google home page and displays it in a messagebox (of course you could write to a file or put in a variable etc etc).

The method to do what you want is to basically get the ResponseStream from the oResponse object. That gives you a stream containing the data from the resource in your web request. The XML which you want will be in that Response Stream. Here we are wrapping that stream with a StreamReader and then just calling the ReadToEnd method on the StreamReader which returns a nice strign for us.

Dim sr As New StreamReader(oResponse.GetResponseStream)
dim theXML as string = sr.ReadToEnd())
sr.Close()

if Not String.IsNullOrEmpty(theXML) then Process(theXML)
Avatar of sybe

ASKER

> it returns the HTML for the Google home page

Well, yes, but http://www.google.com/ does not return a 500 Internal Server Error.
The problem is that the webservice both returns a 500 internal server error (in the header AND some xml. The internal server error in the header prevents WebRequest.GetResponse() from reading the xml. The XML is useful, because it contains some details about the error.
ASKER CERTIFIED SOLUTION
Avatar of Mlanda T
Mlanda T
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of sybe

ASKER

As the w3c recommendation says (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383529)

"In case of a SOAP error while processing the request, the SOAP HTTP server MUST issue an HTTP 500 "Internal Server Error" response and include a SOAP message in the response containing a SOAP Fault element"

That means that with webservices, http-error 500 does not necessarily mean that there was an internal server error as in "unable to process the code", but it can also mean "unable to process the (soap) request". If the webservice is written correctly it will always be able to return some xml. I tried sending an invalid XML-request, and the webservice returned XML with a message that the XML-request was invalid XML.

The issue is very clear: I want to read the XML returned by the webservice, even if there is a HTTP-error 500.
I have posted some code which does the job, but that is basically Classic ASP, and I wonder if it can be done with "WebRequest.GetResponse()". With the Classic ASP solution, I currently do a second (identical) request to the webservice to get the response XML. That  is not exactly the right way to do it.

> since the webresponse object automatically parses the response text for you.

Does it? I was not aware of that. AFAIK, it returns a String, which needs code to parse it as XML. But anyway, the parsing of the response text is not the problem here, but getting access to the response text.
Perhaps try to use the Microsoft.XMLHTTP from VB.NET then
Avatar of sybe

ASKER

The solution is to catch the WebException.

CType(webexception.Response, HttpWebResponse)

holds the responsexml.