C# RestSharp AddJsonBody() doesn't add API call Body name - c#

I am working with RestSharp and an API I believe is set up with Azure. I making a POST request to the API, but have noted that the request only works when the body is named, "agentGetRequest" in Postman.
Bad Body:
{
"supplierKey": "XXXX-XXXX-XXXX-XXXX",
"inputDate": "2021-01-17T00:00:00.000Z"
}
Good Body:
{
"agentGetRequest": {
"supplierKey": "XXXX-XXXX-XXXX-XXXX",
"inputDate": "2021-01-17T00:00:00.000Z"
}
}
So when I run my code
void Post(AgentRequest agentRequest, Credentials creds )
{
Uri baseUrl = new Uri(creds.baseURL);
IRestClient client = new RestClient(baseUrl);
IRestRequest request = new RestRequest(ENDPOINT, Method.POST);
request.AddHeader("subscriptionKey", creds.subscriptionKey);
// Option 1:
request.AddJsonBody(agentRequest);
// Option 2:
request.AddJsonBody(agentRequest, "agentGetRequest")
IRestResponse<GetAgentResponse> response = client.Execute<GetAgentResponse>(request);
if (response.IsSuccessful)
{
Console.WriteLine(JsonConvert.SerializeObject(response.Content));
}
else
{
Console.WriteLine(response.ErrorMessage);
}
}
// Body request object
public class AgentRequest
{
public string inputDate { get; set; }
public string supplierKey { get; set; }
}
It throws a bad request error because it can't find the body, "agentRequest."
I have found a workaround where I feed it a string as the body - but this would hate to have to do this for every endpoint:
// Instead of request.AddJsonBody()...
string body = "{\"agentGetRequest\": {\"supplierKey\": \"XXXX-XXXX-XXXX-XXXX\",\"inputDate\": \"2021-0117T00:00:00.000Z\"}}";
request.AddParameter("application/json", body, ParameterType.RequestBody);
How can I correctly format the body when adding it via AddJsonBody to include the name (and maybe the encapsulating brackets)?

Recording to the accepted answer of RestSharp Post a JSON Object, you could add JSON body like below:
request.AddJsonBody(
new
{
agentGetRequest = agentRequest
}); // AddJsonBody serializes the object automatically

Related

How to add below request body (string) in Postman using http client?

Postman Post call Screenshot
Hi Below is my current code:
var url = "https://localhost:44332/token";
var login = new Login()
{
username = "test#gmail.com",
password = "Password#1",
grant_type = "password"
};
using (var client = new HttpClient())
{
httpResponseMessage = await client.PostAsJsonAsync(url, login);
if (httpResponseMessage.IsSuccessStatusCode)
{
var token = httpResponseMessage.Content.ReadAsStringAsync();
}
}
My error is that 400: Bad Request, whenever i make the API call.
If i use postman, its working,
The following is what i put in POSTMAN body:
"username=test#gmail.com&password=Password#1&grant_type=password"
Many Thanks in advance if anyone can correct me!
It looks like you're trying to get hte token from OAuth 2.0 authentications server. You shouldn't be posting JSON - it expects the data as form. It returns a JSON object with access token storen in property access_token - you probably will need to deserialize it as well.
using System.Net.Http.Json;
using System.Text.Json.Serialization;
var url = "https://localhost:44332/token";
var form = new Dictionary<string, string>
{
{"grant_type", "password"},
{"username","test#gmail.com#1"},
{"password", "Password#1"},
};
using (var client = new HttpClient())
{
var response = await client.PostAsync(url, new FormUrlEncodedContent(form));
if (response.IsSuccessStatusCode)
{
var token = await response.Content.ReadFromJsonAsync<Token>();
var accessToken = token.AccessToken;
}
}
class Token
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }
[JsonPropertyName("token_type")]
public string TokenType { get; set; }
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }
[JsonPropertyName("refresh_token")]
public string RefreshToken { get; set; }
}
Do you pass these parameters by URL in postman? This form username=test#gmail.com&password=Password#1&grant_type=password looks like you use URL past parameters in postman.
Usually, in POST requests we pass parameters in the request body, not the URL.
Besides, a recommendation is not directly a HttpClient instance. If you use .NET Framework and create the HttpClient instance directly, cannot release the socket resource even if you disposable the HttpClient object. If you use .NET Core, you can inject an HttpClient or IHttpClientFactory.
Refers: Use IHttpClientFactory to implement resilient HTTP requests

