Link to home
Start Free TrialLog in
Avatar of pcoppney
pcoppney

asked on

Post to asp/xmlhttp from Aspx and consume xml response

I am trying to post xml to an existing asp page from an aspx page and recieve the xml response.  The code executes fine until the "myWriter.Write(strXML)" statement.  Never returns from asp page.  I have tested the asp page and it works with posts from other asp pages.  The problem occurs when posting from .net.

Any Ideas?

here is the code for the aspx call to the asp:

    Function PostToRSXML(ByVal url As String, ByVal strXML As String) As String
        Dim result As String = ""
        Dim myWriter As StreamWriter

        Dim objRequest As HttpWebRequest = WebRequest.Create(url)
        objRequest.Method = "POST"
        objRequest.ContentLength = strXML.Length
        objRequest.ContentType = "application/x-www-form-urlencoded"

        Try
            myWriter = New StreamWriter(objRequest.GetRequestStream())
            myWriter.Write(strXML)
        Catch e As Exception
            Return e.Message
        Finally
            myWriter.Close()
        End Try

        Dim objResponse As HttpWebResponse = objRequest.GetResponse()
        Dim sr As StreamReader
        sr = New StreamReader(objResponse.GetResponseStream())
        result = sr.ReadToEnd()
        sr.Close()

        Return result
    End Function


Here is the ASP page code:

      Set req = server.CreateObject("MSXML.DOMDocument")
      req.async=false
      blnRetVal = req.load(Request)

      if blnRetVal then
            
                  'Get the XML source
                  set mynode=req.getElementsByTagName("Root")

                  strXML = mynode.item(0).xml
                  ' Create the VB object
                  Set objXML = Server.CreateObject("Objname.Classname")
      
                  lngRetVal = objXML.buildresponse("", "", strXML, strXMLOutput, True)
            
                  Set objXML = Nothing

                  Select Case lngRetVal
                        Case 0
      
                        ' Write the XML
                              Response.Write strXMLOutput

                        ' Now we are done!
                        Case else
                              Response.Write strXMLOutput
                  End Select
      
      end if
Avatar of dfiala13
dfiala13

Try this...

myWriter.Write(strXML)
myWriter.Flush()
myWriter.Close()

The buffer may not be being fully written and sent over and hence never returns.
Avatar of pcoppney

ASKER

Changed ASPX to:


        Dim myWriter As StreamWriter

        Dim objRequest As HttpWebRequest = WebRequest.Create(url)
        objRequest.Method = "POST"
        objRequest.ContentLength = strXML.Length
        objRequest.ContentType = "application/x-www-form-urlencoded"

        Try
            myWriter = New StreamWriter(objRequest.GetRequestStream())
            myWriter.Write(strXML)
            myWriter.Flush()
            myWriter.Close()
        Catch e As Exception
            Return e.Message
        Finally
            'myWriter.Close()
        End Try

        Dim objResponse As HttpWebResponse = objRequest.GetResponse()
        Dim sr As StreamReader
        sr = New StreamReader(objResponse.GetResponseStream())
        result = sr.ReadToEnd()
        sr.Close()

        Return result

Still no luck.  on the "myWriter.Write(strXML)" statement processor goes 100% and stays there until a timeout.
hmmm.

Can you check to see what the request looks like on the ASP page when coming from the ASPX page.

