HTTP POST - I'm stuck - asp.net

I have to POST some parameters to a URL outside my network, and the developers on the other side asked me to not use HTTP Parameters: instead I have to post my key-values in HTTP Headers.
The fact is that I don't really understand what they mean: I tried to use a ajax-like post, with XmlHttp objects, and also I tried to write in the header with something like
Request.Headers.Add(key,value);
but I cannot (exception from the framework); I tried the other way around, using the Response object like
Response.AppendHeader("key", "value");
and then redirect to the page... but this doesn't work, as well.
It's evident, I think, that I'm stuck there, any help?
EDIT I forgot to tell you that my environment is .Net 2.0, c#, on Win server 2003.
The exception I got is
System.PlatformNotSupportedException was unhandled by user code
Message="Operation is not supported on this platform."
Source="System.Web"
This looks like it's caused by my tentative to Request.Add, MS an year ago published some security fixes that don't permit this.

Have you tried the WebClient class? An example might look like:
WebClient client = new WebClient();
NameValueCollection data = new NameValueCollection();
data["var1"] = "var1";
client.UploadValues("http://somewhere.com/api", "POST", data);

Like #lassevk said, a redirect won't work.
You should use the WebRequest class to do an HTTP POST from your page or application. There's an example here.

Take a look at HttpWebRequest. You should be able to construct a request to the URL in question using HttpWebRequest.Method = "POST".

You should post more information.
For instance, is this C#? It looks like it, but I might be wrong.
Also, you say you get an exception, what is the exception type and message?
In any case, you can't redirect to a page for POST, you need to submit it from the browser, not from the server redirect, so if you want to automate this, I would guess you would need to generate a html page with a form tag, with some hidden input fields, and then submit it with javascript.

I think they mean they don't want you to use URL parameters (GET). If you use http headers, it's not really querying through POST any more.

What language/framework?
Using Python and httplib2, you should be able to do something like:
http = httplib2.Http()
http.request(url, 'POST', headers={'key': 'value'}, body=urllib.urlencode(''))

I believe that the Request object would only accept a certain set of predefined headers.
There's an enumeration that lists all the supported HTTP Headers too.
But I can't remember it at the moment... I'll look it up in a sec...

I tested your scenario using 2 sample pages using XmlHttpRequest option.
Custom headers are available in the aspx page posted to, using XmlHttpRequest.
Create the following 2 pages. Make sure the aspx page is in a solution , so that you can run the in the debugger, set break point and inspect the Request.Header collection.
<html>
<head>
< script language="javascript">
function SendRequest()
{
var r = new XMLHttpRequest();
r.open('get', 'http://localhost/TestSite/CheckHeader.aspx');
r.setRequestHeader('X-Test', 'one');
r.setRequestHeader('X-Test', 'two');
r.send(null);
}
< script / >
</head>
<body>
<form>
<input type="button" value="Click Me" OnClick="SendRequest();" />
</form>
</body>
</html>
CheckHeader.aspx
using System;
using System.Web;
using System.Web.UI;
public partial class CheckHeader : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string value = string.Empty;
foreach (string key in Request.Headers)
value = Request.Headers[key].ToString();
}
}
Man.. This html editor sucks.. or i do not know how to use it...

The exception I was facing yesterday was caused by my stupid try to write on the headers of the already built page.
When I started creating my Request following one of the mothods indicated here, I could write my headers.
Now I'm using the WebRequest object, as in the sample indicated by #sectrean, here.
Thanks a lot to everybody. StackOverflow rocks :-)

Related

Create HTTP POST method in ASP.NET which accepts CGI variables

I have an ASP.NET (.NET v4) web application running on IIS 7.5. I have a 3rd party which wants to pass information to my system. They support passing this information using HTTP POST, the information they provide is:
"This method simply calls a script on your server and passes each
field as a CGI variable. When you have received the data your server
should return a '1' on a line by itself to indicate success. Anything
else will generate an error on our server which will be investigated.
To set up this delivery method we need a URL to post to. We can use
HTTP or HTTPS."
My web application currently implements many WCF services but as I don't know what the variables passed in will be I cannot define a specific contract. Can I create a normal aspx page which they can post to and then read each of the parameters passed and do the appropriate processing.
If I do this how do I send back a line containing '1'?
Do I need to do anything else to make this HTTP POST compatible.
The last time I had to tackle a similar situation, i did it using a standard ASPX page, and it all worked quite well.
In my case the output was XML, so I had to make sure that I changed the output mime type to match "text/xml" in my case.. "text/plain" I would guess in yours..
Anyway, C# sharp code below, and make sure that your ASPX file has ONLY the very top line in, that is:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="register.aspx.cs" Inherits="myservices.register" ContentType="text/xml" %>
and nothing else, no carriage returns or anything.
Then do all your work in the code behind:
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "text/plain";
//Get your CGI variables here... you will have to get them to tell you what to expect
string myparam = (string)Request.QueryString["myparam"];
//do what ever you need here with your variables
Response.Write("1");
Response.End();
}// End page load handler
If you need to follow the one with a carriage return, then i believe you can use the carriage return property in the system.environment object, but I've not got doc's to hand to look it up. That should however get you started.
The MOST important thing to remember is to make sure NOTHING is output from the aspx, not even a carriage return.
I've previously written an article on my Blog about how to use this method for producing phone directories for Cisco-IP phones if you want to read it. You can find it here: http://shawtyds.wordpress.com/2009/09/26/cisco-ip-phone-directories-using-c/

