locked
Trying to use HttpWebRequest RRS feed

  • Question

  • User50862095 posted

    I need to post a number of variables to a page that isn't on my site.  In ASP, this would simply be a matter of sending the data via a form.  In .NET 2.0, it's a bit trickier.  I'm have the following: 

                Dim objRequest As HttpWebRequest = CType(WebRequest.Create("http://www.domain.com/default.aspx"), HttpWebRequest)
                objRequest.Method = "POST"
                Dim encoding As New System.Text.ASCIIEncoding()
                Dim byte1 As Byte() = Text.Encoding.UTF8.GetBytes(sPostData)
                objRequest.ContentLength = byte1.Length
                objRequest.ContentType = "application/x-www-form-urlencoded"
                objRequest.KeepAlive = False

                Dim streamToSend As Stream = objRequest.GetRequestStream()
                streamToSend.Write(byte1, 0, byte1.Length)
                streamToSend.Close()

    sPostData is a string built from the variables I want to send, for example

                Dim sPostData = ""
                sPostData = sPostData & "name=" & "John Doe"
                sPostData = sPostData & "addr=" & "123 AnyStreet"
                sPostData = sPostData & "city=" & "any town"
                sPostData = sPostData & "request=" & "books"

    Instead of going to the page indicated in WebRequest.Create, I get a postback to the page I'm doing this on.  What am I doing wrong?

    Diane 

    Saturday, March 10, 2007 12:12 AM

Answers

  • User-225114762 posted

    I'm not sure about this, since I don't know the requirements of the payment processor, but you're mentioning it seems that you've via a different channel (i.e. a web page or something) told the payment processor that it will be receiving requests from a certain list of pages.

    If this assumption is correct, the question now is - how does the payment processor know this? I'd guess it looks at the 'Referer' HTTP header, which is accessible via the Referer property of the HttpWebRequest object. I'd set that to the .NET page's URL (as specified to the payment processor via the setup). I know too little about ASP, but a guess is that it might have a better default value than ASP.NET for that header when issuing a request.

    If that doesn't help, you should get fiddler, hack your ASP page to access the payment processor via HTTP (no SSL, it won't work - but it's just to see what it actually emits) check all the headers and the content, and then do the same for your .NET page and see where the difference lies.

    Svante

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, March 13, 2007 10:32 AM