Very baffling.  I have almost identical code I used.  The only difference (besides that it is in C#) is that I am doing an asynch call...

Check out the  postToURL method

public class Connect
      {
            private const int BUFFER_SIZE= 1024;
            private const int TIME_OUT= 5000;
            private ManualResetEvent m_eventDone;
            private HttpWebRequest m_httpReq;
            private byte[] m_btRead;
            private StringBuilder m_sbResp;
            private string m_sPost;
            private Stream m_stResponse;
            private Decoder m_dec = Encoding.UTF8.GetDecoder();
            private string m_sResp;
            private bool m_bGotResponse = false;



            public Connect()
            {
                  m_eventDone = new ManualResetEvent(false);
                  m_btRead = new byte[BUFFER_SIZE];
                  m_sbResp = new StringBuilder(String.Empty);
            }

            public bool GotResponse
            {
                  get { return m_bGotResponse;}
            }

            public string postToURL(string sURL, string sData)
            {
                  m_httpReq = (HttpWebRequest)WebRequest.Create(sURL);
                  m_httpReq.Method = "POST";
                  m_httpReq.ContentType = "application/x-www-form-urlencoded";
                  m_httpReq.ContentLength = sData.Length;

                  Stream st = m_httpReq.GetRequestStream();

                  StreamWriter stw = new StreamWriter(st);
                  stw.Write(sData);

                  stw.Flush();
                  stw.Close();

                  IAsyncResult ar = (IAsyncResult) m_httpReq.BeginGetResponse(
                        new AsyncCallback(callback), this);

                  //hold until we are done reading
                  //put a timeout here too
                  m_bGotResponse = m_eventDone.WaitOne(TIME_OUT,false);
                  m_sPost = sURL + "?" + sData;
                  return m_sResp;
            }

            public string getPostData()
            {
                  return m_sPost;
            }

            private void callback(IAsyncResult ar){

                  HttpWebResponse httpResp = (HttpWebResponse)m_httpReq.EndGetResponse(ar);        

                  //  Start reading data from the response stream.
                  m_stResponse = httpResp.GetResponseStream();


                  //  Pass rs.BufferRead to BeginRead. Read data into rs.BufferRead
                  IAsyncResult iarRead = m_stResponse .BeginRead(m_btRead, 0,
                        BUFFER_SIZE, new AsyncCallback(readCallback), this);
            }

            
            private void readCallback(IAsyncResult asyncResult)
            {

                  // Read rs.BufferRead to verify that it contains data.
                  int iRead = m_stResponse.EndRead( asyncResult );
                  if (iRead > 0)
                  {
                        // Prepare a Char array buffer for converting to Unicode.
                        Char[] charBuffer = new Char[BUFFER_SIZE];
         
                        // Convert byte stream to Char array and then to String.
                        // len contains the number of characters converted to Unicode.
                        int iLen = m_dec.GetChars(m_btRead, 0, BUFFER_SIZE, charBuffer, 0);
                        String s = new String(charBuffer, 0, iLen);

                        // Append the recently read data to the stringbuilder
                        m_sbResp.Append(Encoding.ASCII.GetString(m_btRead, 0, iRead));        

                        // Continue reading data untilm_stResponse.EndRead returns –1.
                        IAsyncResult ar = m_stResponse.BeginRead( m_btRead, 0, BUFFER_SIZE,
                              new AsyncCallback(readCallback), this);
                  }
                  else
                  {
                        if(m_btRead.Length>0)
                        {
                              //set our response string                  
                              m_sResp = m_sbResp.ToString();
                        }
                        // Close down the response stream.
                        m_stResponse.Close();        
                        // Set the ManualResetEvent so the main thread can exit.
                        m_eventDone.Set();                          
                  }
                  return;
            }    

      }
Put this at top of the asp page

Response.Write"<root></root>"
Response.end

It looks like the request never even gets to the asp. The aspnet_wp.exe  process is the one that pegs the processor.

What are the ramifications of asynchronous communications.  Is asp capable of handling it?
Interesting.  It's blocking before it finishes the write.  

What happens if you send a really short query to the ASP page?

ASP shouldn't notice if it's asynch or not.  It is just responding as normal, the ASPX page is just delegating the wait for the response to another method.
I wonder if it has to do with teh encoding for the request....

Try this...
     Dim objRequest As HttpWebRequest = WebRequest.Create(url)
Dim encodedData As New ASCIIEncoding()
Dim byteArray As Byte() = encodedData.GetBytes(strXML)

        objRequest.Method = "POST"
        objRequest.ContentLength = byteArray.Length
        objRequest.ContentType = "application/x-www-form-urlencoded"

        Try
            myWriter = New StreamWriter(objRequest.GetRequestStream())
            myWriter.Write(byteArray)


progress (maybe), now it gets past the .write() and hangs on .flush() statement
What encoding is the ASP page expecting?  

have you tried a short (and meaningless query)?
Not sure, how do you set the encoding for ASP page.  

Yes I have actually hard coded the same xml that the .net is trying to post and I get results.  I can post to the asp page from other asp pages via xmlhttp.

These pages are running on the same machine could there be any problem there?
Things I'd try,
don't send the same XML, send a really short query string, we know that the problem isn't on the ASP page and this will give us a clue if it something to do with the write buffer size.

>>These pages are running on the same machine could there be any problem there?
I doubt it, but could be. Give it a shot.

>>Not sure, how do you set the encoding for ASP page.  
The encoding would be for the request.  There should be a property on the ASP request object that indicates the encoding. But from what I can tell there isn't, perhaps it is buried in the ServerVariables dictionary (sorry my Classic ASP is very superficial)
I sent this <?xml version='1.0' encoding='utf-8'?><Root></Root> from the one asp page to another and it worked, tried posting the same string from aspx and it does not work.
OK,
it's not the buffer size.

let's eliminate:

1) the same machine issue

