How can I send a GET request with json body? - c#

Is there any way at all that I can send a GET request with a JSON body using c#? I am making a call to an API to retrieve a list of items using a GET request, but I have to pass the customer_id in JSON. I am able to do this successfully in Postman and Python. However, the legacy app that I am working with is built as c# .NET winform. I am able to make other calls using HttpClient, but after some research I am finding that this class does not allow GET request with body except when using CORE. Are there any other alternatives?

According to Ian Kemp's answer to this question,
This can be done in .NET Framework projects using the System.Net.Http.WinHttpHandler Library. (I'll just add the relevant part of the answer here, but I recommend to go check his full answer)
First, Install the System.Net.Http.WinHttpHandler Library from Nuget and then use it as your http client handler as described below:
var handler = new WinHttpHandler();
var client = new HttpClient(handler);
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("some url"),
Content = new StringContent("some json", Encoding.UTF8, ContentType.Json),
};
var response = await client.SendAsync(request).ConfigureAwait(false);
//Handle the response as you see fit

With the HTTP method GET, the body has no meaning. It will be ignored according to the HTTP specs. When getting resources from your API using the GET http verb, you have the option to pass a query string (http://somedomain.com/api/getValues?key=1) or pass the parameter directly in the url (http://somedomain.com/api/getValues/1)
To receive it in your controller, you would have to expect either the parameter or the query string like this:
If the parameter is in the URL:
[HttpGet("/api/getValues/{id}")]
public async Task<IActionResult> GetValues(int id){}
(Make sure that your parameter name in the function matches the name that you gave to it in the route)
If the parameter is a query string:
[HttpGet("/api/getValues")]
public async Task<IActionResult> GetValues(string key){}
(Make sure that the query string key name matches the parameter name in your function)
The best practice is to use the parameter in the URL. Query strings are very useful, but you have to know when to use it, for example, if you want to narrow down the results given certain values, you could the query string to send them.

Related

Attempting to pass empty body to POST endpoint with WebClient

I currently have an endpoint in my project:
[HttpPost("process")]
public IActionResult Process (string Val1, [FromBody] object Json)
{
//processing.....
Return Ok(...);
}
And on my client side I am trying to call this endpoint with WebClient like so:
string response = null;
string body = "{}";
using (var client = new WebClient())
{
client.UserDefaultCredentials = true;
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
response = client.UploadString("localhost:55555/api/process?Val1=Param", body);
}
Here's where my concerns are:
For this endpoint, I will typically be passing a JSON object
However, I want this endpoint to also NOT require a body, I would want it to be empty, as the endpoint should not require it
If you look at my body variable - I am setting it to "{}" otherwise I've not found a different way to pass "EMPTY" body to the endpoint
Questions:
How do I properly pass an EMPTY body to this endpoint? (this endpoint will be used by different clients, and I am just looking for best practice approach to this?
In my endpoint, I have [FromBody] object Json parameter. Is it a better practice to have it be as object or can I alternatively do JObject that could still accept an Empty body
Forgive my "noobness" with these questions if they seem obvious, I'm just getting started in the API development and want to make sure I am using best practices.
You're currently using a WebClient, which is outdated in favour of HttpClient (see this answer). When using HttpClient you can post empty bodies as follows: await client.PostAsync("localhost:55555/api/process?Val1=Param", null);
As for your second question. Look into Data Transfer Objects, aka DTOs. They are in a nutshell dumb types you can use purely for passing and receiving data through your API, you can add things like validation to them as well. Using object or JObject is only needed if you're receiving dynamic data, otherwise use DTOs where possible.

RestSharp PUT request parameters

I'm having issues figuring out how to create a put request using RestSharp.
I need to pass an integer followed by a JSON body in the same request.
So far I have this:
for (var i = 0; i < ReorderedTasks.Count; i++) {
var reorderedTasksJson = new JavaScriptSerializer().Serialize(ReorderedTasks[i]);
var request = new RestRequest("api/task/5/{ID}/", Method.PUT);
request.AddParameter("ID", ReorderedTasks[i].ID.ToString(), ParameterType.UrlSegment);
request.AddParameter("application/json; charset=utf-8", reorderedTasksJson, ParameterType.RequestBody);
client.Execute(request);
}
I've tested out the JSON ad requestBody on POST and it works fine. I think my issue is with the first parameter I'm trying to pass ReorderedTasks[i].ID , I'm not sure if I'm handling the passing of this correctly.
I've initialised client at the beginning of my class.
Problem is the DB isn't updating and I need to isolate the problem. Is the above the correct way in dealing with my two parameters needing passed?
I suggest to put ReorderedTasks[i].ID.ToString() directly to url path.
var request = new RestRequest($"api/task/5/{ReorderedTasks[i].ID.ToString()}/", Method.PUT);
It will help to reduce possible problems with http request format.
I'll add it here, so someone will benefit from it.
If your endpoint URL have parameters like ?param=value&param2=value that you want to pass along with request RestSharp's AddParameter(string, string) won't work with PUT method (but it works just fine with GET or if endpoint doesn't have URL parameters, so it is deceiving)
Use AddParameter(string, string, ParameterType.QueryString) in order to PUT Method work correctly.
Well it depends on what does the webApi expect..
You could use Fiddler to inspect what being sent through the wire and what response You are getting (http://www.telerik.com/fiddler)
Also - here are some sample's how other users use RestSharp
How do I use PUT in RestSharp?

Read content body from a HTTP GET in C# WebAPI

I have a WebAPI C# application. My GET method is defined as:
[HttpGet]
public HttpResponseMessage Get(string id)
This API retrieves some content from a database, based on a given id. Another parameter is required but it is so long that having it on the URL would not work, so I'm using the GET body to send such second parameter.
How can I retrieve it from inside the get method?
I tried
var dataOnBody = await Request.Content.ReadAsStringAsync();
but it doesn't work as the Get method is not async and I think it doesn't need to be that (I want a normal blocking function which reads the content of the body and outputs a string)
I just need a simple way to extract my string from the request body
Even if you somehow manage to do this, you will find that support is not universal. The HTTP specs say:
The GET method means retrieve whatever information (in the form of an
entity) is identified by the Request-URI.
So the data returned relies only on the URI, not anything in the body. Many libraries won't even let you send a request body during a GET.

WebRequest: Query string data vs x-www-form-urlencoded content

I am trying to call Google's OAuth2 authentication service as per these instructions: https://developers.google.com/accounts/docs/OAuth2ForDevices
I put all of the required parameters into the query string and sent the request. This worked for the "Obtaining a user code" section but not for the "Obtaining Access and Refresh Tokens" section.
After much playing around and getting 400 Bad Request errors, I found that, instead of putting the data in the query string, you can create a request with a FormUrlEncodedContent and send the data through as content with application\x-www-form-urlencoded Content-Type.
Here is the code before:
var requestMessage = new HttpRequestMessage();
requestMessage.Method = "POST";
requestMessage.RequestUri = new Uri(fullUrl);
Where fullUrl is something like:
https://accounts.google.com/o/oauth2/device/code?client_id=812741506391-h38jh0j4fv0ce1krdkiq0hfvt6n5amrf.apps.googleusercontent.com&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile
And the new code is:
var requestMessage = new HttpRequestMessage();
requestMessage.Method = "POST";
requestMessage.RequestUri = new Uri(url);
requestMessage.Content = new FormUrlEncodedContent(CreateDictionary(queryStringNames, queryStringValues));
Where url is:
https://accounts.google.com/o/oauth2/device/code
and queryStringNames and queryStringValues are string arrays of the names and values of the required parameters.
What is the difference between these two methods? Is it safe to assume that all POST calls can use the URL Encoded Content requests instead of putting the data in the query string?
In general, POST requests do not need query string but it is still subjected to Server's logic implementation. In case of OAuth which is quite known standard and they do follow good practice, it is safe to use form encoded data unless mentioned explicitly in API to send Parameter as query string.
Query String & Post data are two different set of parameters. If server is expecting Query string then you must send query string only. It all depends on how server side logic is implemented. You can not use them alternatively. Most API documentation specify clearly what are they expecting.

Is there a .NET ready made method to process response body of a HttpListener HttpListenerRequest body?

I'm using HttpListener to provide a web server to an application written in another technology on localhost. The application is using a simple form submission (application/x-www-form-urlencoded) to make its requests to my software. I want to know if there is already a parser written to convert the body of the html request document into a hash table or equivalent.
I find it hard to believe I need to write this myself, given how much .NET already seems to provide.
Thanks in advance,
You mean something like HttpUtility.ParseQueryString that gives you a NameValueCollection? Here's some sample code. You need more error checking and maybe use the request content type to figure out the encoding:
string input = null;
using (StreamReader reader = new StreamReader (listenerRequest.InputStream)) {
input = reader.ReadToEnd ();
}
NameValueCollection coll = HttpUtility.ParseQueryString (input);
If you're using HTTP GET instead of POST:
string input = listenerRequest.Url.QueryString;
NameValueCollection coll = HttpUtility.ParseQueryString (input);
The magic bits that fill out HttpRequest.Form are in System.Web.HttpRequest, but they're not public (Reflector the method "FillInFormCollection" on that class to see). You have to integrate your pipeline with HttpRuntime (basically write a simple ASP.NET host) to take full advantage.
If you want to avoid the dependency on System.Web that is required to use HttpUtility.ParseQueryString, you could use the Uri extension method ParseQueryString found in System.Net.Http.
Make sure to add a reference (if you haven't already) to System.Net.Http in your project.
Note that you have to convert the response body to a valid Uri so that ParseQueryString (in System.Net.Http)works.
string body = "value1=randomvalue1&value2=randomValue2";
// "http://localhost/query?" is added to the string "body" in order to create a valid Uri.
string urlBody = "http://localhost/query?" + body;
NameValueCollection coll = new Uri(urlBody).ParseQueryString();

Categories

Resources