How to convert Object and view it on WebAPI?

Here is my question,
I got a Web API and client(winform), client will send out data with a Serialize Object. My Web API do have received and return a response to client. But I can't view the data on Web API, I do have try using Deserialize Object and convert it into string but not working neither.
Please help me,Thanks!
Here is my code:
Client
private string WebApiPost(string sParam, string sJson)
{
var client = new HttpClient();
var content = new StringContent(sJson, Encoding.UTF8, "application/json");
var response = client.PostAsync(sWebAPI_URL + sParam, content).Result;
var body = response.Content.ReadAsStringAsync().Result;
return body;
}
This is my Web API
public object Post([FromBody]object hL7)
{
//what should I do???
//I've tried set hL7 into string but it wont get any data;
//I've also tried deserialize it but will get 500 internal server error.
return hL7;
}
This is my WebAPI model
public class HL7MID
{
public string LOC { get; set; }
public string COMPANY { get; set; }
}
public class HL7MID_List
{
public string sMSG { get; set; }
public List<HL7MID> data = new List<HL7MID>();
}
Because sJson matches HL7MID, you can use that type in as a paramter of your Post function, and just use that type.
public HL7MID Post([FromBody]HL7MID hL7)
{
//use hL7 here
return hL7;//also since you know the return type, changing that to HL7MID is suggested
}

Is there a way to send a List<> object through POST Method of REST API from one project through other?