2) the encoding.

Try this:
Dim encodedData As New UTF8Encoding()
Dim byteArray As Byte() = encodedData.GetBytes(strXML)

        objRequest.Method = "POST"
        objRequest.ContentLength = byteArray.Length
        objRequest.ContentType = "application/x-www-form-urlencoded"
Didn't work - still have the same problem.
ASKER CERTIFIED SOLUTION
Avatar of dfiala13
dfiala13

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
OK, I finally have it working.  When in doubt go back to the basics right?

I took your example and created an aspx page with nothing else on it except a control to display the results and it worked - all of your examples worked.

What was the problem you ask?  (and rightfully so)

Programing 101 - I had to labels in the HTML with the same ID, one of them was being referenced in the page load of the form.  I was also calling the method to get the xml from the asp page in the page load.  For some reason the debug compile will not stop building just because two controls have the same ID (fairly new to .net so this may be a visual studio option setting).  So as the page loaded it would hang in a loop trying to set the value of the control that was referenced twice.  

The moral of the story - NEVER PUT ANYTHING IN THE PAGE_LOAD UNLESS YOU ABSOTIVELY POSILUTLEY MUST.

Dude - thanks for your help - you earned the points.
You're welcome.  Glad you got it working.  That is a strange bug, didn't think it would let you compile with two controls with the same ID.
I don't suppose you guys are still monitoring this question, but in the event you get my question, can you guys help me?   I tried the sample .net code above and got an error: "BC30002: Type 'XmlDocument' is not defined."

I really have not had a chance to use any .NET, but I need to respond with ASP to someone posting to my page.   I would like to set up the .net page in order to test it.    

thanks!
make sure you have added

Imports System.Xml

to the top of your ASPX code-behind
I'm sorry for sounding so stupid.   I don't have a code-behind.   I'm using Web Matrix (haven't been able to buy vs.net yet).  The way I understand it, I just put this at the top of my code page...right?

<%@ Page Language="VB" %>
Line 2:  <% Imports System.Xml %>

I'm getting this error:

"BC30035: Syntax error"

I was planning on just dropping a button on the page and putting it in an on-click event.   Am I way off base? Thanks.  
You're close, when using inline scripting you need to use the import directive
<%@ Import namespace="System.Xml" %>

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconimport.asp
By the way, I owe you some pretty good points if you help me get this going.....


Anyway, I'm guessing that it's not finding the namespace:

C:\Inetpub\wwwroot\websvc\test.aspx(14) : error BC30002: Type 'StreamWriter' is not defined.

                Dim myWriter As StreamWriter
                                ~~~~~~~~~~~~
C:\Inetpub\wwwroot\websvc\test.aspx(17) : error BC30002: Type 'HttpWebRequest' is not defined.

                Dim objRequest As HttpWebRequest = WebRequest.Create(sURL)
                                  ~~~~~~~~~~~~~~                          
C:\Inetpub\wwwroot\websvc\test.aspx(23) : error BC30002: Type 'StreamWriter' is not defined.

                    myWriter = New StreamWriter(objRequest.GetRequestStream())
                                   ~~~~~~~~~~~~                              
C:\Inetpub\wwwroot\websvc\test.aspx(29) : error BC30816: 'Debug' is not declared. Debug object functionality is available in 'System.Diagnostics.Debug' in the 'System' assembly.

                    Debug.Write(e1.Message)
                    ~~~~~                  
C:\Inetpub\wwwroot\websvc\test.aspx(34) : error BC30002: Type 'HttpWebResponse' is not defined.

                Dim objResponse As HttpWebResponse = objRequest.GetResponse()
                                   ~~~~~~~~~~~~~~~                          
C:\Inetpub\wwwroot\websvc\test.aspx(35) : error BC30002: Type 'StreamReader' is not defined.

                Dim sr As StreamReader
                          ~~~~~~~~~~~~
