passing using the same uri paramater, getting two different outcomes - c#

I am trying to get a list of 100 help desk tickets from an API. the url is below.
https://sdpondemand.manageengine.com/app/itdesk/api/v3/requests?input_data={"list_Info":{"row_count":100,"start_index":101}}
I am able to produce successful results, meaning it brings back 100 rows starting at index 101, when I put the uri into a string like this:
string extra = "app/itdesk/api/v3/requests?input_data={\"list_info\":{\"row_count\":100,\"start_index\":101}}";
but if I try to put the json into classes, then serialize it with the Json.Net library, it will fail, meaning it brings back just 10 rows on index 1.
private class input_data
{
public list_info list_Info = new list_info();
}
private class list_info
{
public int row_count = 100;
public int start_index = 101;
}
input_data input = new input_data();
string json = Newtonsoft.Json.JsonConvert.SerializeObject(input);
string extra1 ="app/itdesk/api/v3/requests?input_data="+json;
I look at both of the request coming out an there exactly the same. what am I doing wrong?
what the vars look like in the code
extra: app/itdesk/api/v3/requests?input_data={"list_info":{"row_count":100,"start_index":101}}
extra1: app/itdesk/api/v3/requests?input_data={"list_Info":{"row_count":100,"start_index":101}}

Passing serialized DTO object in the Get request is not the proper way of implementing an API. Get request supposed to be having params rather than a serialize object. If you wish to do so and have to send an object then why not using a post request.
The sample implementation for a rest api could be as:
Via GET
[Route("{rowCount}/{startIndex}"), HttpGet]
public IHttpActionResult Get(int rowCount, int startIndex)
{
//Your logic Implementation
}
calling would be like
www.xyz.com/controllerName/100/101
This is the rest implementation of the request
Via POST
[Route(""), HttpPost]
public IHttpActionResult Post([FromBody]YourDTOClass obj)
{
//Your logic Implementation
}
For example you have the DTO class
//In C# the class name should be capital
private class ListInfo
{
//In c# the property name should be Capital
public int RowCount {get; set;} = 100;
public int StartIndex {get; set;}= 101;
}
So your Post method would look like
//Route attribute is for configuring the custom route
//It is a feature in MVC 5
//FromBody attribute will search for data in the request body
[Route(""), HttpPost]
public IHttpActionResult Post([FromBody]ListInfo info)
{
//Your logic Implementation
}
If you are using the C# for calling the API too, then you could use HttpClient where passing the json object of your class a data.
Edited: As you are using a third party API, therefore you need to correct the calling.
using (var client = new HttpClient())
{
//Setting the base address of the server
client.BaseAddress = new Uri("https://sdpondemand.manageengine.com");
//creating an anonymous object
var jsonObject = new {
input_data = new {
row_count = 100,
start_index = 101
}
};
//Converting into the content string
var content = new StringContent(JsonConvert.SerializeObject(jsonObject), Encoding.UTF8, "application/json");
//waiting for the post request to complete
var result = await client.PostAsync("app/itdesk/api/v3/requests", content);
//reading the response string
string resultContent = await result.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
//Deserialize your string into custom object here
var obj = JsonConvert.DeserializeObject<YourDTO>(resultContent);
}
else
{
//Todo: Log the Exception here
throw new Exception(contentString);
}
}

extra : app/itdesk/api/v3/requests?input_data={"list_info"{"row_count":100,"start_index":101}}
extra1:app/itdesk/api/v3/requests?input_data={"list_Info":{"row_count":100,"start_index":101}}
messed up the list info
extra : app/itdesk/api/v3/requests?input_data={"list_info"{"row_count":100,"start_index":101}}
extra1:app/itdesk/api/v3/requests?input_data={"list_info":{"row_count":100,"start_index":101}}
[shrug emoji]

Adding comments to this to clear up confusion. ManageEngine Service Desk Plus API is not a properly/typically implemented API. Basically you have to URL encode JSON and pass it in either the URL as a param or in the form as a application/x-www-form-urlencoded
example:
json:
{
"request": {
"subject": "testing subject",
"description": "I am a test. Delete me.",
"requester": {
"id": "4817"
},
"subcategory": {
"name": "Errors/Problems Using SalesForce",
"id": "2406"
},
"category": {
"name": "SalesForce",
"id": "608"
}
}
}
becomes:
input_data='%7B%0A++%22request%22%3A+%7B%0A++++%22subject%22%3A+%22testing+subject%22%2C%0A++++%22description%22%3A+%22I+am+a+test.+Delete+me.%22%2C%0A++++%22requester%22%3A+%7B%0A++++++%22id%22%3A+%224817%22%0A++++%7D%2C%0A++++%22subcategory%22%3A+%7B%0A++++%22name%22%3A+%22Errors%2FProblems+Using+SalesForce%22%2C%0A++++%22id%22%3A+%222406%22%0A++++%7D%2C%0A++++%22category%22%3A+%7B%0A++++%22name%22%3A+%22SalesForce%22%2C%0A++++%22id%22%3A+%22608%22%0A++++%7D%0A++%7D%0A%7D'

