Attempting to pass empty body to POST endpoint with WebClient - c#

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.

Related

How can I send a GET request with json body?

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.

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?

How to access the HTTP request body using RestSharp?

I'm building a RESTful API client using C# .NET 3.5.
I first started building it with the good old HttpWebClient (and HttpWebResponse), I could do whatever I wanted with. I were happy. The only thing I stumbled upon was the automatic deserialization from JSON response.
So, I've heard about a wonderful library called RestSharp (104.1) which eases the development of RESTful API clients, and automatically deserialize JSON and XML responses. I switched all my code on it, but now I realize I can't do things I could do with HttpWebClient and HttpWebResponse, like access and edit the raw request body.
Anyone has a solution?
Edit: I know how to set the request body (with request.AddBody()), my problem is that I want to get this request body string, edit it, and re-set it in the request (in other words: updating the request body on the fly)
The request body is a type of parameter. To add one, you can do one of these...
req.AddBody(body);
req.AddBody(body, xmlNamespace);
req.AddParameter("text/xml", body, ParameterType.RequestBody);
req.AddParameter("application/json", body, ParameterType.RequestBody);
To retrieve the body parameter you can look for items in the req.Parameters collection where the Type is equal to ParameterType.RequestBody.
See code for the RestRequest class here.
Here is what the RestSharp docs on ParameterType.RequestBody has to say:
If this parameter is set, it’s value will be sent as the body of the
request. The name of the Parameter is ignored, and so are additional
RequestBody Parameters – only 1 is accepted.
RequestBody only works on POST or PUT Requests, as only they actually
send a body.
If you have GetOrPost parameters as well, they will overwrite the
RequestBody – RestSharp will not combine them but it will instead
throw the RequestBody parameter away.
For reading/updating the body parameter on-the-fly, you can try:
var body = req.Parameters.FirstOrDefault(p => p.Type == ParameterType.RequestBody);
if (body != null)
{
Console.WriteLine("CurrentBody={0}", body.Value);
body.Value = "NewBodyValue";
}
Or failing that, create a new copy of the RestRequest object with a different body.

adding content to a getasync

when using HttpClient and performing a PostAsync I am able to add a contract with HttpContent. for example
HttpContent content = new ObjectContent<myContractType>(MyContract, xmlFormatter);
var resp myClient.PostAsync(myUri,content).Result
when doing a GetAsync I am unable to pass a HttpContract object. That said do I need to just add the members of the contract in a query string or is there a better way to go about it?
The nature of GET requests does not provide a way to send large amounts of data to the server as might be done with a POST request. In practice, a limited amount of data can be sent in the form of headers or as part of a querystring.
There won't be a way to convert the XML data directly to a querystring, but this is an example of a request with a querystring:
var client = new HttpClient()
client.GetAsync(String.Format("http://service.example.com/api/{0}?foo=bar", id))

json with C# in a WCF service?

I am looking at adding SMS abilities to my WCF service. I found a cheap SMS service called Penny SMS.
Their interface supports json. But I have no idea how to call it in my WCF service.
Here is the interface/example:
Sample JSON-RPC Request
{ "method": "send",
"params": [
"YOUR_API_KEY",
"msg#mycompany.com",
"5551231234",
"Test Message from PENNY SMS"
]
}
How would I call that with C# from a WCF service? What I am looking for is a way to wrap this into a method call. Something like:
StaticSMSClass.SendSMS("1234567890", "My Message to send");
Note they also support an XML-RPC API if that is more doable from C#.
UPDATE: I made a stab at creating a call myself, but it did not work. I am going to post my attempt in a separate question and see if anyone has a way to do it.
You need to send a HTTP POST with the JSON message to the remote server. You can do this with HttpWebRequest. You either build the JSON manually (the messages seem simple), or define types for it and use a JSON serializer.
MSDN has an example, for your case it would look something like (untested):
string json = // Your JSON message
WebRequest request = WebRequest.Create ("http://api.pennysms.com/jsonrpc");
request.Method = "POST";
var postData = Encoding.UTF8.GetBytes(json);
request.ContentLength = postData.Length;
request.ContentType = "text/json";
using(var reqStream = request.GetRequestStream())
{
reqStream.Write(postData);
}
using(var response = request.GetResponse())
{
// Response status is in response.StatusCode
// Or you can read the response content using response.GetResponseStream();
}
See my answer to the question "Client configuration to consume WCF JSON web service" for how the create a JSON client with WCF.
The answers so far are good, but one additional thing you can take advantage of (since you are within a WCF service) is the use of DataContractJsonSerializer.
In particular, I refer to how you actually populate your JSON in the first line of driis's example.
string json = // Your JSON message
Now, one of the best ways to do this may be to create a new class with these members:
[DataContract]
class SomeType
{
[DataMember]
string method;
[DataMember]
string[] params;
}
Then, just create an instance of SomeType every time and serialize it to JSON using the DataContractJsonSerializer every time you want to send over a piece of data. See http://msdn.microsoft.com/en-us/library/bb412179.aspx for how to use the DataContractJsonSerializer stand-alone.
Hope this helps!
Check the WCF REST API. They serve JSON, maybe they also can send JSON (in intra WCF solution it works). Maybe you have to construct the contract in wsdl to get the service running but maybe it works out.

Categories

Resources