How to process a HTTP POST? - c#

I have a HTTP handler which receives a HTTP POST.
HTTP POST message with header is -
POST /ibe/example.com HTTP/1.1
Content-Length: 445
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: */*
Host: 202.177.46.142
charset=UTF-8&param1=val1&param2=val2
Handler in my code is -
var V1 = context.Request["param1"];
var V2 = context.Request["param2"];
But this didn't work.

I think you should be using:
var V1 = context.Request.Param["param1"];
var V2 = context.Request.Param["param2"];
Taken from this example here: http://forums.asp.net/t/1190337.aspx and here How to send data to httphandler

Related

How to call Multipart message request in c#

I need to call an endpoint that requires the Request Header and Request Body with Content-type
and content-length and some other property as well which need to End with BOUNDARY.
Request Header
POST https://www.API-URL.com/ HTTP/1.1
Host: www.API-URL.com
Content-type: multipart/mixed; boundary=BOUNDARY
Content-length: 1034
Request Body
--BOUNDARY
Content-type: application/x-www-form-urlencoded
Content-length: 141
AppVersion=1.0&AcceptLicenseAgreement=Yes&ResponseType=application/x-x-pld&VersionNumber=xxx&UserId=xxxx&Password=xxxxx
--BOUNDARY
Content-type: application/x-x-binary
Content-length: 6
020020 // This the string Data which I need to post
--BOUNDARY--
How can I implement a call to this endpoint by using HttpClient?
Thanks in advance

Different results with Postman and RestSharp

I am testing a WebService on Postman v7.36.0 and I am getting the json without issue. So I copy the code that Postman gaves to use on C# but I am getting a different result a error response saying that I am not using a right input to obtain data (custom error from the source of the webservice).
¿Why I am getting diferent result if I just copied and pasted the code?
¿How can I debug this?
¿Could be a problem the space between the date and the hour?
¿How can I be sure if the inputs that I am sending on Postman are really the same on the RestSharp code?
The code used needs a token that I am getting without problem on another webservive that I have to invoke previously. I copied and pasted the code given on Postman as well and it worked.
To get the token:
var client = new RestClient("http://URL:port/api");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("user", "user");
request.AddParameter("pass", "pass");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
To get the list of people:
var client = new RestClient("http://URL:PORT/api/API");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer " + thetoken);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("startDate", "2020-10-01 00:00");
request.AddParameter("finishDate", "2020-10-31 23:59");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
EDIT: The webservice returns a json with a list of person with the cuantity of days worked between start and finish date.
EDIT 2: I think the issue is about the date format or the way the dates are sent. Using Fiddler I see with Postaman the raw request is:
GET http://URL:port/api/API HTTP/1.1
Authorization: Bearer thetokenxxxx
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Cache-Control: no-cache
Postman-Token: b877f51b-550e-45ff-b4e4-50ca01412491
Host: URL:port
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 66
startDate=2020-10-01%2000%3A00&finishDate=2020-10-31%2023%3A59
But with RestSharp v105.2.3 the raw request is:
GET http://URL:port/api/API?startDate=2020-10-01%2000%3A00&finishDate=2020-10-31%2023%3A59 HTTP/1.1
Authorization: Bearer thetokenxxxx
Content-Type: application/x-www-form-urlencoded
Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
User-Agent: RestSharp/105.1.0.0
Host: URL:port
Accept-Encoding: gzip, deflate

Return Unauthorized (401) only when calling from code (c#)

UPDATE
As #Alexandru Clonțea suggested, I checked the fiddler log and found:
In both success or fail cases, there are actually 2 requests being sent. The first request are mostly the same for both cases, it's something like:
GET http://myservice.com/handler?param1=something&param2=somethingelse HTTP/1.1
Authorization: Basic xxxxxx
Accept: application/json, application/xml, text/json, text/x-json,
text/javascript, text/xml
User-Agent: RestSharp/100.0.0.0
Host: myservice.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
The response for them are the same, which is:
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=utf-8
Location: /handler/?param1=something&param2=somethingelse
Date: Sat, 08 Sep 2018 01:50:16 GMT
Content-Length: 115
Moved Permanently.
I have noticed that it always try to redirect the call to /handler/?param1=something&param2=somethingelse, and that's because of the setup of the server code. it's actually working as expected. The difference is in the second request. The second request of the failure case (which is the c# code) doesn't have the authorization header and that's why it failed. Now, my question will be, why does the second request miss the authorization header? How can I fix it? Below is an example of the failed request:
GET http://myservice.com/handler/?param1=something&param2=somethingelse HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json,
text/javascript, text/xml
User-Agent: RestSharp/100.0.0.0
Accept-Encoding: gzip, deflate
Host: myservice.com
Backgroud:
I have a service written in GO deployed on a server. It requires a basic authentication. For example, I can call it successfully with the following request:
GET /handler/?
param1=something&param2=somethingelse HTTP/1.1
> Host: myservice.com
> Authorization: Basic xxxxxx
> User-Agent: RestClient/5.16.6
> Accept: */*
The request above is made by a rest api client tool (like postman), and it's working fine. It's also working fine if I call it from a browser.
Problem:
Now, I try to make the same call to the same service using c# code, and I have it as:
// pass cert validation
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
HttpClient client = new HttpClient();
var byteArray = Encoding.ASCII.GetBytes(username + ":" + password);
var auth = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Authorization = auth;
var response = client.SendAsync(request).Result; // don't need async
But in this case, I am getting Unauthorized (401) back. I have checked into the actually request that was sent by the code, it had exactly the same authorization header as the one shows above (Authorization: Basic xxxxxx, and the xxxxxx is the same as above) and same uri as well. Actually, everything it sent looks the same as when I used the rest api client tool, but it was just failed in code.
when I check the log on the server side, I see the log below when it returns 401:
[GIN-debug] redirecting request 301: /handler --> /hanlder/?param1=something&param2=somethingelse
but I don't see this log when the call is from the rest api client tool (or browser)
As you may know from the log, the server-side code is using the go gin framework. But since it works fine in other cases, I don't think it's a problem with the server-side code.
Back to the C# code, I have tried to use the HttpWebRequest with NetworkCredential instead of the HttpClient, and I also try to use client.DefaultRequestHeaders.Authorization = auth, but I was still getting the same error.
I am wondering if someone has seen this before or could help? It will be really appreciated.
As a workaround, I can modify the request to be http://myservice.com/handler/?param1=something&param2=somethingelse so that no redirection is needed. Thus, it will be correctly authorized.
But still, haven't figure out how to make the second request to be sent with the authorize header yet.