I have a class Contacts.cs which contains class ContactsDTO, as shown in the below code
namespace WindowsScheduling
{
public class ContactsDTO
{
public string ContactFirstName { get; set; }
public string ContactLastName { get; set; }
public string ContactAddress1 { get; set; }
public string Class { get; set; }
}
}
Now I want to send an object List<ContactsDTO> to an another project through REST API.
The method which I have implemented for this purpose is :-
public string SendContactToKentico( List<ContactsDTO> objDeserializedMessage)
{
var RemoteURL = ConfigurationManager.AppSettings["RemoteURL"].ToString();
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(RemoteURL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage responseMessage = client.GetAsync(RemoteURL + "/Schedule/GetContactsByScheduler",objDeserializedMessage).Result;
return msg;
}
But here my objectDeserializedobject is showing an error :-
Cannot convert from 'System.Collection.Generic.List' to 'System.Net.Http.HttpCompletionOption'
You can't send a body with a GET request. Make sure to read the documentation for the classes you are using. The error message is telling you that none of the overloads for GetAsync take an argument representing body data. Choose the appropriate http verb for sending content; probably POST.
You could probably try something like this...
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(RemoteURL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string url = $"endPoint";
ObjectContent content = new ObjectContent<List<ContactsDTO>>(objMessage, new JsonMediaTypeFormatter());
HttpResponseMessage response = await client.PostAsync(url, content);
Please note: you may not need to use objDeserializedMessage, and you could just use objMessage. And also, I have done PostAsync opposed to GetAsync.
Also, do you want to make a GET request or a POST?
UPDATE 1 : Also check the response's status code like below
if(response.StatusCode == HttpStatusCode.OK){
// handle the response
ExpectedResponseModel responseModel = await response.Content.ReadAsAsync<ExpectedResponseModel >();
}
else {
// request failed, handle error
}
Here, ExpectedResponseModel could be made of the response you're expecting.

Object null in WebApi method after PostAsJsonAsync

I am posting an object to a WebApi method. I'm using PostAsJsonAsync to do this.
public async Task<HttpResponseMessage> PostAsync(string token, ServiceCall call)
{
var client = new HttpClient();
client.SetBearerToken(token);
var response = await client.PostAsJsonAsync(Uri + "id/nestedcall", call);
return response;
}
The object call that I'm passing is not null when I post it.
[HttpPost]
[Route("id/nestedcall")]
public async Task<IHttpActionResult> NestedCall([FromBody]ServiceCall call)
{
// call is null here
}
However it is null in my API method. I can't seem to work out why as all of the examples I've followed use this format.
Why isn't the call object being picked up by the web api?
Edit
Here is the ServiceCall object. It is in a separate class library and a reference is included in both the web application and the API.
public class ServiceCall
{
public ServiceCall(Service service, string grantType)
{
ClientId = service.Id;
ClientSecret = service.Secret;
Uri = service.Uri;
Scope = service.Scope;
GrantType = grantType;
}
public ServiceCall(string clientid, string clientsecret, string uri, string scope, string grantType)
{
ClientId = clientid;
ClientSecret = clientsecret;
Uri = uri;
Scope = scope;
GrantType = grantType;
}
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string Uri { get; set; }
public string Scope { get; set; }
public string GrantType { get; set; }
}
I have seen Object null in WebApi method after PostAsJsonAsync due to serialization.
Better to use PostAsync like below :
var obj = new MyClass()
{
MyProperty = 11
};
using (var client = new HttpClient())
{
string inputJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
HttpContent inputContent = new StringContent(inputJson, Encoding.UTF8, "application/json");
HttpResponseMessage response1 = client.PostAsync("http://localhost:60909/api/home/Test", inputContent).Result;
if (response1.IsSuccessStatusCode)
{
}
}
Using Prefix Stackify I was able to diagnose that the serialiser was throwing an exception:
Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Core.Models.ServiceCall. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'ClientId', line 1, position 12.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize
However, very helpfully, rather than tell me that an exception occurred the controller simply gave me a null object.
As hinted by the exception the solution is to add a default constructor (or at least one the serialiser can understand).
public ServiceCall()
{
}
looks like the JSON serialization may be failing. BTW, remove that [FromBody] and try without it like below. PostAsJsonAsync method serializes the ServiceCall object to JSON and then sends the JSON payload in a POST request.
public async Task<IHttpActionResult> NestedCall(ServiceCall call)
{
// your code
}
I run into exactly the same problem and had to do this to solve it:
using (var client = new HttpClient())
{
client.SetBearerToken(token);
var content = new StringContent(JsonConvert.SerializeObject(call), Encoding.UTF8, "application/json");
var response = await client.PostAsJsonAsync(Uri + "id/nestedcall", content);
return response;
}

Cant get the asp.net Web API token using http client

I am trying to use http Client to make a call to Web API to get the token.I have one MVC app and Web API app.below is the MVC controller action I have.
[HttpPost]
public ActionResult Login()
{
LoginModel m = new LoginModel();
m.grant_type = "password";
m.username = "xxx";
m.password = "xxx1234";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:51540/");
var response = client.PostAsJsonAsync("Token", m).Result;
response.EnsureSuccessStatusCode();
return View();
}
But when I make the request the API responds as BAD request. I tried to add the content type as "application/json" and have confirmed using fiddler that the request is of type json.
I am able to register the user using Web API so at WebAPI side things are looking fine to me,I am using default project created by VS2013 using Individual account and haven't modified any thing on API side.
I am following this tutorial http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api and trying to use HTTP Client instead of fiddler.
I will be thankful if someone helps me
TokenEndpointRequest seems doesn't support JSON yet, but you can use query string
var response = client.PostAsync("Token", new StringContent("grant_type=password&username=xxx&password=xxx1234", Encoding.UTF8)).Result;
Here's my code from the answer & comment above
using (var client = new HttpClient{ BaseAddress = new Uri(BaseAddress) })
{
var token = client.PostAsync("Token",
new FormUrlEncodedContent(new []
{
new KeyValuePair<string,string>("grant_type","password"),
new KeyValuePair<string,string>("username",user.UserName),
new KeyValuePair<string,string>("password","P#ssW#rd")
})).Result.Content.ReadAsAsync<AuthenticationToken>().Result;
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(token.token_type, token.access_token);
// actual requests from your api follow here . . .
}
created an AuthenticationToken class for beautification purposes:
public class AuthenticationToken
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
}

Categories