JsonConvert.DeserializeObject always returns null - json

I'm trying to consume a soccer API (SportMonks) in my ASP.NET MVC Project. I'm new to this so I'm facing a problem of sending deserialized JSON from Controller to View. Here is the code:-
JSON Response:
{"data":[{"id":1,"name":"Europe"},{"id":2,"name":"Asia"},{"id":3,"name":"Africa"},{"id":4,"name":"Oceania"},{"id":5,"name":"Antarctica"},{"id":6,"name":"North America"},{"id":7,"name":"South America"}],"meta":{"subscription":{"started_at":{"date":"2017-03-20 21:02:56.000000","timezone_type":3,"timezone":"UTC"},"trial_ends_at":null,"ends_at":null},"plan":{"name":"Free Plan","price":"0.00","request_limit":"3,1"},"sports":[{"id":1,"name":"Soccer","current":true},{"id":6,"name":"Cricket","current":false}]}}
Models:-
public class SAPI_Continent
{
public int id { get; set; }
public string name { get; set; }
}
public class SoccerAPI
{
public IList<SAPI_Continent> continents { get; set; }
}
Contorller
[HttpGet]
public ActionResult ConsumeExternalAPI()
{
var webClient = new WebClient();
var json = webClient.DownloadString(#"https://soccer.sportmonks.com/api/v2.0/continents?api_token=nAfVFSbRn3x7tP7b840mitMVli48deY0sVndIB6zpae8MquprEivAuH7zplu");
SoccerAPI continents = JsonConvert.DeserializeObject<SoccerAPI>(json);
return View(continents);
}
continents is always null although var json is returning the data normally
View
#if (Model != null)
{
<ul>
#foreach (var con in Model.continents)
{
<li>#con.name</li>
}
</ul>
}
else
{
<p>Error</p>
}
How Can I get the values from the `data` part only `id & name` and why the deserialised variable is null?

Referring to your "null" question. Your continents attribute should be changed to data, as this is the name returned from json.

Related

how to get json data from external rest full web service in asp.net mvc 4

I am trying to get the json data from an external rest url(http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3) and display it on my web page in my asp.net mvc application. For that I have written some code i.e.
Controleer---
namespace MyMVCApplication.Controllers
{
public class EmployeeController : Controller
{
string Baseurl = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3";
public async Task<ActionResult> StateDetails()
{
List<State> listStateInfo = new List<State>();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage Res = await client.GetAsync(Baseurl);
if (Res.IsSuccessStatusCode)
{
//Storing the response details recieved from web api
var StateResponse = Res.Content.ReadAsStringAsync().Result;
//Deserializing the response recieved from web api and storing into the Employee list
listStateInfo = JsonConvert.DeserializeObject<List<State>>(StateResponse);
}
return View(listStateInfo);
}
}
}
}
Model----
namespace MyMVCApplication.Models
{
public class State
{
public int ObjectID { get; set; }
public string StateName { get; set; }
public int Black { get; set; }
public int Population { get; set; }
}
}
While debugging the code getting the error: "Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 10, position 1" at
JsonConvert.DeserializeObject.
Please suggest me how to solve this issue.
Replace your url with http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/3?f=pjson to get the json version of the web service

Web Api 2 controller to download wikipedia api and show json output on web

