Last post Mar 13, 2007 11:34 AM by Svante
Mar 10, 2007 12:12 AM|Mainship|LINK
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)
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?
Mar 10, 2007 07:41 AM|Svante|LINK
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.
Mar 10, 2007 10:44 AM|Mainship|LINK
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?
Mar 10, 2007 11:40 AM|Svante|LINK
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.
Mar 10, 2007 01:45 PM|Mainship|LINK
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())
Dim response As HttpWebResponse = request.GetResponse
Dim reader As New StreamReader(response.GetResponseStream())
Dim tmp As String = reader.ReadToEnd()
Me.PanelEnd.GroupingText = "Here we go" & tmp
Mar 10, 2007 02:55 PM|Svante|LINK
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
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?
Mar 10, 2007 02:58 PM|Mainship|LINK
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?
Mar 10, 2007 03:21 PM|Svante|LINK
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 .
Mar 10, 2007 03:28 PM|Mainship|LINK
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?
Mar 10, 2007 03:37 PM|Svante|LINK
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.
Mar 10, 2007 04:50 PM|Mainship|LINK
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.
Mar 12, 2007 06:36 PM|Mainship|LINK
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.
Mar 13, 2007 02:21 AM|Svante|LINK
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
Mar 13, 2007 09:45 AM|Mainship|LINK
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?
Mar 13, 2007 10:32 AM|Svante|LINK
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.
Mar 13, 2007 11:15 AM|Mainship|LINK
That did it! I'm getting the same response I'm getting with the ASP page. Thank you!!!!
Mar 13, 2007 11:34 AM|Svante|LINK
You're welcome. Good luck.