Post request to Minimal API service with JSON body - c#

I've got a minimal API service with a MapPost:
app.MapPost("/sendmessage", (RabbitMessage rm) => server.SendMessage(rm.exchange,
rm.routingkey, rm.message));
app.Run();
record RabbitMessage(string exchange, string routingkey, string message);
It works fine when sending a JSON with Postman:
{
"message": "msg",
"routingkey": "freestorage",
"exchange": "system"
}
But from a C# client:
var kv = new Dictionary<string, string> {
{ "exchange", "system" },
{ "routingkey", routingkey },
{ "message", message }
};
var content = new FormUrlEncodedContent(kv);
string contentType = "application/json";
if (Client.DefaultRequestHeaders.Accept.FirstOrDefault(hdr => hdr.MediaType == contentType) == default)
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
var response = await Client.PostAsync("sendmessage", content);
The response is UnsupportedMediaType. What is the proper way to send these values to minimal API? Or do I need to setup the API itself differently?

I don't think using FormUrlEncodedContent is the correct way as it is used for application/x-www-form-urlencoded MIME type.
Instead, you should pass the request body with StringContent and serialize the kv as content.
using System.Text;
using Newtonsoft.Json;
var stringContent = new StringContent(JsonConvert.SerializeObject(kv),
Encoding.UTF8,
"application/json");
var response = await Client.PostAsync("sendmessage", stringContent);

Related

Get Access token form OneLogin using the PKCE .net core API

I'm Trying to get the access token form OneLogin using the Authorization Code with PKCE. I'm able to go through step1 for PKCe and getting the authorization code back from OneLogin. But when i try to get the token using the authorization code sent by one login i keep getting 400 bad request error. I'm not sure what is wrong. I followed the info provided by oneLogin website to all required parameters in the request for Step 2. below the code i'm using. I will appreciate if some one can help on this.
public async Task GetAccessToken(string redirecturl, string authCode)
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
var client = new HttpClient(clientHandler);
var body = JsonConvert.SerializeObject(new
{
grant_type = "authorization_code",
code = authCode, ---The code returned from OneLogin in step 1
client_id=XXXXXXXXXXXXXXXXXX386d707215718",
redirect_uri=redirecturl,--The redirect URL registered in onelogin account
code_verifier=GetCacheEntry(CodeKey)-- the code verifier used in step one
});
var req = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://MySubdomain.onelogin.com/oidc/2/token"),
Content = new StringContent(body)
};
req.Content.Headers.ContentType= new MediaTypeHeaderValue(#"application/x-www-form-urlencoded");
var response = await client.SendAsync(req);
if (response.StatusCode == HttpStatusCode.OK)
{
var responseBody =await response.Content.ReadAsStringAsync();
var json = JsonConvert.DeserializeObject<OAuthTokenResponse>(responseBody);
memoryCache.Remove(CodeKey);
return Ok(json);
}
return BadRequest(response);
}
Looks like you're sending the body as a json content, although you've correctly specified the Content Type as x-www-form-urlencoded.
Here's how I create the body and send the request
var data = new Dictionary<string, string>(){
{ "code", code },
{ "code_verifier", AuthCodeParticipantDetail.CodeVerifier},
{ "grant_type", "authorization_code" },
{ "redirect_uri", AuthCodeParticipantDetail.CallBackUrl},
{"client_id", AuthCodeParticipantDetail.ClientId}
};
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
HttpResponseMessage response = await _httpClient.PostAsync(url, new FormUrlEncodedContent(data));
var tokens = await response.Content.ReadFromJsonAsync<Tokens>();

Add a member to Microsoft Teams using Graph API and delegated permissions

I am trying to simply add a member (who is already in the organization) to a specific Microsoft Team. The observerID is the id of the the member that I want to add and teamID is is the ID of the specific Team. I am using delegated permission with TeamMembers.ReadWrite.All enabled.
My code looks like this:
string json = $#"
{{
""#odata.type"": ""#microsoft.graph.aadUserConversationMember"",
""roles"": [""member""],
""user#odata.bind"": ""https://graph.microsoft.com/beta/users({observerID})""
}}";
var body = new StringContent(json, Encoding.UTF8, "application/json");
Console.WriteLine("Add observer");
return await protectedApiCallHelper.CallWebApiAsync(WebApiUrlTeams + teamID + "/members", accessToken, body);
public async Task<JObject> CallWebApiAsync(string webApiUrl, string accessToken, HttpContent content)
{
if (!string.IsNullOrEmpty(accessToken))
{
var defaultRequestHeaders = HttpClient.DefaultRequestHeaders;
if (defaultRequestHeaders.Accept == null || !defaultRequestHeaders.Accept.Any(m => m.MediaType == "application/json"))
{
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
defaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
HttpResponseMessage response = await HttpClient.PostAsync(webApiUrl, content);
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
JObject result = JsonConvert.DeserializeObject(json) as JObject;
return result;
}
}
return null;
}
My problem is that the http call fails with the status code 400; 'Bad Request'. I have tried again and again to find any issues with my call but I can't seem to find the problem. When I Console.WriteLine the json I use for the body it looks like this:
{
"odata.type": "#microsoft.graph.aadUserConversationMember",
"roles": ["member"],
"user#odata.bind": "https://graph.microsoft.com/beta/users(d52c2663-1c41-401b-8015-1216f0e68960)"
}
And the url looks like: "https://graph.microsoft.com/beta/teams/a9f9ac33-fba5-4ce2-9515-8c498c70af85/members" and when I try the call through Postman it still returns a error code 400.
Does anyone have any insight on what might be wrong?
In fact, this error is very simple. Reporting 400 is usually a parameter error. Your json file is missing the special symbols # and ". I tested it locally and worked for me.