Related

Deserializing an api call response content without having to create a model representing the content

Is there another way to deserialize the response content of an api call into a generic object in .Net without having to create a model representing the json object? In other words, is there or does .Net provide a generic object or model that i can use to deserialize the response into. The reason being is because every api call response is not the same which means i have to create a new model for every api call. And i have about 20 different endpoints that return different responses, which means i would have to create 20 models representing the response.
My recommendation would be to create request and response models for this, even though it feels like extra work. This is because you'll need to eventually pass the parameters to functions in your business layer anyway, and you'll want to take advantage of the type safety without doing a bunch of Int32.TryParse's, which at that point, you're creating variables and doing extra work anyway. Actually, you're not going to be able to outrun the type safety the language not only provides, but generally requires. What I've done, is just copy/paste my DTO or EDMX table model into the new class, then decorate it. Pretty fast.
You may be looking for dynamic object which is late bound with unknown compile time properties.
A handy implementation of this is the JObject available with Newtonsoft.Json package and it offers similar functionality to the typeless elements of Javascript in that the properties can be of any type, with any nesting, etc. as long as it was parsed from well formed Json.
Usage is super simple, but watch out for null values, etc as default behavior for dynamic (aka ExpandoObject under the hood) is to throw exceptions for properties (aka Keys) not found...
public static void Run()
{
string apiJsonResponse = #"{
Name: 'Luke Skywalker',
Title: 'Jedi',
Skills : [
'Lightsaber',
'The Force'
]
}";
dynamic json = JObject.Parse(apiJsonResponse);
Console.WriteLine($"Name: {json.Name}");
Console.WriteLine($"Title: {json.Name}");
Console.WriteLine($"Skills: {String.Join(", ", json.Skills)}");
}
The result will be the Json dynamically parsed and rendered without any strongly typed model:
You can use generic method to have list of JObject. Based on your need you can extract model from jobject.
private static async Task<List<JObject>> CallApi(Uri uri, HttpContent data = null, string headerKey = null, string headerKeyVal = null)
{
string res = string.Empty;
try
{
var handler = new HttpClientHandler
{
//UseDefaultCredentials = true,
};
using var client = new HttpClient(handler);
if (!string.IsNullOrWhiteSpace(headerKey))
client.DefaultRequestHeaders.Add(headerKey, headerKeyVal);
var post = await client.GetAsync(uri);
//var post = await client.PostAsync(uri);
if (post.StatusCode != HttpStatusCode.InternalServerError)
{
res = await post.Content.ReadAsStringAsync();
}
return JsonConvert.DeserializeObject<List<JObject>>(res);
}
catch (Exception ex)
{
throw ex;
}
}
in .Net 3.1 after version, can use using System.Text.Json
api response data
{
"Status" : "0"
"Data" : {
"FirstName" : "firstName",
"LastName" : "lastName"
}
}
Response Model
public class ResponseModel
{
public string Status { get; set; }
public JsonElement Data { get; set; }
}
Deserialize
public void Deserialize()
{
var jsonString = "{ \"Status\": \"0\", \"Data\": { \"FirstName\": \"firstName\", \"LastName\" : \"last_name\"} }";
var response = JsonSerializer.Deserialize<ResponseModel>(jsonString);
//get first_name
var firstName = response.Data.GetProperty("FirstName").GetString();
Console.WriteLine(firstName);
}

How call WebAPI method in MVC and send the json object to it