I am trying to parse a wikipedia api which contain the short text of an article.I am using ASP.Net MVC for coding. My wikipedia api is https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exlimit=max&explaintext&exintro&titles=Berlin&redirects= which is in json formatted. At present what I have done is - inside the Model I created a folder named Wiki, and inside it I created four class named Limits.cs, Pageval.cs, Query.cs, Rootobject.cs.
public class Limits
{
public int extracts { get; set; }
}
public class Pageval
{
public int pageid { get; set; }
public int ns { get; set; }
public string title { get; set; }
public string extract { get; set; }
}
public class Query
{
public Dictionary<string, Pageval> pages { get; set; }
}
public class Rootobject
{
public string batchcomplete { get; set; }
public Query query { get; set; }
public Limits limits { get; set; }
}
Now in the controller class I created a WebApi 2 contrller to make the model object show on the web. In this case I am very new in handling this situation because I am new at MVC. I am trying to parse in this way but it is not working at all.
public class WikiController : ApiController
{
// GET: api/Wiki
// GET: api/Wiki/5
public string GetShortText(string name)
{
string result;
using (WebClient client = new WebClient())
{
var response = client.DownloadString("https://en.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exlimit=max&explaintext&exintro&titles=" + name + "&redirects=");
var responseJson = JsonConvert.DeserializeObject<Rootobject>(response);
var firstKey = responseJson.query.pages.First().Key;
var extract = responseJson.query.pages[firstKey].extract;
try
{
Regex regex = new Regex(#".(?<=\()[^()]*(?=\)).(.)");
string.Format("Before:{0}", extract);
extract = regex.Replace(extract, string.Empty);
string result1 = String.Format(extract);
result = Regex.Replace(result1, #"\\n", " ");
}
catch (Exception)
{
result = "Error";
}
}
return result;
}
The Routconfig is-
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
You can do a couple of things. You can use attribute routing or you can define a route for your custom method. The reason it does not map at the moment is that you do not have a route that defines your parameter. So going the route way you can define
routes.MapRoute(
name: "Wiki",
url: "api/wiki/getshorttext/name",
defaults: new { controller = "Wiki", action = "GetShortText", name = UrlParameter.Optional }
)
;
On a side note as you are performing a I/O bound operation I would suggest making your action async using async and await feature of .net. This way you won't block any thread while you waiting for Wikipedia to respond. Also HttpClient offers a DownloadStringAsync which is awaitable. Have a look at async and await

jQuery Bootgrid - Ajax Sort Parameter with ASP.NET MVC Actions

I managed to create an ApiController retrieving data from my repositories, and populating a grid in my view through Bootgrid with Ajax. This is an example of request data sent to Api's Action, given by their Docs here (look for POST Body Request tab):
current=1&rowCount=10&sort[sender]=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed
Here is an example URL:
http://localhost/api/SomeController?current=1&rowCount=10&sort%5BName%5D=asc&searchPhrase=&id=b0df282a-0d67-40e5-8558-c9e93b7befed
I created two Helper classes to handle data I must return as response, and sort data (as it's an array):
public class SortData
{
public string Field { get; set; } // FIeld Name
public string Type { get; set; } // ASC or DESC
}
public class BootgridResponseData<T> where T: class
{
public int current { get; set; } // current page
public int rowCount { get; set; } // rows per page
public IEnumerable<T> rows { get; set; } // items
public int total { get; set; } // total rows for whole query
}
Therefore, my action is as follow:
public BootgridResponseData<SomeViewModel> Get(int current, int rowCount, List<SortData> sort, string searchPhrase, string id)
{
// get items and return a bootgrid response data with them...
}
The method is invoked and all parameters come with data properly, except sort, which is always null.
What kind of parameter should I expect for this? I also tried to put object but it comes null anyway.
After learning a bit more, I saw Bootgrid has a requestHandler setting which allows you to manipulate data sent to server.
I did it in my javascript like this:
var grid = $("#my-grid").bootgrid({
ajax: true,
rowCount: 10,
ajaxSettings: {
method: "POST",
cache: true
},
requestHandler: function (request) {
// Scan the original sort object from Bootgrid...
// and populate an array of "SortData"...
request.sortItems = [];
if (request.sort == null)
return request;
for (var property in request.sort) {
if (request.sort.hasOwnProperty(property)) {
request.sortItems.push({ Field: property, Type: request.sort[property] });
}
}
return request;
},
url: "/api/FooApi"
});
Then I created my post action in API like this:
public class FooApiController : ApiController
{
[HttpPost]
public BootgridResponseData<FooModel> Get(BootgridRequestData model)
{
// This would come from some data store, using the request params...
// I use PagedList to make pagination easier...
IPagedList<FooModel> itemsPaged = store.GetPagedFoo();
// Then return the response with data...
return new BootgridResponseData<FooModel>()
{
current = model.current,
rowCount = model.rowCount,
rows = itemsPaged,
total = itemsPaged.TotalItemCount
};
}
}
The BootgridResponseData has already been shown in my question. I just added a BootgridRequestData which the following structure:
public class BootgridRequestData
{
public int current { get; set; }
public int rowCount { get; set; }
public string searchPhrase { get; set; }
public IEnumerable<SortData> sortItems { get; set; }
}
Then I could even use my original SortData helper class:
public class SortData
{
public string Field { get; set; } // FIeld Name
public string Type { get; set; } // ASC or DESC
}
I've struggled with this as well. You are overthinking it. It's nice to create simple models to handle the post call from jquery-bootgrid, but you can also just use simple parameters in the post method. As for the sort, it looks like a Key-Value pair, but that doesn't serialize properly.
I ended up trying a Dictionary object and it works.
Here is my signature:
[HttpPost]
public async Task<ActionResult> GetActiveDogs(int? current, int? rowCount,
Dictionary<string, string> sort, string searchPhrase = null)
I had the same problem passing the sort options to my webservice. The Dictionary object did not solve my problem either.
To solve it, I created a class holding string properties for each field I wanted to pass through the bootgrid sort options. See code excerpt
class TestSort
{
public string field1 { get; set; }
public string field2 { get; set; }
...
}
I use this class as the sort options parameter in my webservice. All fields in this class that are referred to by the bootgrid options are set to "ASC" or "DESC". The others remain null.
I added an 'orderBy' property to this class that returns an orderby clause for the fields that are not null.
Approch1.
consider you have table with columns "col1, col2, col3, ...".
you can use:
public ActionType Get(int current, int rowCount, Sort sort, string searchPhrase) {
//sort.col1 == 'asc' (consider sorted by col1 in ascending order)
}
public class Sort
{
public string col1 { get; set; }
public string col2 { get; set; }
public string col3 { get; set; }
//... other columns
}
Approach 2.
You can use remove you parameters and parse request data manually. i used post here instead of get.
[HttpPost]
public object Post(){
string jsonContent = Request.Content.ReadAsStringAsync().Result;
Dictionary<string, string> keyvalues = new Dictionary<string, string>();
string[] keyvalue_strings = jsonContent.Split('&');
string sort_column = "";
string sort_direction = "";
for (var i = 0; i< keyvalue_strings.Length; i++)
{
var a = keyvalue_strings[i].Split('=');
a[0] = a[0].Replace("%5B", "[").Replace("%5D", "]");
keyvalues.Add(a[0], (a[1]));
if (a[0].Contains("sort"))
{
sort_column = a[0].Replace("sort[", "").Replace("]", "");
sort_direction = a[1];
}
}
//now you have keyvalues, sort_column, sort_direction.
//...
}

Post complex type to web api

I am trying to post below complex object Inspection to a web api httppost method ,
public class Inspection
{
public string Url { get; set; }
public int HireContractLineId { get; set; }
public List<ImageInfo> Images { get; set; }
}
public class ImageInfo
{
public DateTime CapturedDateTime { get; set; }
public string ImageData { get; set; }
public string FileName { get; set; }
public string ContentType { get; set; }
}
my controller is
[ActionName("Inspection")]
[HttpPost]
public HttpResponseMessage Post([FromBody] Inspection inspection)
{
List<ImageInfo> images = inspection.Images;
for (var i = 0; i < images.Count; i++)
{
}
}
As long as I post say 5 to 6 images, the controller receives the object correctly and process it, but if I try to post with more images say 10 (all images around 200 KB), I could hit the controller , but before I reach for loop, the controller hits again and this time passed Inspection object is null and I get Null reference exception.
I guess it has something to do with the size of the passed object, but I couldn't figure out where to increase the size ,with only 5-6 Image Objects, everything works fine.
Below is how the controller is called
client.BaseAddress = new Uri(AppParameters.WebApiBaseURL);
HttpResponseMessage response =
await client.PostAsJsonAsync("api/fleetitems/Inspection", inspection);

How to convert json dynamic object to c# entity

When I make mvc ajax json post applicaiton, there is a trouble to convert json dynamic object to entity.
In my app, movie is a business entity, json object has row status property than movie entity. When json data is posted to mvc server side, it can be converted to dynamic object, everyting is ok in this stage. But after handling some logic to each row status, it is needed to convert dynamic object to movie business entity, then begin database transaction logic. But there is a troulbe even I try different method to cast the object.
please did someone use the same cast method? thanks your advice or reply.
public class movie
{
public int id
{
get;
set;
}
public string title
{
get;
set;
}
}
/// <summary>
/// Convert Json Object to Entity
/// </summary>
/// <param name="id">ajax post value
/// format: {"id": "{\"id\": 1, \"title\": \"sharlock\", \"RowStatus\": \"deleted\"}"}
/// </param>
[AllowAnonymous]
[HttpPost]
public void DoJsonSimple(string id)
{
string title;
var entity = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(id);
//*** entity is dynamic object
//*** entity.id, entity.title and entity.RowStauts can be accessed.
int first = entity.id;
var status = entity.RowStatus;
if (status == "deleted")
{
//*** m1 is null
//*** m1.title can not be accessed
movie m1 = entity as movie;
title = m1.title;
//*** m2 is an empty object
//*** m2.id is 0, m2.title is null
var m2 = AutoMapperHelper<dynamic, movie>.AutoConvertDynamic(entity);
title = m2.title;
//*** Exception: Object must implement IConvertible.
var m3 = EmitMapper.EMConvert.ChangeTypeGeneric<dynamic, movie>(entity);
title = m3.title;
}
}
Just create another class for the rows.
public class Request
{
[JsonProperty("id")]
public string Json { get; set; }
}
public class Movie
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
}
// either this for variant 1...
public class Row
{
public string RowStatus { get; set; }
}
// or that for variant 2...
public class MovieRow : Movie
{
public string RowStatus { get; set; }
}
[AllowAnonymous]
[HttpPost]
public void DoJsonSimple_Variant1(string id)
{
var json = JsonConvert.DeserializeObject<Request>(id).Json;
var entity = JsonConvert.DeserializeObject<MovieRow>(json);
var row = JsonConvert.DeserializeObject<Row>(json);
switch (row.RowStatus)
{
case "deleted":
// delete entity
break;
// ...
}
// ...
}
[AllowAnonymous]
[HttpPost]
public void DoJsonSimple_Variant2(string id)
{
var json = JsonConvert.DeserializeObject<Request>(id).Json;
var row = JsonConvert.DeserializeObject<MovieRow>(json);
var entity = (Movie)row;
switch (row.RowStatus)
{
case "deleted":
// delete entity
break;
// ...
}
// ...
}