Custom header in HttpClient POST request not working

I am trying to send a POST request when using HttpClient. When I run the code I am getting an unauthorized response. But I am able to get it to work in PostMan. Below is my current code snippet and pictures of what I am trying to perform. I'd like to add I am trying to send a json string in my body.
using (HttpClient client = new HttpClient())
{
var connectionUrl = "https://api.accusoft.com/prizmdoc/ViewingSession";
var content = new Dictionary<string, string> { { "type", "upload" }, { "displayName", "testdoc" } };
// Serialize our concrete class into a JSON String
var stringPayload = JsonConvert.SerializeObject(content);
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
using (var httpClient = new HttpClient())
{
//client.DefaultRequestHeaders.Add("Acs-Api-Key", "aPsmKCmvkZHf9VakCmfHB8COmzRxXY5FDhj8F1FU1IGmQlOkfjiKESKxfm38lhey");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Acs-Api-Key", "aPsmKCmvkZHf9VakCmfHB8COmzRxXY5FDhj8F1FU1IGmQlOkfjiKESKxfm38lhey");
// Do the actual request and await the response
var httpResponse = httpClient.PostAsync(connectionUrl, httpContent).Result;
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
// Do something with response. Example get content:
var connectionContent = httpResponse.Content.ReadAsStringAsync().Result;
}
else
{
// Handle a bad response
return;
}
}
}
You're using two HttpClients when you only need to use one.
using (HttpClient client = new HttpClient())
and
using (var httpClient = new HttpClient())
The second one (httpClient) is doing the post but the authentication header has been added to client. Just remove the second one (httpClient) and make sure you use client.PostAsync(...) to send the request.
I'd also consider using await, rather than .Result (see why here) when sending the request:
var httpResponse = await client.PostAsync(connectionUrl, httpContent);
In addition to haldo's answer,
In your code, you are adding your Acs-Api-Key header as and Authorization header, meaning it ends up looking like Authorization: Acs-Api-Key (key) rather than Acs-Api-Key: (key) which is what you have in PostMan.
Instead of adding it as an Authorization header, just add it as a regular header.
client.DefaultRequestHeaders.Add("Acs-Api-Key","(key)");
Also something else that may cause issues is that you aren't wrapping your content in the "source" object like you are in PostMan. There are a couple ways of doing this
The first would be to simply wrap it in it's string format:
stringPayload = $"\"source\":{{{stringPayload}}}"
Or you can do it before you serialize by making your own object instead of having a Dictionary
var content = new PayloadObject(new Source("upload", "testdoc"));
var stringPayload = JsonConvert.SerializeObject(content);
// Send the request
class PayloadObject{
Source source {get; set;}
PayloadObject(Source source){
this.source = source;
}
}
class Source{
string type {get; set;}
string displayName {get; set;}
Source(string type, string displayName){
this.type = type;
this.displayName = displayName;
}
}

How to consume a webApi from asp.net Web API to store result in json file

How to consume RestApi using c# and to store the content of responses in json file? i.e When I run the program, it should call API and automatically it should store the json content in json file.
How can it be possible using Asp.Net?
You should use HTTP POST
using System.Net.Https; // Add this library
using (var client = new HttpClient())
{
var values = "DataToSend";
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://sit.com/sample.aspx", content);
var responseString = await response.Content.ReadAsStringAsync(); //JSON
}
You can call any rest api using httpclient(Microsoft.AspNet.WebApi.Client)
Following method returns a json string async which you can save later
static async Taskstring> GetContentAsync(string path)
{
using (var httpClient = new HttpClient())
return await httpClient.GetStringAsync(address);
}
to get json content synchronously
using (var client = new HttpClient())
{
var response = client.GetAsync("http://example.com").Result;
if (response.IsSuccessStatusCode)
{
string responseString = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseString);//you can save the responseString here
}
}
or use open source library like RestSharp
var client = new RestClient("http://example.com");
// execute the request
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
More examples can be found https://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client or using restsharp

C# HttpClient PostAsync with JSON parameter for VSO git API

I am trying to understand the VSO git API. I have made Get requests succesfully like so:
using (var response = client.GetAsync(
uri).Result)
{
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
ResponseInfo.Text = JsonHelper.FormatJson(responseBody);
}
I do this after setting client.DefaultRequestHeaders for Basic Authentication and Mediatype to application/json.
For post requests, the VSO Documentation shows this:
I understand that the parameters are JSON. However, I'm not sure how to pass that into the post request in C#. I have tried the following:
string content = #"{
""refUpdates"": [
{
""name"": ""refs/heads/master"",
""oldObjectId"": ""*old object id*""
}
],
""commits"": [
{
""comment"": ""Test commit"",
""changes"": [
{
""changeType"": ""edit"",
""item"": {
""path"": ""/foo.txt""
},
""newContent"": {
""content"": ""test"",
""contentType"": ""rawtext""
}
}
]
}
]
}";
var stringToJson= new JavaScriptSerializer();
var JSONoutput = stringToJson.Deserialize<object>(content);
StringContent stringContent = new StringContent(JSONoutput.ToString(), Encoding.UTF8, "application/json");
and then I pass that in to
using (var response = client.PostAsync(uri, stringContent).Result)
{
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
I get a 400 Bad Request error. Am I passing in my parameters correctly? Essentially I am taking the string version of what the tutorial gave me, convert it to JSON, deserialize it, convert it to HTTPContent, and pass that into PostAsync. I can't think of another way to do it.
Thank you for your time!
Turns out I can just do
StringContent stringContent = new StringContent(content, Encoding.UTF8, "application/json");
The string version of the JSON object is enough for StringContent.

Categories

Resources