I need to call this method in MVC controller and pass the UpdateRequest object as json format. how I can do that?
[HttpPost]
[Route("updatecertificate")]
public void updatecertificate([FromBody] UpdateRequest certificatereviewed)
{
loansRepository.updatecertificate(certificatereviewed.Id, certificatereviewed.CertificateReview);
}
and this is the input class:
public class UpdateRequest {
public int Id { get; set; }
public bool CertificateReview { get; set;}
}
this is how I call and send separate variable but now I like to send the class object in json format.
private async Task UpdateFundingCertificateReviewed(int id, bool fundingCertificateReviewed)
{
await httpClient.PostAsync(string.Format("{0}/{1}", LoanApiBaseUrlValue, updatecertificate),null);
}
I personally like Newtonsoft.Json to serialize the object.
private async Task UpdateFundingCertificateReviewed
(int id, bool fundingCertificateReviewed)
{
using (var client = new HttpClient())
{
var url = string.Format("{0}/{1}", LoanApiBaseUrlValue, updatecertificate);
var updateRequest = new UpdateRequest { Id = 1, CertificateReview = true};
var data = JsonConvert.SerializeObject(updateRequest);
await client.PostAsync(url, data);
}
}
FYI: Async without return is not a good practice. However, it is out of the original question.
If you want to transform an object into a JSON string, see this question: Turn C# object into a JSON string in .NET 4
var json = new JavaScriptSerializer().Serialize(obj);
Is this what you are after or do you want to know how to construct the http request with a JSON object in the body?
your questionis not very clear, what is the outcome that you expect ?
If you want to POST an request with JSON body you can check the #Win comment,
however if you want to make an Response from the Api to the MVC project you should do a bit more steps tough. :))

Displaying JSON data acquired from a WebRequest in ASP.NET 5 using MVC 6