RestSharp - Service Unavailable - Maximum number of active clients reached

I'm using RestSharp to communication with an Web Service.
I use this code
public static object GetTagValue(string url, string tagname, out string resp)
{
object result = null;
resp = string.Empty;
string theReq = string.Format("tags/{0}", tagname);
var client = new RestClient(url);
var request = new RestRequest(theReq, Method.GET);
request.RequestFormat = DataFormat.Json;
IRestResponse response = client.Execute(request);
resp = response.Content;
if (!string.IsNullOrWhiteSpace(resp))
{
dynamic json = JValue.Parse(resp);
if (null != json.value)
{
result = json.value;
}
}
return result;
}
Call to the server
GET http://ame-hp/tags/int32 HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json,
text/javascript, text/xml
User-Agent: RestSharp/105.2.3.0
Host: ame-hp
Accept-Encoding: gzip, deflate
Response from the server for a working call:
HTTP/1.1 200 Ok
Server: Internet Pack HTTP Server
Connection: Close
Set-Cookie: SID=f11985564d;Expires=Fri, 27 Jan 2017 07:52:17
GMT;Path=/
Content-Type: application/json
Content-Length: 133
{"quality":"Good","description":"","name":"int32","value":0,"dataType":"int32","controllers":[],"initialValue":null,"readonly":false}
It's working but after two calls the service answers with this
{"Code":503,"Message":"Service Unavailable - Maximum number of active clients reached."}
Third call to server
GET http://ame-hp/tags/int32 HTTP/1.1
Accept: application/json, application/xml, text/json, text/x-json,
text/javascript, text/xml
User-Agent: RestSharp/105.2.3.0
Host: ame-hp
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Response from the server for all calls from now and until the server is restarted
HTTP/1.1 503 Service Unavailable - Maximum number of active clients
reached.
Server: Internet Pack HTTP Server
Connection: Keep-Alive
Content-Type: application/json
Content-Length: 88
{"Code":503,"Message":"Service Unavailable - Maximum number of active
clients reached."}
So I assume that the service has a limit of two clients.
But why do there exist two active clients?
Either the Server or RestSharp is not closing the connection, but which?
Is there something I can do in RestSharp to close the connection?
The problem was, as I assumed, that the server only allows 2 clients. On the first connection a Session Cookie is sent back and this has to be used for the rest of the calls.
In RestSharp you only need to add one line to make this happen
After creating the client (which by the way you need to reuse for all the calls). You add this line:
client.CookieContainer = new System.Net.CookieContainer();
The initialization of the client would be
client = new RestClient();
client.CookieContainer = new System.Net.CookieContainer();
Then you can use
client.BaseUrl = new Uri(url);
To set the url you want to call

FromBody not binding string parameter

I have an issue similar to ASP.NET MVC 4 RC Web API Parameter Binding Issue, but I'm trying to solve it by using the [FromBody] attribute.
Fiddler reports the following request (excluding irrelevant bits like User Agent String)
PUT http://localhost:82/api/account/shoppinglistitems HTTP/1.1
Host: localhost:82
Connection: keep-alive
Content-Length: 11
Origin: http://localhost:3000
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/javascript, */*; q=0.01
query=apple
My controller action is
[HttpPut]
public ShoppingListItemWebModel CreateShoppingListItem([FromBody]string query) {
// query is null
}
I could wrap the parameter in a complex type, but that seems like a hack to fix the issue. Or I could put the query in the URI, but that doesn't fit the pattern of the rest of the API. Is it possible to do it this way? If so, where is my mistake?
change your request to be
PUT http://localhost:82/api/account/shoppinglistitems HTTP/1.1
Host: localhost:82
Connection: keep-alive
Content-Length: 11
Origin: http://localhost:3000
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/javascript, */*; q=0.01
=apple
notice the lack of "query"
If you're using AngularJS instead of jQuery you might want to opt for the following alternative, since AngularJS uses content type application/json by default.
PUT http://localhost:82/api/account/shoppinglistitems HTTP/1.1
Host: localhost:82
Connection: keep-alive
Content-Length: 7
Origin: http://localhost:3000
Content-Type: application/json
Accept: application/json, text/javascript, */*; q=0.01
'apple'
Notice that the value is wrapped in string quotes (either single or double).

Categories

Resources