jQuery ajax call containing script-tag in data

I read some values from text boxes and send them via jQuerys post method to an server. If the user enters text containing something like "bla bla", the call fails. The data looks like this in that case:
var data = { myKey: 'bla <script> bla' };
And I send it to the server like this:
$.post(targetUrl, data, function(x) {...});
On the server side (an Asp.Net web form) it looks like the call never reaches the server. Any hint how to solve that? If there's a convenient function which cleans data from bad tags, that would be fine too.
Have you desactivate the validate request of your aspx page?
add this in your page declaration: validateRequest="false"
To strip tags using a jQuery function:
jQuery.fn.stripTags = function() {
return this.replaceWith( this.html().replace(/<\/?[^>]+>/gi, '') );
};
Do you receive a page_load in ASP.NET? If yes, isn't there anything in Request.Params?
I would suggest escaping your values client side using the javascript escape function as shown below
var data = { myKey: escape('bla <script> bla') };
Once you have done that, you can retrieve the correct value on the server side using the following (.Net Code)
HttpUtility.UrlDecode(param_value_to_decode)
I tested this and the correct value is being passed correctly to the server via the post request.
Hope this helps.
Additional Info : I forgot to mention the cause of the error. When inspecting the request using firebug, it returns a "500 Internal Server Error - A potentially dangerous Request.Form value was detected from...". This is a built in protection mechanism from asp.net to protect against script injection. The following page directive ValidateRequest="false" did not solve the problem as expected (Works in traditional WebForms). It might be something specific to the Mvc platform, not to sure. The above solution does work, so just use that.
Regards
G

URL Encoding being lost before processing - ASP.net

