How to POST data to ASP.NET HttpHandler? - asp.net

I am trying to send a large chunk of data over to a HTTP handler. I can't send it using GET because of the URL length limit so I decided to POST it instead. The problem is that I can't get at the values. context.Request.Form shows that it has 0 items. So is there a way that I can POST data to a HttpHandler?

Having some code to look at would help diagnose the issue. Have you tried something like this?
jQuery code:
$.post('test.ashx',
{key1: 'value1', key2: 'value2'},
function(){alert('Complete!');});
Then in your ProcessRequest() method, you should be able to do:
string key1 = context.Request.Form["key1"];
You can also check the request type in the ProcessRequest() method to debug the issue.
if(context.Request.RequestType == "POST")
{
// Request should have been sent successfully
}
else
{
// Request was sent incorrectly somehow
}

I also had the same problem. It was an client/AJAX problem. I had to set the AJAX call request header "ContentType" to
application/x-www-form-urlencoded
to make it work.

I was having the same problem, and eventually figured out that setting the content type as "json" was the issue...
contentType: "application/json; charset=utf-8"
That's a line some popular tutorials suggest you to add in the $ajax call, and works well with ASPx WebServices, but for some reason it doesn't for an HttpHandler using POST.
Hard to catch since values in the query string work fine (another technique seen in the web, though it doesn't makes much sense to use POST for that).

The POST data that you are sending to your HTTP Handler must be in querystring format a=b&c=d. And you can retrieve it on the server-side using Request["a"] (will return b), and so on.

Faced similar problem. After correcting all issues, there was one more thing I missed in web.config - to change verb as * OR GET,POST. After that everything worked fine.
<httpHandlers>
...
<add verb="*" path="test.ashx" type="Handlers.TestHandler"/>
</httpHandlers>

POST fields are contained in
HttpContext.Request.Params
To retrieve them you can use
var field = HttpContext.Request.Params["fieldName"];

Related

Angular: Custom headers are ignored by $http and $resource. Why?

I'm trying to access a REST service I don't control. First problem is that the service doesn't include a Access-Control-Allow-Origin header, which is a problem that, if I understand correctly, immediately limits me to JSONP.
Also, by default, this service sends XML rather than JSON, though it's capable of sending JSON. I think it should respond to my Accept header, the people responsible for the service say it looks at my Content-Type. That would mean I'd need to do a POST rather than a GET (though get makes more sense when I'm just getting some static data, right?).
Stubborn as I am, I'm trying my Accept header first. Since Angular only accepts JSON, I'd expect it to use the Accept: application/json header by default, but it doesn't, and it ignores my attempts to set it manually:
app.config(['$httpProvider', function($httpProvider){
console.log($httpProvider.defaults.headers.common);
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.headers.post['Access-Control-Max-Age'] = '1728000';
$httpProvider.defaults.headers.common['Access-Control-Max-Age'] = '1728000';
$httpProvider.defaults.headers.common['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.useXDomain = true;
}]);
I do this again in the actual resource:
return $resource('http://foo.com/getStuff', {}, {
fetch: {
method:'JSONP',
params: params,
headers: {
'Accept':'application/json, text/javascript',
'Content-Type':'application/json; charset=utf-8'
},
isArray:false,
callback: 'JSON_CALLBACK'
}
});
But still, the request headers contain Accept: */*.
My question is: WHY? Why does Angular ignore my headers? And how do I get it to use the proper headers anyway?
And also: is there a way to use JSONP in a POST?
Edit: Originally I used Angular 1.0.7, but I just tried it with 1.2.3 and got the same results. Headers are ignored, yet everybody claims that this is the way to do it.
I also tried doing it directly with $http, rather than with $resource, with the same results.
Edit 2: Here's a JSFiddle. It's anonymized and doesn't use my real server, but using Firebug/developer tools, you can verify that it sends Accept: */* on both calls, despite my many attempts to set application/json headers. And that is my real problem here. On my real server, I'm getting an XML result because of that, despite my real server's ability to send JSON.
(Whether the real server supports jsonp is less relevant at the moment. This dummy server clearly doesn't, but that's okay. I just care about the headers.)
Edit 3: I've tried both solutions suggested below:
$http.defaults.headers.common['Accept'] = 'application/json, text/javascript';
$http.defaults.transformRequest.push(function (data, headersGetter) {
headersGetter().Accept = "application/json, text/javascript";
return data;
});
I've tried both statements separately. In the controller, and then in the service just before the http call itself. Still doesn't work.
Can someone give me a JsFiddle where this is shown to work?
Edit 4: I notice that when I use GET rather than JSONP, the Accept header is correct. But then the response is rejected because it doesn't have the correct header.
What kind of headers should a JSONP call have? Because there's a lot more headers in the JSONP call, but nothing that identifies it as JSONP. Does the server have to have explicit JSONP support for this to work? I suddenly realize I don't know nearly enough about jsonp.
I think your answer is here. According to the wiki, A JSONP call is executed through injection of a <script> tag to load the script from the host server, which responds by calling your callback, passing the data. A <script> tag generates a regular browser request (not an XmlHttpRequest), and the browser will send its own Accept header (it also sends its own User-Agent header, for example).
I would hope there is an easier client-side way to do this, but I think the only way may be the one suggested in the referenced post:
So, if you want to be able to set request headers for cross domain calls
you will have to setup a server side script on your domain that will
delegate the call to the remote domain (and set the respective
headers) and then send the AJAX request to your script.
EDIT: here is a (rejected) jQuery bug report about this same problem.
Some more background info:
In angular, callbacks are managed automagically, so if your say this:
$http({
method: "JSONP",
url: "http://headers.jsontest.com?callback=JSON_CALLBACK",
}).success(function(data) {
console.log('Return value:');
console.log(data);
}).error(function(data) {
console.log('Error!');
console.log(data);
})
a <script> tag will be created that looks more or less like this:
<script type="application/javascript"
src="http://headers.jsontest.com/?callback=angular.callbacks._1">
</script>
The content of the response to http://headers.jsontest.com/?callback=angular.callbacks._1 will be:
angular.callbacks._1({key1: "value1", key2: "value2"});
angular.callbacks._1 will contain your success function, and it will be called with the data.
While what you have is supposed to work according to the docs, my experience has been a bit different. To get around this issue, we did the following:
Create a "base controller" that gets added to the page either on the body or html tag.
In that controller, make the assignment using $http instead of $httpProvider. Because your base controller loads when the initial page loads, it is there for all other controllers and services that will run in your app.
I don't know why this works and the proscribed method does not, and I'd love to see an answer to your question that is better than this work-around, but at least this can get you moving forward with development again.
The following works for me - however, I do that during "runtime" with $http and I am not using $httpProvider during bootstrapping.
function SomeCtrl($http) {
$http.defaults.transformRequest.push(function (data, headersGetter) {
headersGetter().Accept = "application/json, text/javascript";
return data;
});
}
Edit
Here is a working jsFiddle version. Check the request which is done with Developer Tools/Firebug and see that "application/json, text/javascript" is requested.

Is it considered bad practice to perform HTTP POST without entity body?

I need to invoke a process which doesn't require any input from the user, just a trigger. I plan to use POST /uri without a body to trigger the process. I want to know if this is considered bad from both HTTP and REST perspectives?
I asked this question on the IETF HTTP working group a few months ago. The short answer is: NO, it's not a bad practice (but I suggest reading the thread for more details).
Using a POST instead of a GET is perfectly reasonable, since it also instructs the server (and gateways along the way) not to return a cached response.
POST is completely OK. In difference of GET with POST you are changing the state of the system (most likely your trigger is "doing" something and changing data).
I used POST already without payload and it "feels" OK. One thing you should do when using POST without payload: Pass header Content-Length: 0. I remember problems with some proxies when I api-client didn't pass it.
If you use POST /uri without a body it is something like using a function which does not take an argument .e.g int post (void); so it is reasonable to have function to your resource class which can change the state of an object without having an argument. If you consider to implement the Unix touch function for a URI, is not it be good choice?
Yes, it's OK to send a POST request without a body and instead use query string parameters. But be careful if your parameters contain characters that are not HTTP valid you will have to encode them.
For example if you need to POST 'hello world' to and end point you would have to make it look like this: http://api.com?param=hello%20world
Support for the answers that POST is OK in this case is that in Python's case, the OpenAPI framework "FastAPI" generates a Swagger GUI (see image) that doesn't contain a Body section when a method (see example below) doesn't have a parameter to accept a body.
the method "post_disable_db" just accepts a path parameter "db_name" and doesn't have a 2nd parameter which would imply a mandatory body.
#router.post('/{db_name}/disable',
status_code=HTTP_200_OK,
response_model=ResponseSuccess,
summary='',
description=''
)
async def post_disable_db(db_name: str):
try:
response: ResponseSuccess = Handlers.databases_handler.post_change_db_enabled_state(db_name, False)
except HTTPException as e:
raise (e)
except Exception as e:
logger.exception(f'Changing state of DB to enabled=False failed due to: {e.__repr__()}')
raise HTTPException(HTTP_500_INTERNAL_SERVER_ERROR, detail=e.__repr__())
return response

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

ASP.NET's equivalent of PHP's $_GET and $_POST?

As thet title says.
I'm new to asp.net, and I'm sorta trying to build some AJAX-stuff to learn.
ASP.Net AJAX may also be worth reading as there are some built-in things that could be useful.
"Request.QueryString" and "Request.Form" are the likely answers to the title question.
Following up with marr75's response, the Request property exposes a dictionary of GETed and POSTed variables.
See http://msdn.microsoft.com/en-us/library/swe97x0b.aspx.
It explains how to access the response and request context. If you're going to do ajax stuff, you might want to think about WCF REST, in which case, it's totally different and I would recommend going through some tutorials to see how the http elements of the application are abstracted away. In any event, in a lot of ASP.NET development, you don't touch the response and request contexts directly.
Request object is a map of all the request headers - both from the POST request and URL encoded params:
//This will retrieve the value of "SomeHeader" from the request
//e.g. http://localhost/page.aspx?SomeHeader=thisisvalue
string value = HttpContext.Current.Request["SomeHeader"];
//value == "thisisvalue"

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