I am calling a api and getting list of ids in json format in restsharp api response. But problem i am unable to write the syntax for List in restsharp Execute method. Please check the code bellow. And correct my List<> Syntax.
var client2 = new RestClient(apiEndPoint);
var request2 = new RestRequest(Method.GET);
var Result2 = client.Execute<List><PageIds>(request);
My id model:
class PageIds
{
public int Id { get; set; }
}
Hay i think this is your answer-
var Result2 = client.Execute<List<PageIds>>(request);
However until we see your json response cant sure this will work or not. But at-least it is the correct syntax for List on this particular situation.
Related
I'm trying to make a GET request to a REST api which returns a JSON. This is what I have right now:
RestClient client = new RestClient(BASE_URL);
var request = new RestRequest(CONTROLLER_PATH);
var response = await client.GetAsync<MyDtoClass[]>(request);
When this code executes, response is an array of MyDtoClass but the fields in each element of the array are null. If instead, I run this code (I removed the generic):
RestClient client = new RestClient(BASE_URL);
var request = new RestRequest(CONTROLLER_PATH);
var response = await client.GetAsync(request);
then response is a string represintation of the JSON that BASE_URL + CONTROLLER_PATH returns (nothing is null).
What is the idiomatic way to make a request to this REST api and convert the response into an array of MyDtoClass. Also, if anyone has suggestions for a library you think is better then RestSharp, please share.
Thank you in advance.
The issue was that MyDtoClass had fields instead of properties.
I'm building a class library that connects to a client's API, and collects the response from a given endpoint into a class. In other words, I'll hit the client's Donuts endpoint, and using JsonConvert to deserialize the response into my Donuts class, which has fields that match the attributes in the JSON object. This is all well and good, but they have a lot of endpoints, and I have many methods which repeat the same code over and over. In the interests of DRYness and separation of concerns, I'd like to have a separate namespace that makes the rest call, no matter the endpoint, and returns the correct result to the main class. Here's an example of what it does now (I'm using RestSharp to configure the request and response):
public List<T> Index<T>(string Endpoint)
{
List<T> Results = new List<T>();
RestClient Client = new RestClient();
RestRequest Req = ConfigureGetRequest(Endpoint);
IRestResponse Resp = Client.Execute(Req);
if (Resp.StatusCode == System.Net.HttpStatusCode.OK)
{
Results = JsonConvert.DeserializeObject<List<T>>(Resp.Content, DeserializationSettings);
}
return Results;
}
}
There's other code in the if statement (it's actually an if-else for error handling), but it's not really relevant to this question. I have this same code in multiple methods, with the only difference being that it returns List<Bagel>, or List<Cruller>, etc... What I'd like to do is extract this code into it's own method, but I'm not sure how. Right now, I'm trying to deserialize into List<object>, and then convert it to List<Donut> later, but that doesn't seem to be something I can do. My other thought is to pass in the endpoint name as a parameter (public List<Donut> GetDonuts(string Endpoint)), and then somehow use that to determine what type of object to deserialize into, if that makes sense? Anyhoo, if anyone has any insight on a good way to do this, it would be appreciated!
EDIT
Awesome responses, thank you folks. I've refactored the method according to Matt Dillard's answer below. The next step is to convert the List to List. The method that calls the method above looks like this:
public List<Donut> GetDonuts()
{
List<Donut> Results = new List<Donut>();
MODULE MakeCall = new GET();
return Results = MakeCall.Index("donuts")();
}
My Intellisense tells me that "The type arguments for method 'MODULE.Index(string)' cannot be inferred from the usage. Try specifying the type arguments explicitly". I tried casting like so: (List)MakeCall.Index("donuts")();
but that didn't work out. Is there a way to cast this so that I can have methods GetDonuts, GetCrullers, etc... that all call Index effectively?
Generics:
public List<T> GetStuff<T>(string endpoint)
{
List<T> Results = new List<T>();
RestClient Client = new RestClient();
RestRequest Req = ConfigureGetRequest(endpoint);
IRestResponse Resp = Client.Execute(Req);
if (Resp.StatusCode == System.Net.HttpStatusCode.OK)
{
Results = JsonConvert.DeserializeObject<List<T>>(Resp.Content, DeserializationSettings);
}
return Results;
}
}
Bascially replace all references to Donut with T.
Presumably the endpoint address would change, so you can add that as a parameter.
Call something like this:
var donuts = GetStuff<Donut>("http://dunkin.com/api/allthedonuts");
You probably would like to have it as generic method which accepts a type T and return a list of such like
public List<T> GetDonuts<T>() where T : class, new()
{
I figured out what needed to happen. I can't deserialize a generic list, but I can deserialize a generic, and place it in a list. The final code looks like this:
public List<Donut> GetDonuts<T>()
{
GET MakeCall = new GET();
List<Donut> Results = new List<Donut>();
Results = MakeCall.Index<Donut>();
return Results;
}
public List<T> Index<T>()
{
T Result;
List<T> ResultList = new List<T>();
RestClient Client = new RestClient();
RestRequest Req = ConfigureGetRequest(Endpoint);
IRestResponse Resp = Client.Execute(Req);
if (Resp.StatusCode == System.Net.HttpStatusCode.OK)
{
Result = JsonConvert.DeserializeObject<T>(Resp.Content, DeserializationSettings);
ResultList.Add(Result);
}
return ResultList;
}
This allows me to use GetDonuts, GetCrullers, etc... to be lean and DRY. Thanks for all the help!
I'm trying to deserialise a response from a REST service into C# Strongly typed classes - however I've ran into the same issue has in this post:
How do I output this JSON value where the key starts with a number?
However I have the issue that you cannot start a variable name in c# with a number - meaning that the class at that level just deserialises into null.
I need to know how to get into the objects and deserialise them into the c# classes.
My Current code is below:
public static async Task<T> MakeAPIGetRequest<T>(string uri)
{
Uri requestURI = new Uri(uri);
using (HttpClient client = new HttpClient())
{
HttpResponseMessage responseGet = await client.GetAsync(requestURI);
if (responseGet.StatusCode != HttpStatusCode.OK)
{
throw new Exception(String.Format(
"Server error (HTTP {0}: {1}).",
responseGet.StatusCode,
responseGet.Content));
}
else
{
string response = await responseGet.Content.ReadAsStringAsync();
T objects = (JsonConvert.DeserializeObject<T>(response));
return objects;
}
}
}
EDIT: I cannot change the way the service is pushing the data back
The correct way to deal with this was to use the JsonProperty tag on the target classes to define what Json property to listen for, as shown below (referenced from https://stackoverflow.com/questions/24218536/deserialize-json-that-has-some-property-name-starting-with-a-number
public class MyClass
{
[JsonProperty(PropertyName = "24hhigh")]
public string Highest { get; set; }
...
Thanks to #HebeleHododo for the comment answer
While there is no direct way to construct a strongly typed C# object in this case, You could still have the capabilities to parse the json string manually and extract values -
var json = "{'1':{'name':'test','age':'test'}}";
var t = JObject.Parse(json)["1"];
Console.WriteLine(t["name"]); //test
Console.WriteLine(t["age"]); //test
I am making of System.Net.Http.HttpClient class to call an end point. This endpoint is expect certain input and returns a List of user defined object of type Employee ( List<Employee>).
This is the code that I am using.
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:7792/");
client.DefaultRequestHeaders.Accept.Clear();
FilterModel payload = new FilterModel();
payload.employeeId= 97050001;
payload.Level= "Manager";
// New code:
HttpResponseMessage response = client.PostAsJsonAsync("api/employee", payload).Result;
if (response.IsSuccessStatusCode)
{
var employee= response.Content.ReadAsStringAsync();
//HOW DO I CONVERT THE OUTPUT INTO LIST<EMPLOYEE>?
Console.Write("---DONE---");
}
Console.ReadKey();
}
I know this is not the ideal way to call an end point & I must use asyc await. I just need the data, the call can be sync or async & I want to type cast the result into List.
Currently I get a string back which I need to deserialize. Please help
You can use JsonConvert as below:
var jsonString= response.Content.ReadAsStringAsync();
var employees = JsonConvert.DeserializeObject<List<Employee>>(jsonString);
Hope this help!
UPDATE 2020:
Use some thing like this:
return await response.Content.ReadFromJsonAsync<List<Employee>>();
I have started using RestSharp to call an webapi proejct as it seems pretty easy to use.
I am wanting to build a helper class for all of my crud actions.
I have this so far for a simple PUT request.
public static IRestResponse Update(object objectToUpdate,string apiEndPoint)
{
var client = new RestClient(CreateBaseUrl(null))
{
Authenticator = new HttpBasicAuthenticator("user", "Password1")
};
var request = new RestRequest(apiEndPoint, Method.PUT);
request.AddObject(objectToUpdate);
var response = client.Execute<MyViewModel>(request);
//var response = client.ExecuteDynamic(request);
return response;
}
So the above code works however I have had to hardcode my viewmodel into it
var response = client.Execute<MyViewModel>(request);
How can I change this so I dont need to know the type of model I am expecting?
I tried using var response = client.ExecuteDynamic(request);
however this throws an exception of
Unable to cast object of type 'RestSharp.RestResponse' to type 'RestSharp.RestResponse`1[System.Object
Im not sure how I am meant to cast my object correctly
I'm not familiar with RestSharp. However, it sounds like generics could help you here. Either your class or method needs to accept a type. For example, the signature of your method would change to
public static IRestResponse Update<T>(object objectToUpdate,string apiEndPoint)
This would allow you to call the method as:
Update<MyViewModel>(objectToUpdate, apiEndPoint);
Your implementation would change from your concrete type to:
var response = client.Execute<T>(request);
Overall you could modify your code to something like this:
public static IRestResponse Update<T>(object objectToUpdate,string apiEndPoint)
{
var client = new RestClient(CreateBaseUrl(null))
{
Authenticator = new HttpBasicAuthenticator("user", "Password1")
};
var request = new RestRequest(apiEndPoint, Method.PUT);
request.AddObject(objectToUpdate);
var response = client.Execute<T>(request);
//var response = client.ExecuteDynamic(request);
return response;
}
Documentation on C# Generics can be found here: http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx