Asp.Net Mvc Entity Framework Deserialized object Linq query null object - c#

I deserialize JSON file into my Entity Classes. for simplify, Let's assume these are my classes
public class Result{
...
public List<Sens> senses { get; set; }
}
public class Sens{
...
public Object definition { get; set; }
}
After I deserialize my JSON into a Result Object I insert to database. There is no error and I can insert Result and Senses with no conflict. But when I call Result from the database with LINQ query like this I get the Result object but my senses come null.
Question 1 Why and how can I solve it
var results =(from r in db.Results
where r.headword == Id
select r).ToList();
I try to add my senses to Result like this
foreach (Result item in resultmodel.Results)
{
item.senses = (from s in db.Senses
join r in db.Results on s.res equals r
where r.Id_ == item.Id_
select s).ToList();
}
I can add but when I try to show senses from my view I get
System.Collections.Generic.List`1[System.String]
But I am waiting it would be a string
Question 2 what is wrong with my approach.

There will be no problem if you convert your JSON string to the c# object. But in return, you want to map a string to object. What is that object? What are the properties? C# doesn't know anything about it.
One of my projects, I had a similar issue while writing and reading from Redis Cache server.
I added type definitions while serializing the object and deserialized with these types.
Serialize:
var jsonString = JsonConvert.SerializeObject(item, _settings);
return Encoding.UTF8.GetBytes(jsonString);
Deserialize:
JsonConvert.DeserializeObject<T>(jsonString, _settings);
Settings:
private static readonly JsonSerializerSettings _settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
Formatting = Formatting.None,
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
}
I hope this helps.

Related

Deserialize JSON to a dynamic object or a class in C#

I am trying to deserialize JSON into an object so I can add it to elastic search. JSON can be of many different object types in the project so I would like the function to be dynamic.
First I am serializing the Data that I get from EF Core context
var serializedObject = JsonConvert.SerializeObject(document, Formatting.None,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
Next I would like to deserialize to an object. For example if I have
public class EValues
{
public dynamic values { get; set; }
}
var test = JsonConvert.DeserializeObject<EValues>(serializedObject.ToString());
I would like the JSON to be deserialized to the below:
{
"values":{
"StudentId":"60712555-ff1d-4a3e-8c81-08d9c2fc4423",
"Student":{
"Name":"string",
"Country":"string",
"Street":"string"
}
}
}
The serializedObject JSON I am actually trying to deserialize:
{
"StudentId":"60712555-ff1d-4a3e-8c81-08d9c2fc4423",
"Student":{
"Name":"string",
"Country":"string",
"Street":"string"
}
}
You can just do:
var test = new EValues {
values = JsonConvert.DeserializeObject<dynamic>(serializedObject)
};
The JSON that would correspond to EValues would have an extra level of nesting { "values" : {} } not present in your serializedObject JSON.

Convert List<Model> to a customised json?

I am new to ASP.NET Core. I have tried to generate a json String with a List variable.
In Developers.cs Model,
public int Id { get; set; }
public string Name { get; set; }
I have added some data to the List
List<Developers> list = new List<Developers>();
list.Add(new Developers()
{
Id = 1;
Name = "Senura",
});
And I have converted that List into a String by parsing to a json
var json =list;
JsonConvert.SerializeObject(json, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented });
I am getting this output
[{"Id":1,"Name":"Senura"}]
I need to get an output like this >> {"result":[{"Id":1,"Name":"Senura"}]}
How can I get such?? Thanks in advance.
I have made a separate Model Class named DevResult.cs.
And I have added a Result property which accepts a List<Developers>.
And then created a variable from the newly created Model (DevResult.cs). And assigned the list variable to the Result property.
DevResult devRes = new DevResult()
{
Result = list,
};
And serialized DevResult variable to json object
JsonConvert.SerializeObject(devRes, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented });
Now it returns {"Result":[{"Id":1,"Name":"Senura"}]}
Big Thanks goes to #maccettura who has helped in the comments section.👍🏽

Deserialize json array in web api project

My controller method is as follows
public ActionResult Index()
{
Tweets model = null;
var client = new HttpClient();
var task = client.GetAsync("http://localhost:33615/api/product").ContinueWith((t) =>
{
var response = t.Result;
var readtask = response.Content.ReadAsAsync<Tweets>();
readtask.Wait();
model = readtask.Result;
});
task.Wait();
return View(model.Result);
}
The url return the row as follws:
[{"Id":1,"Name":"Honda Civic","Description":"Luxury Model 2013"},{"Id":2,"Name":"Honda Accord","Description":"Deluxe Model 2012"},{"Id":3,"Name":"BMW V6","Description":"V6 Engine Luxury 2013"},{"Id":4,"Name":"Audi A8","Description":"V8 Engine 2013"},{"Id":5,"Name":"Mercedes M3","Description":"Basic Model 2013"}]
My Tweets and tweet class are as follows:
public class Tweets
{
public Tweet[] Result;
}
public class Tweet
{
[JsonProperty("Name")]
public string Name { get; set; }
[JsonProperty("Description")]
public string Description { get; set; }
}
I can't figure it out where i do mistake.it gives me following error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'RestFiddlerTest.Controllers.Tweets' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly
How to fix this.
I've double checked your code and there are a few issues with it.
First of all, I don't see your logic to deserialize to Json, according to the JSon object, I'm guessing that you're using Newtonsoft.Json?
Then you have a class Tweets which contains an array of Tweet objects.
Now, when you create a small sample, like the following:
var dataToSerialize = new Tweets();
dataToSerialize.Result = new [] { new Tweet { Description = "Desc", Name = "Name" } };
var data = JsonConvert.SerializeObject(dataToSerialize);
The output of this piece of code will be the following:
{"Result":[{"Id":null,"Name":"Name","Description":"Desc"}]}
This is not the same as the output you get from your WebAPI.
Now, when you do use Newtonsoft.Json, when serializing your object, you are probably doing something like this:
const string JSon = "[{\"Id\":1,\"Name\":\"Honda Civic\",\"Description\":\"Luxury Model 2013\"},{\"Id\":2,\"Name\":\"Honda Accord\",\"Description\":\"Deluxe Model 2012\"},{\"Id\":3,\"Name\":\"BMW V6\",\"Description\":\"V6 Engine Luxury 2013\"},{\"Id\":4,\"Name\":\"Audi A8\",\"Description\":\"V8 Engine 2013\"},{\"Id\":5,\"Name\":\"Mercedes M3\",\"Description\":\"Basic Model 2013\"}]";
var data = JsonConvert.DeserializeObject<Tweets>(JSon);
Note: I've put the Json string in a string because I didn't have the time to write a full WebAPI.
Now, this will not work, because the string I input and that's also the one that your controller does return is not a Tweets object (remember you're missing the Result in your JSon string? Instead, this is a array of Tweet objects, so you can change your code like the following:
var data = JsonConvert.DeserializeObject<Tweet>(JSon);
Unfortunately, you will receive the exact same error. So why is that? Because you're trying to deserialize your object into an object of type Tweet while your object is an array of type Tweet.
So, modify your code like the following:
var data = JsonConvert.DeserializeObject<Tweet[]>(JSon);
Now, you're deserializing your object into the correct type.
So, I do hope that this post will help you.
Kind regards,
I used Newtonsoft.Json.
public ActionResult Index()
{
List<Tweet> model = null;
var client = new HttpClient();
var task = client.GetAsync("http://localhost:33615/api/product").ContinueWith((t) =>
{
var response = t.Result;
var readtask = response.Content.ReadAsAsync<List<Tweet>>();
readtask.Wait();
model = readtask.Result;
});
task.Wait();
return View(model);
}

How to extract data from JSON in ASP.NET using c#

{"pometek.net":{"status":"available","classkey":"dotnet"},"pometek.com":{"status":"available","classkey":"domcno"}}
I want to dispense this in table format. Need help.
You can use Json.NET to deserialize the json object into a C# class, and then map that class to a table format in asp.net
You shouldn't need a third-party library; the out-of-the-box JavaScriptSerializer can handle this.
class Item {
public string status { get; set; }
public string classkey { get; set; }
}
var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
var input = "{\"pometek.net\":{\"status\":\"available\",\"classkey\":\"dotnet\"},\"pometek.com\":{\"status\":\"available\",\"classkey\":\"domcno\"}}";
var results = jss.Deserialize<Dictionary<string, Item>(input);
var query = results["pometek.net"].status; // = "available"
Displaying this as a table is a separate step.

A circular reference was detected while serializing an object of type 'SubSonic.Schema .DatabaseColumn'.

I am trying to do a simple JSON return but I am having issues I have the following below.
public JsonResult GetEventData()
{
var data = Event.Find(x => x.ID != 0);
return Json(data);
}
I get a HTTP 500 with the exception as shown in the title of this question. I also tried
var data = Event.All().ToList()
That gave the same problem.
Is this a bug or my implementation?
It seems that there are circular references in your object hierarchy which is not supported by the JSON serializer. Do you need all the columns? You could pick up only the properties you need in the view:
return Json(new
{
PropertyINeed1 = data.PropertyINeed1,
PropertyINeed2 = data.PropertyINeed2
});
This will make your JSON object lighter and easier to understand. If you have many properties, AutoMapper could be used to automatically map between DTO objects and View objects.
I had the same problem and solved by using Newtonsoft.Json;
var list = JsonConvert.SerializeObject(model,
Formatting.None,
new JsonSerializerSettings() {
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
});
return Content(list, "application/json");
This actually happens because the complex objects are what makes the resulting json object fails.
And it fails because when the object is mapped it maps the children, which maps their parents, making a circular reference to occur. Json would take infinite time to serialize it, so it prevents the problem with the exception.
Entity Framework mapping also produces the same behavior, and the solution is to discard all unwanted properties.
Just expliciting the final answer, the whole code would be:
public JsonResult getJson()
{
DataContext db = new DataContext ();
return this.Json(
new {
Result = (from obj in db.Things select new {Id = obj.Id, Name = obj.Name})
}
, JsonRequestBehavior.AllowGet
);
}
It could also be the following in case you don't want the objects inside a Result property:
public JsonResult getJson()
{
DataContext db = new DataContext ();
return this.Json(
(from obj in db.Things select new {Id = obj.Id, Name = obj.Name})
, JsonRequestBehavior.AllowGet
);
}
To sum things up, there are 4 solutions to this:
Solution 1: turn off ProxyCreation for the DBContext and restore it in the end.
private DBEntities db = new DBEntities();//dbcontext
public ActionResult Index()
{
bool proxyCreation = db.Configuration.ProxyCreationEnabled;
try
{
//set ProxyCreation to false
db.Configuration.ProxyCreationEnabled = false;
var data = db.Products.ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(ex.Message);
}
finally
{
//restore ProxyCreation to its original state
db.Configuration.ProxyCreationEnabled = proxyCreation;
}
}
Solution 2: Using JsonConvert by Setting ReferenceLoopHandling to ignore on the serializer settings.
//using using Newtonsoft.Json;
private DBEntities db = new DBEntities();//dbcontext
public ActionResult Index()
{
try
{
var data = db.Products.ToList();
JsonSerializerSettings jss = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
var result = JsonConvert.SerializeObject(data, Formatting.Indented, jss);
return Json(result, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(ex.Message);
}
}
Following two solutions are the same, but using a model is better because it's strong typed.
Solution 3: return a Model which includes the needed properties only.
private DBEntities db = new DBEntities();//dbcontext
public class ProductModel
{
public int Product_ID { get; set;}
public string Product_Name { get; set;}
public double Product_Price { get; set;}
}
public ActionResult Index()
{
try
{
var data = db.Products.Select(p => new ProductModel
{
Product_ID = p.Product_ID,
Product_Name = p.Product_Name,
Product_Price = p.Product_Price
}).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(ex.Message);
}
}
Solution 4: return a new dynamic object which includes the needed properties only.
private DBEntities db = new DBEntities();//dbcontext
public ActionResult Index()
{
try
{
var data = db.Products.Select(p => new
{
Product_ID = p.Product_ID,
Product_Name = p.Product_Name,
Product_Price = p.Product_Price
}).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(ex.Message);
}
}
JSON, like xml and various other formats, is a tree-based serialization format. It won't love you if you have circular references in your objects, as the "tree" would be:
root B => child A => parent B => child A => parent B => ...
There are often ways of disabling navigation along a certain path; for example, with XmlSerializer you might mark the parent property as XmlIgnore. I don't know if this is possible with the json serializer in question, nor whether DatabaseColumn has suitable markers (very unlikely, as it would need to reference every serialization API)
add [JsonIgnore] to virtuals properties in your model.
Using Newtonsoft.Json: In your Global.asax Application_Start method add this line:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
Its because of the new DbContext T4 template that is used for generating the EntityFramework entities. In order to be able to perform the change tracking, this templates uses the Proxy pattern, by wrapping your nice POCOs with them. This then causes the issues when serializing with the JavaScriptSerializer.
So then the 2 solutions are:
Either you just serialize and return the properties you need on the client
You may switch off the automatic generation of proxies by setting it on the context's configuration
context.Configuration.ProxyCreationEnabled = false;
Very well explained in the below article.
http://juristr.com/blog/2011/08/javascriptserializer-circular-reference/
Provided answers are good, but I think they can be improved by adding an "architectural" perspective.
Investigation
MVC's Controller.Json function is doing the job, but it is very poor at providing a relevant error in this case. By using Newtonsoft.Json.JsonConvert.SerializeObject, the error specifies exactly what is the property that is triggering the circular reference. This is particularly useful when serializing more complex object hierarchies.
Proper architecture
One should never try to serialize data models (e.g. EF models), as ORM's navigation properties is the road to perdition when it comes to serialization. Data flow should be the following:
Database -> data models -> service models -> JSON string
Service models can be obtained from data models using auto mappers (e.g. Automapper). While this does not guarantee lack of circular references, proper design should do it: service models should contain exactly what the service consumer requires (i.e. the properties).
In those rare cases, when the client requests a hierarchy involving the same object type on different levels, the service can create a linear structure with parent->child relationship (using just identifiers, not references).
Modern applications tend to avoid loading complex data structures at once and service models should be slim. E.g.:
access an event - only header data (identifier, name, date etc.) is loaded -> service model (JSON) containing only header data
managed attendees list - access a popup and lazy load the list -> service model (JSON) containing only the list of attendees
Avoid converting the table object directly. If relations are set between other tables, it might throw this error.
Rather, you can create a model class, assign values to the class object and then serialize it.
I'm Using the fix, Because Using Knockout in MVC5 views.
On action
return Json(ModelHelper.GetJsonModel<Core_User>(viewModel));
function
public static TEntity GetJsonModel<TEntity>(TEntity Entity) where TEntity : class
{
TEntity Entity_ = Activator.CreateInstance(typeof(TEntity)) as TEntity;
foreach (var item in Entity.GetType().GetProperties())
{
if (item.PropertyType.ToString().IndexOf("Generic.ICollection") == -1 && item.PropertyType.ToString().IndexOf("SaymenCore.DAL.") == -1)
item.SetValue(Entity_, Entity.GetPropValue(item.Name));
}
return Entity_;
}
You can notice the properties that cause the circular reference. Then you can do something like:
private Object DeCircular(Object object)
{
// Set properties that cause the circular reference to null
return object
}
//first: Create a class as your view model
public class EventViewModel
{
public int Id{get;set}
public string Property1{get;set;}
public string Property2{get;set;}
}
//then from your method
[HttpGet]
public async Task<ActionResult> GetEvent()
{
var events = await db.Event.Find(x => x.ID != 0);
List<EventViewModel> model = events.Select(event => new EventViewModel(){
Id = event.Id,
Property1 = event.Property1,
Property1 = event.Property2
}).ToList();
return Json(new{ data = model }, JsonRequestBehavior.AllowGet);
}
An easier alternative to solve this problem is to return an string, and format that string to json with JavaScriptSerializer.
public string GetEntityInJson()
{
JavaScriptSerializer j = new JavaScriptSerializer();
var entityList = dataContext.Entitites.Select(x => new { ID = x.ID, AnotherAttribute = x.AnotherAttribute });
return j.Serialize(entityList );
}
It is important the "Select" part, which choose the properties you want in your view. Some object have a reference for the parent. If you do not choose the attributes, the circular reference may appear, if you just take the tables as a whole.
Do not do this:
public string GetEntityInJson()
{
JavaScriptSerializer j = new JavaScriptSerializer();
var entityList = dataContext.Entitites.toList();
return j.Serialize(entityList );
}
Do this instead if you don't want the whole table:
public string GetEntityInJson()
{
JavaScriptSerializer j = new JavaScriptSerializer();
var entityList = dataContext.Entitites.Select(x => new { ID = x.ID, AnotherAttribute = x.AnotherAttribute });
return j.Serialize(entityList );
}
This helps render a view with less data, just with the attributes you need, and makes your web run faster.

Categories