I have looked at some forum posts and found no solution to my problem, so now I ask you for help. First i show you what the result of my HttpGet is and then i show you the not working deserialization.
Working example: I use the same code for an HttpGet to get a json result.
[HttpGet]
[Route("~/get_new_authtoken")]
public async Task<IActionResult> GetNewAuthTokenAsync()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://testApi/WebService/");
string APIConnection = _configuration.GetValue<string>("APIConnection");
HttpResponseMessage response = client.PostAsync("authtoken", new StringContent(string.Format(APIConnection))).Result;
if (response.IsSuccessStatusCode)
{
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
}
catch (Exception ex)
{
SentrySdk.CaptureException(ex);
return Ok(ex.Message);
}
}
with following result when i call it via Postman
Not working deserialization: I store the token in a database and want to update it when it expires.
Object i want to desiralize in:
public class AuthToken
{
[JsonPropertyName("access_token")] public string AccessToken { get; set; }
[JsonPropertyName("refresh_token")] public string RefreshToken { get; set; }
[JsonPropertyName("token_type")] public string TokenType { get; set; }
[JsonPropertyName("expires_in")] public int ExpiresIn { get; set; }
}
when i add the following code to the httpget above to test the deserializationthe object Authtoken is always null.
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
Like this->
if (response.IsSuccessStatusCode)
{
//To test
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
//To test
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
Updated the testint to following code:
AuthToken newAccessToken = new AuthToken();
var responseString = await response.Content.ReadAsStringAsync();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(responseString);
result of the responseString:
JsonPropertyNameAttribute is from System.Text.Json while JsonConvert.DeserializeObject is part of Newtonsoft.Json either switch to former completely by using System.Text.Json.JsonSerializer.Deserialize:
AuthToken newAccessToken = JsonSerializer.Deserialize<AuthToken>(...);
// or just use ReadFromJsonAsync instead of ReadAsStringAsync
Or use attributes for latter:
public class AuthToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
// ...
}
Related
I created a web API application for public holidays.
Here is the class Pho
public class Pho
{
public DateTime date { get; set; }
public string localName { get; set; }
public string countryCode { get; set; }
}
Here the code I tried to call the API
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://date.nager.at/api/v3/PublicHolidays/2017/FR");
using (HttpResponseMessage response = await client.GetAsync(""))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
return Ok(responseContent);
}
}
It didn't work and I didn't know how to fix it
try to fix uri
client.BaseAddress = new Uri("https://date.nager.at");
using (HttpResponseMessage response = await client.GetAsync("/api/v3/PublicHolidays/2017/FR"))
{
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
return Ok(responseContent);
}
return BadRequest("status code "+response.StatusCode.ToString());
}
One of the possible reasons your code is not working is because you're trying to set BaseAddress when the client hasn't been initialized yet.
To add BaseAddress at the time of intializing HttpClient you should do it this way:
var client = new HttpClient
{
BaseAddress = new Uri("https://date.nager.at/api/v3/PublicHolidays/2017/FR")
};
using (HttpResponseMessage response = await client.GetAsync(client.BaseAddress))
{
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
return Ok(responseContent);
}
so, I get the Access Token and I want to create a request...
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", accesToken);
HttpResponseMessage response = await httpClient.GetAsync("https://graph.microsoft.com/v1.0/users");
Also, the Problem may be on setting the scopes for the authentication...i set it to:
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
But I don't know if it gets all application permissions that I have (it is a deamon).
You can use this sample which will help you to create events with same client credential flow which you are using but you need to change some things here.
You need to first give the Calendar.ReadWrite permission in the Azure portal for your app.
You need to add the below code in the Program.cs
if (result != null)
{
var httpClient = new HttpClient();
var apiCaller = new ProtectedApiCallHelper(httpClient);
await apiCaller.CallWebAPIToPostEvent($"{config.ApiUrl}v1.0/users/{user obj id}/calendars/{calendar id}/events", result.AccessToken, Display);
}
Then you need to add the below classes in the protectedApiCallHelper.cs
public class Event
{
[JsonProperty("subject")]
public string Subject { get; set; }
[JsonProperty("body")]
public Body Body;
[JsonProperty("start")]
public TimeAndDate Start;
[JsonProperty("end")]
public TimeAndDate End;
[JsonProperty("location")]
public Location Location;
[JsonProperty("attendees")]
public List<Attendees> Attendees;
}
public class Body
{
[JsonProperty("contentType")]
public string ContentType { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
}
public class TimeAndDate
{
[JsonProperty("dateTime")]
public string DateTime { get; set; }
[JsonProperty("timeZone")]
public string TimeZone { get; set; }
}
public class Location
{
[JsonProperty("displayName")]
public string DisplayName { get; set; }
}
public class Attendees
{
[JsonProperty("emailAddress")]
public EmailAddress EmailAddress;
[JsonProperty("type")]
public string Type;
}
public class EmailAddress
{
[JsonProperty("address")]
public string Address { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
In this same ProtectedApiCallHelper class you can create a post request and get the details by adding the below code
public async Task CallWebAPIToPostEvent(string webApiUrl, string accessToken, Action<JObject> processResult)
{
var defaultRequetHeaders = HttpClient.DefaultRequestHeaders;
if (defaultRequetHeaders.Accept == null || !defaultRequetHeaders.Accept.Any(m => m.MediaType == "application/json"))
{
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
defaultRequetHeaders.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
var payload = new Event
{
Subject = "Let's go for lunch",
Body = new Body
{
ContentType = "HTML",
Content = "Does mid month work for you?"
},
Start = new TimeAndDate
{
DateTime = "2019-03-15T12:00:00",
TimeZone = "Pacific Standard Time"
},
End = new TimeAndDate
{
DateTime = "2019-03-15T14:00:00",
TimeZone = "Pacific Standard Time"
},
Location = new Location
{
DisplayName = "Harry's Bar"
},
Attendees = new List<Attendees>
{
new Attendees
{
EmailAddress = new EmailAddress
{
Address = "Shiva#nishantsingh.live",
Name = "Shiva"
},
Type = "required"
}
}
};
// Serialize our concrete class into a JSON String
var stringPayload = await Task.Run(() => JsonConvert.SerializeObject(payload));
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(stringPayload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await HttpClient.PostAsync(webApiUrl, httpContent);
if (response.Content != null)
{
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
}
This will help you create the event with these details.
I developing a xamarin application using singleton based to get the server values. Searched the example by StackOverflow in this site(Show List in Xamarin consuming REST API). but I have small doubts about this. no one reply to my comment to this question.
My Code:
public async Task<Response> GetList<T>(string urlBase, string servicePrefix, string controller)
{
try
{
var client = new HttpClient();
client.BaseAddress = new Uri(urlBase);
var url = string.Format("{0}{1}", servicePrefix, controller);
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
return new Response
{
IsSuccess = false,
Message = result,
};
}
var list = JsonConvert.DeserializeObject<List<T>>(result);
return new Response
{
IsSuccess = true,
Message = "Ok",
Result = list,
};
}
catch (Exception ex)
{
return new Response
{
IsSuccess = false,
Message = ex.Message,
};
}
}
My doubt what is Response in this code. It is a separate class or HTTP response message. but I changed the HTTP response message, it gives an error in the above-declared variables(Success, Message).
Response is a Custom class like following code,.It contails three properties.
public class Response
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public object Result { get; set; }
}
I have a web API application. I'm supposed to do a post to an endpoint. When l tried my API controller in postman, l get the error message "
Requested resource does not support HTTP 'POST'
I'm new to Web API so any help and suggestions are welcomed.
This is my model class:
namespace Products.Models
{
public class Prouct
{
public string ProductID { get; set; }
public string ProductName { get; set; }
public string ProductPrice { get; set; }
public string VoucherID { get; set; }
}
}
Here is my controller class
[RoutePrefix("api/products")]
public class ProductsController : ApiController
{
static HttpClient client = new HttpClient();
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
public string Get(int id)
{
return "value";
}
[Route("products")]
public async Task PostAsync(string ProductID, string ProductName, string ProductPrice,
string VoucherID)
{
Products p = new Products();
p.ProductID = ProductID;
p.ProductName = ProductName;
p.ProductPrice = ProductPrice;
p.VoucherID = VoucherID;
var client = new HttpClient { BaseAddress = new
Uri("http://localhost:51613/") };
var response = await
client.PostAsJsonAsync("api/products",
p);
if (response.IsSuccessStatusCode)
{
}
public void Put(int id, [FromBody]string value)
{
}
public void Delete(int id)
{
}
You need to specify HttpPost on PostAsync method. by default, it is [HttpGet].
[HttpPost]
[Route("products")]
public async Task PostAsync(string ProductID, string ProductName, string ProductPrice, string VoucherID)
{
// implementation
}
Looks like you're stuck in a loop. Why does the PostAsync method call itself after having been invoked? This will result in an endless request loop.
var client = new HttpClient { BaseAddress = new Uri("http://localhost:51613/") };
This is not related to the fact that the [HttpPost] attribute is required however.
Please observe that you are supposed to use [FromBody] . Also inside Postman (image attached) you have to choose "Raw" data with the product json with type as JSON(application.json).
[HttpPost]
[Route("products")]
public async Task PostAsync([FromBody] Products p)
{
var client = new HttpClient
{
BaseAddress = new
Uri("http://localhost:51613/")
};
var response = await
client.PostAsJsonAsync("api/products",
p);
if (response.IsSuccessStatusCode)
{
}
}
I have an external api that is hosted on a different domain for now we can use the following url as an example
https://myapi.mydomain/api/data
This API returns the following data
{"data":[
{
"id":1,
"company":"JUST A DEMO",
"ext_identifier":"DEMO1"
},
{
"id":2,
"company":"ANOTHER DEMO",
"ext_identifier":"DEMO2"
}
]}
I need to call a controller method that does the GET request against this API and then returns the JSON data for me to consume.
So far I have the following code, I think I am close....
Here is the controller code
string url = "https://myapi.mydomain/";
[HttpGet]
public async Task<ActionResult> Search()
{
CustomerList customers = null;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// New code:
HttpResponseMessage response = await client.GetAsync("api/data");
if (response.IsSuccessStatusCode)
{
customers = await response.Content.ReadAsAsync<CustomerList>();
}
}
return Json(new
{
data = customers
},
JsonRequestBehavior.AllowGet);
}
public class CustomerList
{
public int id { get; set; }
public string company { get; set; }
public string ext_identifier { get; set; }
}
Why is it that when I ask a question 10 minutes later I come up with the answer so here it is if anyone is interested.
This seems to be the most elegant solution I can come up with but if anyone has any improvements please let me know thanks.
[HttpGet]
public async Task<ActionResult> GetCustomers()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(customerApi);
if (response.IsSuccessStatusCode)
{
string jsondata = await response.Content.ReadAsStringAsync();
return Content(jsondata, "application/json");
}
return Json(1, JsonRequestBehavior.AllowGet);
}
}