this is my first question, so I apologize if I mess up the formatting or do this wrong in general, feel free to give me pointers, I'm always open to learn.
Anyway, my issue at hand is that I have a web application I'm working on using ASP.NET 5 and MVC 6, all up to date, and so far for testing, I've been using the localdb and working with fake data. Now, I have a url, with an API token, and login info, and I am using a WebRequest to get the data and stream it with a StreamReader into a variable, writing it, and then trying to return it.
WebRequest req = WebRequest.Create(#"https://url.fortheapi.com/api/search/things?criteria=" + userInput);
req.Method = "GET";
req.Headers["username"] = "user";
req.Headers["password"] = "password";
req.Headers["token"] = "token";
StreamReader responseReader = new StreamReader(req.GetResponse().GetResponseStream());
var responseData = responseReader.ReadToEnd();
Response.WriteAsync(responseData);
return View(responseData);
Here is where I'm stuck because I am not sure exactly how to pass it to the view as model data, I have no model currently, and I want to make one based on this database and use Entity Framework to work with it like I have been with the localdb. If there's a better way to do it, please feel free to present it. I will accept all the help I can get right now.
You need to create POCO classes to represent the data you receive from your api call. Once you get the response data, you may simply use a javascript serialize to deserialize the response to an object of your POCO class. You can pass this to your view.
public async Task<ActionResult> Contact()
{
var req = WebRequest.Create(#"yourApiEndpointUrlHere");
var r = await req.GetResponseAsync().ConfigureAwait(false);
var responseReader = new StreamReader(r.GetResponseStream());
var responseData = await responseReader.ReadToEndAsync();
var d = Newtonsoft.Json.JsonConvert.DeserializeObject<MyData>(responseData);
return View(d);
}
Assuming your api returns json data like this
{ "Code": "Test", "Name": "TestName" }
and you have created a POCO class called MyData which can be used to represent the data coming back from the api. You may use json2csharp to generate your C# classes from the json response you received from your api.
public class MyData
{
public string Code { get; set; }
public string Name { set;get;}
//Add other properties as needed
}
Now your view should be strongly typed to this POCO class
#model MyData
<h2>#Model.Code</h2>
<h2>#Model.Name</h2>
If what you are receiving is JSON, you can accomplish this is many ways.
One would be to wrap the code you've posted into a JSON Result typed Action. A very simplistic example below:
[HttpPost]
public JsonResult GetIncidentId(int customerId, string incidentNumber)
{
JsonResult jsonResult = null;
Incident incident = null;
try
{
incident = dal.GetIncident(customerId, incidentNumber);
if (incident != null)
jsonResult = Json(new { id = incident.Id });
else
jsonResult = Json(new { id = -1 });
}
catch (Exception exception)
{
exception.Log();
}
return jsonResult;
}
Calling it via Javascript from the view and manually populating your form (meh).
Or more elegantly, you could create an MVC model to hold the data you receive and serialise the JSON into that model. An example of which is below:
From: http://www.newtonsoft.com/json/help/html/deserializeobject.htm
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
string json = #"{
'Email': 'james#example.com',
'Active': true,
'CreatedDate': '2013-01-20T00:00:00Z',
'Roles': [
'User',
'Admin'
]
}";
Account account = JsonConvert.DeserializeObject<Account>(json);
Hope this helps and good luck with your app!

Can I manually hard code a JSON object to be returned by ASP.NET web API?

I'm used to doing this in Django (similar to Ruby on Rails) where in some cases I need to hard code a JSON response object for the client to be able to interpret, but I've been searching everywhere online on figuring out how to do this with ASP.NET web API and I can't find anything on this, ASP.NET web API seems to be forcing me to create a class to represent a JSON response for every URI controller.
For example, here's the only way I know for manually creating a JSON response:
1.) I first need to create the class to represent the response object
public class XYZ_JSON
{
public string PropertyName { get; set; }
public string PropertyValue { get; set; }
}
2.) Then I need to properly write up the URI controller that'll return an "XYZ_JSON" that I've just defined above:
// GET: api/ReturnJSON
public XYZ_JSON Get()
{
XYZ_JSON test = new XYZ_JSON { PropertyName = "Romulus", PropertyValue = "123123" };
return test;
}
Will result with an http response of something like:
200 OK
{"PropertyName":"Romulus", "PropertyValue":"123123"}
This whole class to JSON design pattern is cool and all, but it's not helpful and actually makes things much worse when trying to return a class as a JSON object with many classes within it such as:
public class XYZ_JSON
{
public string PropertyName { get; set; }
public string PropertyValue { get; set; }
public List<ComplexObject> objects { get; set; } // <- do not want
}
The JSON response object above isn't that complex, but for what I'm trying to accomplish I'll have to put a list of classes within a list of classes within a list of classes, and I can't develop it in this awkward way unless I spend a week on it which is just ridiculous.
I need to be able to return a JSON response in this kind of fashion:
// GET: api/ReturnJSON
public JSON_Response Get(string id)
{
// do some SQL querying here to grab the model or what have you.
if (somethingGoesWrong = true)
return {"result":"fail"}
else
return {"result":"success","value":"some value goes here"}
}
The design pattern above is what I'm trying to accomplish with ASP.NET web API, a very simply way to return a semi-hard coded JSON response object which would allow me to return very unique and dynamic responses from a single URI. There's going to be many use cases where a list of up to 8 completely unique Class objects will be returned.
Also, If what I'm trying to accomplish is the backwards way of doing things than that's fine. I've released a very successful and stable iOS application with a flawless Django backend server handling things this way perfectly without any issues.
Can someone explain to me how I can return a simple hard coded JSON response using the ASP.NET web API?
Thanks!
You can create anonymous types in C#, so you can use one of these to produce your hard-coded result. For example:
return new JsonResult
{
Data = new
{
result = "success",
value = "some value"
}
};
To clarify, the above code is for ASP.NET MVC. If you're using Web API, then you can just return the data object, or use an IHttpActionResult. The anonymous type part (the new {}) stays the same.
Use an anonymous object.
public object Get(string id)
{
// do some SQL querying here to grab the model or what have you.
if (somethingGoesWrong = true)
return new {result = "fail"}
else
return new {result = "success", value= "some value goes here"}
}
You can use a generic JObject to return your values without constructing a complete class structure as shown below
public JObject Get(int id)
{
return JsonConvert.DeserializeObject<JObject>(#"{""result"":""success"",""value"":""some value goes here""}");
}
For hard coded response, why not just do something like below. The JSON content will be returned without being surrounded by quotation marks.
public HttpResponseMessage Get()
{
string content = "Your JSON content";
return BuildResponseWithoutQuotationMarks(content);
}
private HttpResponseMessage BuildResponseWithoutQuotationMarks(string content)
{
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(content);
return response;
}
private HttpResponseMessage BuildResponseWithQuotationMarks(string content)
{
var response = Request.CreateResponse(HttpStatusCode.OK, content);
return response;
}
// GET: api/ReturnJSON
public JsonResult Get()
{
return Json(new { Property1 = "Value1", Property2 = "Value2" });
}
You can return json using JsonResult class. and the Json() method takes anonymous object so you don't need to create a class.

RestSharp: Converting results

I get the following JSON that I am trying to convert to a business object using RestSharp
{
"valid":true,
"data":[
{
"dealerId":"4373",
"branchId":"4373",
}
]
}
I wish to convert to:
public class Dealer
{
public string dealerId ;
public string branchId;
}
But this fails, though the JSON is fine:
var client = new RestClient("http://www.????.com.au");
var request = new RestRequest(string.Format("service/autocomplete/dealer/{0}/{1}.json", suburb.PostCode, suburb.City.Trim().Replace(" ", "%20")), Method.GET);
var response2 = client.Execute<Dealer>(request);
return response2.Data;
Your business object doesn't match the response JSON you are getting back. If you want your response to serialize, your C# object would look something like
public class DealerResponse
{
public bool valid { get;set; }
List<Dealer> data { get;set; }
}
public class Dealer
{
public string dealerId;
public string branchId;
}
I haven't tested this code, but even though you are only interested in the information in 'data', your response C# objects still need to represent the whole JSON response to serialize correctly.
Hope that helps.

Categories