All replies

  • User-225114762 posted

    Maybe you excluded that part, but I have to ask... Don't you want to do a objRequest.GetResponse() to actually post the request?

    The next thing to ensure is that http://www.domain.com/default.aspx is not only correct, but resolvable on the server executing the code.

    Finally, get Fiddler ( http://www.fiddlertool.com/fiddler/ )and check out what request you're really seeing as a postback to the original page.

    Svante

    Saturday, March 10, 2007 7:41 AM
  • User50862095 posted

    http://www.domain.com/default.aspx is an example, the page I'm trying to get to is resolvable.

    The Fiddler program looks interesting.  I'm going to go play with that in a moment.

    I don't have objRequest.GetResponse().  Maybe I'm not understanding this, but doesn't that ask for a response?  I'm not expecting a response.   Well, I am, but it will be on another page.  Am I mis-understanding what this does, do I need it?

    Diane 

    Saturday, March 10, 2007 10:44 AM
  • User-225114762 posted

    Hello,

    I think you're misunderstanding something. HTTP is a state-less request/response protocol - there's always a response. The API exposed by HttpWebRequest to issue a request is done in such way that it's when you ask for the response that the request actually gets sent. So, to send a request, in your case a HTTP POST using HttpWebRequest, you must do GetResponse(). You're of course free to ignore it (but you shouldn't - at least you should check the status code to determine if the request was accepted by the server).

    Just what do you mean you're expecting a response on another page?

    Presumably, you have a page that gets executed by a client web browser doing a GET or a POST to it. That's the page you've shown some code for. For whatever reason, you want that to cause another POST to a different server "behind the scenes" as far as the original client is concerned. The original request from the client web browser is then responded to by other code that you've not shown. Right? So the client gets a response, but as a side effect a POST is done according to your code. The response to that POST is not shown to the original client, so you just want to ignore it. That's ok - but you must still get it for the request to be issued at all.

    Svante

    Saturday, March 10, 2007 11:40 AM
  • User50862095 posted

    I have an ASP page that collects payment information in a form, then sends the form to a gateway.  Both in the form and in the gateway are the path and name for a success page and a declined page.  The gateway takes the form data, does it's thing, then sends the responses to the appropriate page.  From the user's perspective, after clicking the send button, they wait a second or so then see a receipt page or a message informing them that their payment has been declined.  This is all working nicely.

    Now I'm trying to mimic this process using ASP.NET 2.0.  I'm sending from a secure page to a secure page.  I understand what you're saying, it takes a bit of grokking though.  I found another example that sort of works, I have it below.  I can send to the gateway, but I get an error (and support is virtually useless, I have to wait for tier two on Monday, can't help).  Do I have it set correctly for sending from a secure page to a secure page?  I tried sending to a page I wrote that simply writes the from data it received, and it looks like it's correct.  So I wonder if the error is because I'm not handling https correctly.  Once my form data is accepted, I'll have to figure out what I get back from the gateway and if i get back enough to not worry about receipt and decline pages.

           

          
                Dim uri As New Uri("https://www.staging.yourpay.com/lpcentral/servlet/lppay")
                Dim uri As New Uri("https://secure.EnticedByNature.com/form-secureOrder.aspx")
                Dim sPostData As String = ""
                sPostData = sPostData & "bcountry=" & "USA"
                sPostData = sPostData & "rdoType=" & "Visa"
                sPostData = sPostData & "cardnumber=" & "4111111111111111"
                sPostData = sPostData & "expmonth=" & "06"
                sPostData = sPostData & "expyear=" & "2008"
                sPostData = sPostData & "sstype=" & "Visa"
                sPostData = sPostData & "chargetotal=" & "10.00"
                sPostData = sPostData & "&userID=" & "12345"
                sPostData = sPostData & "responseSuccessURL=" & "http://secure.enticedbynature.com/default.aspx"
                sPostData = sPostData & "responseFailURL=" & "http://secure.enticedbynature.com/default.aspx"
                sPostData = sPostData & "2000=" & "submit"

            If (uri.Scheme = uri.UriSchemeHttps) Then
                    Dim request As HttpWebRequest = HttpWebRequest.Create(uri)
                    request.Method = WebRequestMethods.Http.Post
                    request.ContentLength = sPostData.Length
                    request.ContentType = "application/x-www-form-urlencoded"

                    Dim writer As New StreamWriter(request.GetRequestStream())
                    writer.Write(sPostData)
                    writer.Close()

                    Dim response As HttpWebResponse = request.GetResponse
                    Dim reader As New StreamReader(response.GetResponseStream())
                    Dim tmp As String = reader.ReadToEnd()
                    response.Close()

                    Me.PanelEnd.GroupingText = "Here we go" & tmp
            End If

    Diane
     

    Saturday, March 10, 2007 1:45 PM
  • User-225114762 posted

    Ok, I think I see where the problem lies. The gateway (the code we're discussing) forwards the request to the back-end payment processor server, which will do a redirect to either the 'accepted', or 'declined' page.

    Point is, you have to pickup the response from the back-end server, check that it is a redirect (typically status code 302 if they've done their homework), get the redirect URL from that response, and then do a redirect which actually reaches the client web browser.

    Your sample code above probably works in the sense that the back-end server gets the appropariate request, accepts or declines - but the client web browser doesn't get the expected 'accepted' or 'declined' page, because the redirect does not reach the client.

    Does this make sense?

    Svante

    Saturday, March 10, 2007 2:55 PM
  • User50862095 posted

    Yes it makes sense, and it's good to know there may be a way for me to pick up the response, but at the moment, I'm getting an error from the processor.  Something is wrong with what they're receiving, but what I'm sending looks right.  Am I handling all the https stuff ok?  Maybe I have a wrong setting there?

    diane 

    Saturday, March 10, 2007 2:58 PM
  • User-225114762 posted

    If you're getting an error from the processor, that's where you should start looking. Unfortunately fiddler won't help you, because it can't decrypt the https data. If you can simulate it via a browser, there's an excellent plugin for Firefox that's free, Firebug, which I think suppports https. The Internet Explorer plug-in iewatch works well too, but it's not free (well worth the money though).

    If you're really getting a response from the processor, the https stuff is not a likely candidate. More likely is that the form data is not correctly encoded or something like that. I notice that you're not UrlEncoding the data before posting for example, check out HttpUtility.UrlEncode . In the second sample, you're not encoding as ASCII either - I think you should. First UrlEncode it, then get an ASCII encoded representation of the form data and send that to the RequestStream .

    Svante

    Saturday, March 10, 2007 3:21 PM
  • User50862095 posted

    Oh boy, your starting to go over my head.  I'm just about almost ready to start getting comfortable with this stuff, and you have to go and throw in some new stuff <grin>.

    Is there a reason why I can't send from one secure page to another, and see what I get?  If I get Firebug, is it fairly clear what I'm supposed to do with it?  I'll see about HttpUtility.UrlEncode and encoding as ASCII as well.  Know of any good articles or tutorials on this?

    Thanks,

    Diane 

    Saturday, March 10, 2007 3:28 PM
  • User-225114762 posted

    Nobody said it was going to be easy! Or did they... Hmm, I do seem to recall some hype from MS about ASP.NET 2.0...

    Yes, there's a reason you can't send to a secure page and see what you get in transit. Fiddler is a proxy (just like your code!), and thus sits inbetween the payment processor and your code. Your code, when using https, will encrypt data before sending it - so fiddler can't read it!

    You can certainly read the response, because you see it after it's decrypted by your servers SSL layer (https is HTTP with SSL as you may recall).

    Firebug is fairly clear, but it just shows what goes on to and from your browser. Not what happens in your server, or what happens between your server and the payment processor. Still very useful! Strongly recommended.

    Don't despair - the UrlEncoding is just a simple method call returning a string. It does things like replacing spaces with '+', and reserved characters into %xx hexencodings etc. You should UrlEncode the field names and values before building your form data.

    Svante

    Saturday, March 10, 2007 3:37 PM
  • User50862095 posted

    There's just so much to learn!  Can I URLEncode the string after I build it, or should I encode each piece first?  If that doesn't work, I'll have to wait until Monday.  If someone at the processor can tell me what the error is, I'll have more to go on.  The problem may not be in what I'm sending them at all.

    Thanks for you help.  I'll post the an update on Monday.

    Diane 

     

    Saturday, March 10, 2007 4:50 PM
  • User50862095 posted

    Well, tech support is useless.  Because I'm working in .NET, they won't talk to me.

    I can send the same data in ASP, and it's accepted. I created an ASP page that has one line, response.write request.form.  This should give me the string that the ASP page with the form is sending.  Right?  If I send this string in the ASP.NET page, I get an error - it doesn't recognize something in the data. If I first urlencode the string, then send it, I get the error "Invalid Store Name" which makes me think I'm closer, but not quite there. 

    I have sPostData = HttpUtility.UrlEncode(sPostData), but you said something about encoding as ascii?  I saw where HttpUtility.UrlEncode can take an encode parameter, but I can't get it to work with ascii. 

    Diane
     

    Monday, March 12, 2007 6:36 PM
  • User-225114762 posted

    You should UrlEncode each name and value separately, not the '=' and '&' etc, i.e. not the entire sPostData. Do some debug output of the actual post data just before you post it in ASP, and the same just before you post it in ASP.NET and compare and spot the differences.

    Svante

    Tuesday, March 13, 2007 2:21 AM
  • User50862095 posted

    Ok, my postdata string is now being built like this (these are just the first few lines):

            Dim sPostData AS String
            sPostData = HttpUtility.UrlEncode("storename") & "=" & HttpUtility.UrlEncode("1111162216")
            sPostData = sPostData & "&" & HttpUtility.UrlEncode("txnorg") & "=" & HttpUtility.UrlEncode("eci")
            sPostData = sPostData & "&" & HttpUtility.UrlEncode("mode") & "=" & HttpUtility.UrlEncode("payonly")
            sPostData = sPostData & "&" & HttpUtility.UrlEncode("txntype") & "=" & HttpUtility.UrlEncode("sale")

    I set my asp page to post to a second asp page that contains only response.write request.form.  I'm allowing my asp.net page to post back to itself, displaying the result.  I compared the two strings and they are identical.  I also took a look at the string in the .NET page just before it gets sent, and it is identical to what is posted back.  I can't find any difference between the two at all.  Yet the two pages are eliciting different responses when posted to the processor. 

    I have to set up the 'store', giving it a list of payment pages.  If the store doesn't recognize the pages that's posting, it will generate an error 1002.  That's exactly the error the .NET pages keeps getting, even though it's listed as a payment page in the store set up.  I can add multiple payment pages in the setup.  I tried putting the ASP page first, the .NET page first, and the .NET page by itself just to see if it made any difference.  It didn't.

    I would think that they simply don't recognize the aspx extension, except when I was encoding the entire string (and I could see how that was wrong when I took a good look at it), I got an invalid store error, which suggests the string was at least recognized enough to be looked at. 

    What am I missing?  Could there be something different that isn't human readable?

    Diane 

    Tuesday, March 13, 2007 9:45 AM
  • User-225114762 posted

    I'm not sure about this, since I don't know the requirements of the payment processor, but you're mentioning it seems that you've via a different channel (i.e. a web page or something) told the payment processor that it will be receiving requests from a certain list of pages.

    If this assumption is correct, the question now is - how does the payment processor know this? I'd guess it looks at the 'Referer' HTTP header, which is accessible via the Referer property of the HttpWebRequest object. I'd set that to the .NET page's URL (as specified to the payment processor via the setup). I know too little about ASP, but a guess is that it might have a better default value than ASP.NET for that header when issuing a request.

    If that doesn't help, you should get fiddler, hack your ASP page to access the payment processor via HTTP (no SSL, it won't work - but it's just to see what it actually emits) check all the headers and the content, and then do the same for your .NET page and see where the difference lies.

    Svante

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, March 13, 2007 10:32 AM
  • User50862095 posted

    That did it!  I'm getting the same response I'm getting with the ASP page.  Thank you!!!!

    Diane 

    Tuesday, March 13, 2007 11:15 AM
  • User-225114762 posted

    You're welcome. Good luck.

    Tuesday, March 13, 2007 11:34 AM