C:\Inetpub\wwwroot\websvc\test.aspx(36) : error BC30002: Type 'StreamReader' is not defined.

                sr = New StreamReader(objResponse.GetResponseStream())
                         ~~~~~~~~~~~~                                
C:\Inetpub\wwwroot\websvc\test.aspx(40) : error BC30451: Name 'Xml1' is not declared.

                Xml1.Document = xmlDoc
You are correct, you don't have the namespaces declared.  The last error is you don't have a control named Xml1.  Open a new question and add a link to it in this one.
Once again, thanks for your help.    


Ok....I'm down to only a couple of errors after adding some namespaces:

C:\Inetpub\wwwroot\websvc\test.aspx(21) : error BC30002: Type 'HttpWebRequest' is not defined.

                Dim objRequest As HttpWebRequest = WebRequest.Create(sURL)
                                  ~~~~~~~~~~~~~~                          
C:\Inetpub\wwwroot\websvc\test.aspx(33) : error BC30816: 'Debug' is not declared. Debug object functionality is available in 'System.Diagnostics.Debug' in the 'System' assembly.

                    Debug.Write(e1.Message)
                    ~~~~~                  
C:\Inetpub\wwwroot\websvc\test.aspx(38) : error BC30002: Type 'HttpWebResponse' is not defined.

                Dim objResponse As HttpWebResponse = objRequest.GetResponse()

I have declared them:

<%@ Page Language="VB" %>
<%@ Import namespace="System.Xml" %>
<%@ Import namespace="System.Web" %>
<%@ Import namespace="System.IO" %>
<%@ Import namespace="System.Collections" %>
<%@ Import namespace="System.Diagnostics.Debug" %>
<script runat="server">

    ' Insert page code here
    '

    Sub Button1_Click(sender As Object, e As EventArgs)
        ' Put user code to initialize the page here
                Dim xmlDoc As XmlDocument
                xmlDoc = New XmlDocument

                Dim result As String = ""
                Dim myWriter As StreamWriter
                Dim sURL = "http://localhost/websvc/testasp.asp"
                Dim sXML = "<?xml version='1.0' encoding='utf-8' ?><Root><groupnum>test</groupnum></Root>"
                Dim objRequest As HttpWebRequest = WebRequest.Create(sURL)
                objRequest.Method = "POST"
                objRequest.ContentLength = sXML.Length
                objRequest.ContentType = "application/x-www-form-urlencoded"

                Try
                    myWriter = New StreamWriter(objRequest.GetRequestStream())
                    myWriter.Write(sXML)
                    myWriter.Flush()
                    myWriter.Close()

                Catch e1 As Exception
                    Debug.Write(e1.Message)
                Finally

                End Try

                Dim objResponse As HttpWebResponse = objRequest.GetResponse()
                Dim sr As StreamReader
                sr = New StreamReader(objResponse.GetResponseStream())
                result = sr.ReadToEnd()
                sr.Close()
                xmlDoc.LoadXml(result)
                'Xml1.Document = xmlDoc


    End Sub

</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <asp:Button id="Button1" onclick="Button1_Click" runat="server" Text="Button"></asp:Button>
        <!-- Insert content here -->
    </form>
</body>
</html
<%@ Import namespace="System.Diagnostics" %>
<%@ Import namespace="System.Net %>
Ok....that worked well.   I'm getting really close.  I know that if I can figure out how to hit the asp page with the .net page, I'm good.  The ASP page seems to be working, and sending back a valid xml message--but I need to be able to tell my users how to do it.  


Line 37:                 End Try
Line 38:
Line 39:                 Dim objResponse As HttpWebResponse = objRequest.GetResponse()
Line 40:                 Dim sr As StreamReader
Line 41:                 sr = New StreamReader(objResponse.GetResponseStream())
 

Source File: C:\Inetpub\wwwroot\websvc\test.aspx    Line: 39

Stack Trace:


[WebException: The remote server returned an error: (500) Internal Server Error.]
   System.Net.HttpWebRequest.CheckFinalStatus() +674
   System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) +139
   System.Net.HttpWebRequest.GetResponse() +149
   ASP.test_aspx.Button1_Click(Object sender, EventArgs e) in C:\Inetpub\wwwroot\websvc\test.aspx:39
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +83
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +57
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +18
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33
   System.Web.UI.Page.ProcessRequestMain() +1277

 
Your ASP page is returning an error.

You really should ask a new question.