I am building a web-store that uses URL encoding extensively.
I have a list of Departments & Categories in my database which I use to generate the links. These are, of course, URL encoded before they are sent.
Some Typical Links are...
/MySite/Store/Countertop+Equipment/Can+Openers.aspx
/MySite/Store/Dinnerware.aspx
/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx
In my HTTPHandler I call app.Request.Path to obtain the current path. The string returned by this call is no longer URL encoded which is making it impossible for me to parse correctly.
Once the URL encoding is lost
/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx becomes
/MySite/Store/Kitchen/Pastry/Decorating.aspx.
This is obviously breaking the method that converts the URL to a QueryString.
Anyone know how to fix this?
Here is the core of my HTTPHandler
public void Init(System.Web.HttpApplication app)
{
app.BeginRequest += new EventHandler(Application_BeginRequest);
}
private void Application_BeginRequest(object sender, EventArgs e)
{
System.Web.HttpApplication app = (System.Web.HttpApplication)sender;
string realUrl = GetRealUrl(app.Request.Path);
if (!String.IsNullOrEmpty(realUrl))
app.Context.RewritePath(realUrl, false);
}
I really appreciate your help!
You cannot use Request.Url (including Url..PathAndQuery, AbsolutePath etc) as its OriginalString is already decoded.
So there is no point to use Request.Url at all and you can try to play with following:
Request.AppRelativeCurrentExecutionFilePath
Request.CurrentExecutionFilePath
Or in a worst-case scenario you'll need to parse the Url:
[Test]
public void RewriteProoveOfConcept() {
var path = #"/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx";
var res = Regex.Replace(path, #"/(.+)/(.+)/(.+)/(.+)\.aspx", #"/$1/YourPage.aspx?category1=$2&category2=$3&category3=$4");
Assert.AreEqual(#"/MySite/YourPage.aspx?category1=Store&category2=Kitchen&category3=Pastry%2f+Decorating", res);
}
This shows how you can get the URL:
/MySite/YourPage.aspx?category1=Store&category2=Kitchen&category3=Pastry%2f+Decorating
from:
/MySite/Store/Kitchen/Pastry%2f+Decorating.aspx
Additionally consider using Routing instead of UrlRewrite.
Cheers,
Dmitriy.
Try the AbsolutePath or PathAndQuery properties on the Request object. Both of them should maintain the url encoding.
You can UrlEncode the URL before parsing it. Or better yet, keep URL's non-encoded in database. You don't even need to encode them if you use HyperLink control.
It turns out that the issue is occurring in IIS before .Net even gets its hands on the request. It appears that this is a dead end.
An additional word of warning is that my IIS test server (XP) was rejecting requests containing encoded amperstands as a security risk and could not be persuaded to cooperate with anything short of a registry edit. Not sure if this goes for all versions, but even if a server variable can be retrieved this seems like another good reason to use a different tactic.
Here is the follow-up question with the accepted solution-
ASP.Net URL Encoding

Server.Transferrequest() and getting the current URL

Say in my 'Page_init()' of "a.aspx" i just have 'server.transferrequest("b.aspx").
This works great, displays the content for "b.aspx" and the browserurl still stays at "a.aspx".
Happy days.
However does anyone know how to see this url from my "b.aspx" (the resulting page)?.
The usual request.rawurl and request.url.absoluteuri both return the current page as "b.aspx".
Server.TransferRequest performs an asynchronous execution of the specified URL. This means that your client has no clue of was is going on at the server so from your client perspective it's the same page.
If you need to change the actual page (which is the most common) then use Response.Redirect.
Maybe before you do the transfer you could save the information you need somewhere, then retrieve it when it's needed again.
You can use PreviousPage to get source page that makes server transfer :
string previousPagesUrl = PreviousPage.Request.RawUrl;
EDIT : #maxp, as an answer to your comment, PreviousPage only works for Server.Transfer and cross page postback.
You'll get null for PreviousPage if :
the source page redirects to the destination page.
a link at source page forwards the page to destination page.
NameValueCollection headers = new NameValueCollection();
headers["RawUrl"] = HttpContext.Current.Request.RawUrl;
Server.TransferRequest("b.aspx", true, null, headers);
And then use Headers["RawUrl"] in b.aspx.
Have you tried this method:
public void Transfer(string path, bool preserveForm )
http://msdn.microsoft.com/en-us/library/caxa892w.aspx
I currently got in the same problem, and I found out that Server object has this parameter on transfer method that gives you the posibility to preserve the original request form or not.

Process raw HTTP request content

I am doing an e-commerce solution in ASP.NET which uses PayPal's Website Payments Standard service. Together with that I use a service they offer (Payment Data Transfer) that sends you back order information after a user has completed a payment. The final thing I need to do is to parse the POST request from them and persist the info in it. The HTTP request's content is in this form :
SUCCESS
first_name=Jane+Doe
last_name=Smith
payment_status=Completed
payer_email=janedoesmith%40hotmail.com
payment_gross=3.99
mc_currency=USD
custom=For+the+purchase+of+the+rare+book+Green+Eggs+%26+Ham
Basically I want to parse this information and do something meaningful, like send it through e-mail or save it in DB. My question is what is the right approach to do parsing raw HTTP data in ASP.NET, not how the parsing itself is done.
Something like this placed in your onload event.
if (Request.RequestType == "POST")
{
using (StreamReader sr = new StreamReader(Request.InputStream))
{
if (sr.ReadLine() == "SUCCESS")
{
/* Do your parsing here */
}
}
}
Mind you that they might want some special sort of response to (ie; not your full webpage), so you might do something like this after you're done parsing.
Response.Clear();
Response.ContentType = "text/plain";
Response.Write("Thanks!");
Response.End();
Update: this should be done in a Generic Handler (.ashx) file in order to avoid a great deal of overhead from the page model. Check out this article for more information about .ashx files
Use an IHttpHandler and avoid the Page model overhead (which you don't need), but use Request.Form to get the values so you don't have to parse name value pairs yourself. Just pretend you're in PHP or Classic ASP (or ASP.NET MVC, for that matter). ;)
I'd strongly recommend saving each request to some file.
This way, you can always go back to the actual contents of it later. You can thank me later, when you find that hostile-endian, koi-8 encoded, [...], whatever it was that stumped your parser...
Well if the incoming data is in a standard form encoded POST format, then using the Request.Form array will give you all the data in a nice to handle manner.
If not then I can't see any way other than using Request.InputStream.
If I'm reading your question right, I think you're looking for the InputStream property on the Request object. Keep in mind that this is a firehose stream, so you can't reset it.

Resources