I am doing server to server communication and I am getting data back from my api. I using Http web client to do that. This is my code
public async Task<List<Report>> GetReports(string tokenType, string token, int page, int count)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, token);
var builder = new UriBuilder(ApiEndPointBase + "api/" + ApiVersion + "/LibraryDocument");
builder.Port = -1;
var query = HttpUtility.ParseQueryString(builder.Query);
query["page"] = page.ToString();
query["count"] = count.ToString();
builder.Query = query.ToString();
string url = builder.ToString();
var result = await client.GetAsync(url);
if (!result.IsSuccessStatusCode)
throw new Exception("");
List<Report> reports = new List<Report>();
await result.Content.ReadAsAsync<List<Report>>().ContinueWith(response =>
{
reports = response.Result;
});
return reports;
}
The issue I am having is that I am getting data from server in this format
public class Report
{
public int pK_LibraryDocument { get; set; }
public string fileName { get; set; }
public List<string> AvailableForModules { get; set; }
}
But I want data like this
public class Report
{
public int id{ get; set; }
public string fileName { get; set; }
public List<string> AvailableForModules { get; set; }
}
I would probably have other variable name changes as well. The reason for that is that I would have multiple data sources with same data but the format or name would be different. So I want to have a centralize naming for my self.
Is it possible in a not expensive (time consuming) way.
JSON.NET that is used by default for deserialization supports JsonProperty attribute for adjusting JSON field name:
public class Report
{
[JsonProperty("pK_LibraryDocument")]
public int id { get; set; }
public string fileName { get; set; }
public List<string> AvailableForModules { get; set; }
}
Related
I'm trying to get response a external API using httpclint in .netcore5.0.
Initially I got timeout exception. So I add client.Timeout = Timeout.InfiniteTimeSpan; after adding this response is come. but it takes more than 20 mins.
But I browser I can get API result within milliseconds.
How can I get response from API with a short time. Any idea to decrease this responding time?
startup.cs
services.AddHttpClient<IHolidayService, HolidayService>("PublicHolidaysApi", c => c.BaseAddress = new Uri("https://api.xmltime.com"));
service.cs
public class HolidayService : IHolidayService
{
private readonly IHttpClientFactory _clientFactory;
private readonly HttpClient _client;
public HolidayService(HttpClient client)
{
_client = client;
client.Timeout = Timeout.InfiniteTimeSpan;
}
public HolidayService(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
_client = clientFactory.CreateClient("PublicHolidaysApi");
}
public async Task<Holiday> GetHolidays(string country,int year)
{
string url = string.Format($"/holidays?accesskey="MyAccessKey"&secretkey="MySecretKey"&version=3&country=ro&year=2021&lang=en");
var result = new Holiday();
using (var cts = new CancellationTokenSource(Timeout.InfiniteTimeSpan))
{
var response = await _client.GetAsync(url, cts.Token).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
using var responseStream = await response.Content.ReadAsStreamAsync();
result = await JsonSerializer.DeserializeAsync<List<Holiday>>(responseStream);
}
else
{
throw new HttpRequestException(response.ReasonPhrase);
}
}
return result;
}
}
}
model
public class Holiday
{
[JsonPropertyName("urlid")]
public string UrliId { get; set; }
[JsonPropertyName("url")]
public string Url { get; set; }
[JsonPropertyName("country")]
public Country Country { get; set; }
[JsonPropertyName("name")]
public Name Name { get; set; }
[JsonPropertyName("oneliner")]
public OneLiner OneLiner { get; set; }
[JsonPropertyName("date")]
public Date Date { get; set; }
[JsonPropertyName("types")]
public List<string> Types { get; set; }
[JsonPropertyName("uid")]
public string UId { get; set; }
}
public class Country
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
}
public class Name
{
[JsonPropertyName("lang")]
public string Lang { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
public class OneLiner
{
[JsonPropertyName("lang")]
public string Lang { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
public class Date
{
[JsonPropertyName("iso")]
public string iso { get; set; }
[JsonPropertyName("datetime")]
public DateTime? Datetime { get; set; }
}
}
There are so many possibilities in this situation and I can only give you a way to solve the problem.
First of all, we need to locate the reason why it is so slow. Is it the server or the client?
We can use packet capture tools such as Fiddler ,and then observe the corresponding network requests.
If client had send but server not response , you should think about the api limit...
And if not, the request are not send at all, may be you should the check the connection pool of the HttpClient, or the WorkThreadPool of dotnet.
there are a few problems with your question.
it doesn't compile.
it is incomplete.
it has sensitive data.
but I can get the data from API in no time. just open this link https://dotnetfiddle.net/ryjakT and run the program.
I changed few things
Return Type, it should be List
var result = new Holiday(); to var result = new List();
I am using Newtonsoft.Json for Deserialization.
you were trying to Deserialize to an incorrect model, it should be Root.
I am using an asp.net api to query from my xamarin app to SQL Server. Below is how I am querying the API, and setting up the return type, but I am getting an error of
Can not convert List to List
What do I need to change in my code so that this will execute as desired?
public List<string> GetApprovalGrid()
{
string URI = "XXXXXXX/api/Xamarin/properties";
using (var webClient = new System.Net.WebClient())
{
var json = webClient.DownloadString(URI);
var message = JsonConvert.DeserializeObject<List<string>>(json);
return message;
}
}
public class ApproveUsers
{
public int ID { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public string phone { get; set; }
public string company { get; set; }
public string approveduser { get; set; }
}
private void LoadApproveUserGrid()
{
List<ApproveUsers> ApprovedUser = new List<ApproveUsers>();
//this line throws the error
ApprovedUser = dal.GetApprovalGrid();
//more code here
}
ApprovedUser is of type List<ApproveUsers> but GetApprovalGrid() returns List<string>
EDIT:
JsonConvert.DeserializeObject<List<ApproveUsers>>(json);
if your json is correctly formatted
EDIT2: you need to change the method signature to this too:
public List<ApproveUsers> GetApprovalGrid()
Via an http Post, I send html FormData to my Web Api2 controller.
The FormData contains one or more images, as well as client properties.
My front end Angular 5 service sends the http post (working fine):
var url = this.host + 'import/MediaUpload';
return this.http.post(url, formData, options)
.map((result: any) => result._body)
.catch(this.handleError);
I would like to convert the FormData to a generic List of MediaInfo class (defined below this MediaUpload() method) :
public async Task<HttpResponseMessage> MediaUpload(int projectId, int sectionId)
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = await Request.Content.ReadAsMultipartAsync<InMemoryMultipartFormDataStreamProvider>(new InMemoryMultipartFormDataStreamProvider());
//access form data
NameValueCollection formData = provider.FormData;
List<MediaInfo> listMedia = new List<MediaInfo>();
//dynamic jsonData = JObject.Parse(formData["MediaInfo"]); // THROWS ERROR
JArray ary = JArray.Parse(formData["MediaInfo"]);
foreach (var item in ary) {
//listMedia.Add((MediaInfo)item); // ???
Console.WriteLine(item);
}
//access files
IList<HttpContent> files = provider.Files;
HttpContent file1 = files[0];
var thisFileName = file1.Headers.ContentDisposition.FileName.Trim('\"');
// additional file upload code removed, working fine..
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("DocsUrl", URL);
return response;
}
public class MediaInfo
{
public string PatientID { get; set; }
public string PatientFirstName { get; set; }
public string PatientLastName { get; set; }
public string PatientUID { get; set; }
public string PatientDOB { get; set; }
public string ExamDate { get; set; }
public string ExamDevice { get; set; }
public string SerialNo { get; set; }
public string Eye { get; set; }
public int DeviceID { get; set; }
public int CSIInstanceID { get; set; }
public int MediaNo { get; set; }
public string Procedure { get; set; }
public string FileName { get; set; }
public int FileSize { get; set; }
}
I thought I could do something like :
listMedia.Add((MediaInfo)item;
But I'm missing the correct conversion somewhere.
You can convert a JObject to a type of your choosing with the .ToObject<T>() method.
https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JToken_ToObject__1_1.htm
In this case you want your code to look like this:
listMedia.Add(item.ToObject<MediaInfo>());
You could also use JsonConvert.DeserializeObject to convert it directly into the desired type provided formData["MediaInfo"] returned well formed JSON.
List<MediaInfo> listMedia = JsonConvert.DeserializeObject<List<MediaInfo>>(formData["MediaInfo"]);
I am able to handle simple JSON serialization and deserialization but this API response seems little complicated, and I am seeking an advice as to what would be ideal approach to tackle this.
I'm trying to call an API for MVC application.
Goal is to map API data to model.
API endpoint is
https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=MyAPIKey
Troubles here are:
JSON data keys have white space in them.
When I tried doing paste special in Visual studio, It gave me a long
list of classes for each date entry separately, because this API
call returns a separate set of information for date.
To solve problem explained in point 1, I used [JsonProperty("1. Information")] in class. And in my code..
public async Task TSI()
{
HttpClient client = new HttpClient();
//Uri uri = new Uri("http://date.jsontest.com/");
Uri uri = new Uri("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=5min&apikey=demo");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
dynamic result = await response.Content.ReadAsAsync<object>();
IEnumerable<dynamic> dObj = JsonConvert.DeserializeObject<dynamic>(result.ToString());
IEnumerable<dynamic> t1 = dObj.FirstOrDefault();
IEnumerable<dynamic> t2 = dObj.LastOrDefault();
dynamic MetaData = t1.FirstOrDefault();
Rootobject ro = new Rootobject();
ro.MetaData = MetaData;
}
PS: I'm relatively new to make API calls and handling them.
I was able to make a call to
date.jsontest.com
and map the API data to model (which I had created using paste special)
//API response
{
"time": "12:53:22 PM",
"milliseconds_since_epoch": 1504875202754,
"date": "09-08-2017"
}
//C# code to map to API data
public class sampleObject
{
public string time { get; set; }
public long milliseconds_since_epoch { get; set; }
public string date { get; set; }
}
My RootObject looks like this:
public class Rootobject
{
[JsonProperty("Meta Data")]
public MetaData MetaData { get; set; }
[JsonProperty("Time Series (1min)")]
public TimeSeries1Min TimeSeries1min { get; set; }
}
public class MetaData
{
[JsonProperty("1. Information")]
public string _1Information { get; set; }
[JsonProperty("2. Symbol")]
public string _2Symbol { get; set; }
[JsonProperty("3. Last Refreshed")]
public string _3LastRefreshed { get; set; }
[JsonProperty("4. Interval")]
public string _4Interval { get; set; }
[JsonProperty("5. Output Size")]
public string _5OutputSize { get; set; }
[JsonProperty("6. Time Zone")]
public string _6TimeZone { get; set; }
}
// I have so many of these sub-classes for dates, which again is an issue
public class TimeSeries1Min
{
public _20170907160000 _20170907160000 { get; set; }
public _20170907155900 _20170907155900 { get; set; }
....
....}
public class _20170907160000
{
public string _1open { get; set; }
public string _2high { get; set; }
public string _3low { get; set; }
public string _4close { get; set; }
public string _5volume { get; set; }
}
public class _20170907155900
{
public string _1open { get; set; }
public string _2high { get; set; }
public string _3low { get; set; }
public string _4close { get; set; }
public string _5volume { get; set; }
}
It is hard to create a model from this json, but you can convert those data to dictionary
var jObj = JObject.Parse(json);
var metadata = jObj["Meta Data"].ToObject<Dictionary<string, string>>();
var timeseries = jObj["Time Series (1min)"].ToObject<Dictionary<string, Dictionary<string, string>>>();
The following code should do what you want
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<Rootobject>(result);
//No idea what you want to do with this line as there is no MetaData property on the root object
obj.MetaData = MetaData;
}
In my Desktop application, I want to read the Wall posts,Messages, Like counts etc for a particular Facebook page (not for a facebook user)
I went through this post get user data(on stackoverflow). I want to achieve the same thing but for a FB page.
I am ready to create a facebook application to achieve this and have the user to give permission to pull the data.
Please advice on the above.
You need an access token to get page data from Facebook.
First get an access token using below URL with your facebook application's parameters:
https://graph.facebook.com/oauth/access_token?type=client_cred&client_id={yourappid}&client_secret={yourappscret}
Then you can call the Facebook Graph API with returning token
General: https://graph.facebook.com/wikipedia?access_token={token}
Posts: https://graph.facebook.com/wikipedia/posts?access_token={token}
An example code would be;
class Program
{
static void Main(string[] args)
{
var client = new WebClient();
string oauthUrl = string.Format("https://graph.facebook.com/oauth/access_token?type=client_cred&client_id={0}&client_secret={1}", "appid", "appsecret");
string accessToken = client.DownloadString(oauthUrl).Split('=')[1];
string pageInfo = client.DownloadString(string.Format("https://graph.facebook.com/wikipedia?access_token={0} ", accessToken));
string pagePosts = client.DownloadString(string.Format("https://graph.facebook.com/wikipedia/posts?access_token={0} ", accessToken));
}
}
After researching i have developed this code
class Posts
{
public string PostId { get; set; }
public string PostStory { get; set; }
public string PostMessage { get; set; }
public string PostPictureUri { get; set; }
public Image PostImage { get; set; }
public string UserId { get; set; }
public string UserName { get; set; }
}
private List<Posts> getFBPosts()
{
//Facebook.FacebookClient myfacebook = new Facebook.FacebookClient();
string AppId = "--------";
string AppSecret = "----------";
var client = new WebClient();
string oauthUrl = string.Format("https://graph.facebook.com/oauth/access_token?type=client_cred&client_id={0}&client_secret={1}", AppId, AppSecret);
string accessToken = client.DownloadString(oauthUrl).Split('=')[1];
FacebookClient myfbclient = new FacebookClient(accessToken);
string versio= myfbclient.Version;
var parameters = new Dictionary<string, object>();
parameters["fields"] = "id,message,picture";
string myPage="fanPage"; // put your page name
dynamic result = myfbclient.Get(myPage +"/posts", parameters);
List<Posts> postsList = new List<Posts>();
int mycount=result.data.Count;
for (int i = 0; i < result.data.Count; i++)
{
Posts posts = new Posts();
posts.PostId = result.data[i].id;
posts.PostPictureUri = result.data[i].picture;
posts.PostMessage= result.data[i].message;
var request = WebRequest.Create(posts.PostPictureUri);
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
posts.PostImage = Bitmap.FromStream(stream);
}
postsList.Add(posts);
}
return postsList;
}
You can also use a Nuget package called Facebook to fetch data from Facebook graph. Also, Json.NET helps you map the data directly into objects:
public class FacebookPageInfo
{
public long Id { get; set; }
public string Name { get; set; }
}
public class FacebookPost
{
public string Message { get; set; }
// ReSharper disable once InconsistentNaming
public string Created_Time { get; set; }
public string Id { get; set; }
}
public class FacebookPagingInfo
{
public string Previous { get; set; }
public string Next { get; set; }
}
public class FacebookPostData
{
public List<FacebookPost> Data { get; set; }
public FacebookPagingInfo Paging { get; set; }
}
public class Friend
{
public string Id { get; set; }
public string Name { get; set; }
}
// get access token
string oauthUrl = $"https://graph.facebook.com/oauth/access_token?type=client_cred&client_id={appId}&client_secret={appSecret}";
string accessToken = client.DownloadString(oauthUrl).Split('=')[1];
// get data and deserialize it
var fbClient = new FacebookClient(accessToken);
var fbData = fbClient.Get("/wikipedia/").ToString();
var info = JsonConvert.DeserializeObject<FacebookPageInfo>(fbData);
fbData = fbClient.Get("/wikipedia/posts").ToString();
var posts = JsonConvert.DeserializeObject<FacebookPostData>(fbData);