I have a problem with Serialization of Data from database to JSON format. I'm using WebAPI 2 and Entity Framework 6. I've created with EF a Model. The database and the tables with content are even created.
When I use the code below I'm getting an error when I type http://localhost:54149/api/qr_group .
Controller:
private EfContext db = new EfContext();
// GET api/<controller>
public IEnumerable<QR_Group> GetGroups()
{
var result = from g in db.QR_Groups
select g;
return result.ToList();
}
I don't know how to use Newtonsoft.Json to serialize the table with the content in JSON format.
I've tried the following code instead of the code above:
public IQueryable<QR_Group> GetGroups()
{
var groupList = (from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
}).AsQueryable();
var json = JsonConvert.SerializeObject(groupList);
return json; //error CS0029: Cannot implicitly convert type `string' to `System.Linq.IQueryable<RestApi.Models.QR_Group>'
}
I get the error CS0029.. How can I solve this to return the data in json? As reminder: The QR_Group entity has 3 columns (Id, name, code)
Specifically to your second function, JsonConvert.SerializeObject would just serialize any object into a JSON format string, which means you should return a string instead of an IQueryable<>.
So for the controller there are quite a few ways to return it back, like: In MVC, how do I return a string result?
EDIT:
Following code would be one way that should working:
Controller:
private EfContext db = new EfContext();
// GET api/<controller>
public ActionResult GetGroups()
{
var groupList = (from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
}).AsQueryable();
return Content(JsonConvert.SerializeObject(groupList));
}
you didn't mention the error when you are returning list from the api
controller. as i assume that you are returning a database entity that
in simple case not allow you as json result, because your entity may
be linked with other entities in the database.
you can check this link for reference
Now modify your code to something like below. It is just to make you understand.
Define a Type say QR_Group_Return
public class QR_Group_Return{
public string name{ get; set;}
public string code{ get; set;}
// Some other properties will go here.
}
Now instead of returning IEnumerable<QR_Group> we will return IEnumerable<QR_Group_Return>
private EfContext db = new EfContext();
// GET api/<controller>
public IEnumerable<QR_Group_Return> GetGroups()
{
var result = (from g in db.QR_Groups
select new QR_Group_Return {
name = g.name,
code = g.code,
// map your other properties also
}).ToList();
return result;
}
Hope this helps
Related
public Class SomeModel
{
public int Id { get; set;}
public string Name {get; set;}
}
this is the method I'm binding values to above model, it contains inline SQL Queries
Public ActionResult GetData()
{
IEnumarable<SomeModel> alltheListValues = ....
}
using above method, I want to filter all the record that containing ids in following string.
string filterIds = "12,13,14,15"
SomeModel model class Id values are in Integer type, but I have string type id set, without going for looping this, I decided to use WHERE IN query to filter this.
since WHERE IN query we can get in Linq as contains
I wrote down follwoing function to filter values
IEnumarable<SomeModel> filterValues = GetData.Where(Id=> Id.ToString().Contains(filterIds));
but this is not selecting any value always zero filter result, how can I wrote this properly
This could be a way to go:
string filterIds = "12,13,14,15";
//Convert filterIds string into a integers collection
var ids=filterIds.Split(',').Select(int.Parse);
IEnumarable<SomeModel> filterValues = GetData().Where(sm=> ids.Contains(sm.Id));
One thing I noticed now is the signature of your GetData method, I think what you mean is:
public IEnumarable<SomeModel> GetData()
{
IEnumarable<SomeModel> alltheListValues = ....
//...
return alltheListValues;
}
Have a array/collection instead of a list and check if the id is in it.
IEnumarable<SomeModel> filterValues = ActualGetData().Where(n => filterIds.Contains(n.Id))
Where ActualGetData() returns you an IEnumarable.
In your current code GetData() returns an ActionResult as Drew Kennedy mentioned
If you are sure that all the elements of collection of "Id" will be convertible to number then you can use following approach.
var models = new List<SomeModel>(); //Consider that this collection is coming from some service or repository.
var Ids = filterIds.Split(',').Select(x => int.Parse(x));
IEnumarable<SomeModel> filterValues = models.Where(n => Ids.Contains(n.Id));
Your code wound't compile so I am posting here just the logical code here. You can use it as per your requirement.
In my controller I have a method that looks like this:
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == CarCategoryId[0]
select new { search.Manufacturer, search.Model, search.Gear };
I'm trying to get the output of this statement to the view..
ViewData["somename"] = CarModelAndGear;
This way won't work.. I'm getting an error "LINQ to entities does not recognize the method 'Int32 get_Item(Int32)' method, and this method cannot be translated into a store expression. "
How can I get 'CarModelAndGear' to the view?
You need to store the category in a variable first because the provider is not able to interpret the list indexer method:
int CatId = CarCategoryId[0];
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == CatId
select new { search.Manufacturer, search.Model, search.Gear };
You are using LinqToSql here. So what it is trying to do is convert that Linq expression into a SQL statement.
While you can access an item in a collection from C#, this cannot be translated into SQL, so it falls over.
Try this rather:
var id = CarCategoryId[0];
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == id
select new { search.Manufacturer, search.Model, search.Gear };
You can execute linq and then assign to ViewData
ViewData["somename"] = CarModelAndGear.ToList();
But i prefer approach described by live2, when you will combine everything to model and then pass the model
Create a model for your result
public class CarViewResult
{
public string Manufacturer { get; set; }
public string Model { get; set; }
public string Gear { get; set; }
public CarViewResult(string manufacturer, string model, string gear)
{
this.Manufacturer = manufacturer;
this.Model = model;
this.Gear = gear;
}
}
Add add the new model to your LINQ query
var CarModelAndGear = from search in entity.CarsCategories
where search.ID == CarCategoryId[0]
select new CarViewResult(search.Manufacturer, search.Model, search.Gear);
ViewData["somename"] = CarModelAndGear.ToList();
I am facing this situation and it is really strange to me.
I have class A has the following
public class A
{
public A()
{
Values = new List<B>();
}
public virtual IList<B> Values { get; set; }
}
I have a method that will read all A records form the db.
var all = await GetAll();
here is my method
public async Task<IList<A>> GetAll(int id1)
{
var parameters = new[]
{
new SqlParameter("#ProductTypeId", SqlDbType.Int) {Value = id1},
};
return (await _sqlCommandWrapper.ExecuteReaderAsync("SPName", r => new A
{
values = JsonConvert.DeserializeObject<IList<B>>(r["Values"].ToString())
}, parameters)).ToList();
}
my db column r["Values"] will return json that can be deserialized to list of B class.
Then i am using linq to query all my A:
var subitems = all .Where(a=> a.Values .Count > 0).ToList();
If my r["Values"] return data, it works fine.
however if it is not then a.Values is null ?
Any reason, however I defined in my A constructor that Values = new List<B>();
Reason for the issue is, following code which do the Json deserialization replaces the Values of type (IList<B>), you are not doing anything with the original list that is instantiated in the constructor
values = JsonConvert.DeserializeObject<IList<B>>(r["Values"].ToString())
When r["Values"].ToString() is a valid Json it gets deserialized into IList<B> which is an assignment call, now when r["Values"].ToString() generates a Json that is a mismatch or empty then the result of the following code is Null
JsonConvert.DeserializeObject<IList<B>>(r["Values"].ToString())
In case you plan to use the List instantiated in the constructor then it should be:
Values.Add(JsonConvert.DeserializeObject<B>(r["Values"].ToString()))
In this case r["Values"].ToString() generates the Json for type B not IList<B>
However this would certainly not work as is, since you are generating a new A, which is then added to IList<A> and returned as a Task result, so that part would also need modification
For unit testing purposes, I'd like to test my class mappings without reading and writing documents into the MongoDB database. To handle special cases such as circular parent / child references and read only properties, I've used BsoncClassMap.RegisterClassMap< MyType>(...) with some custom mappings overriding the default AutoMap(); generated mappings.
Does anyone know how to convert a BsonDocument into the desired strongly typed object without making a round trip to the database? The driver is doing this when going to and from the data store. My goal would be to use the same logic that the MongoDB C# driver is using internally to test the serialization to / from a C# domain object into a BsonDocument.
I'm able to use the Bson extension method ToBsonDocument() to convert a C# object into a BsonDocument? The piece that I'm lacking is the reverse of the process - essentially a BsonDocument.ToObject< MyType>();.
Is this possible with the latest version of the official MongoDB C# driver? It seems like it should be - I'm wondering if I'm just blind and am missing the obvious.
The MongoDB Driver does provide a method for deserializing from Bson to your type. The BsonSerializer can be found in MongoDB.Bson.dll, in the MongoDB.Bson.Serialization namespace.
You can use the BsonSerializer.Deserialize<T>() method. Some example code would be
var obj = new MyClass { MyVersion = new Version(1,0,0,0) };
var bsonObject = obj.ToBsonDocument();
var myObj = BsonSerializer.Deserialize<MyClass>(bsonObject);
Console.WriteLine(myObj);
Where MyClass is defined as
public class MyClass
{
public Version MyVersion {get; set;}
}
I hope this helps.
A straight forward way if you want to map rows fetched from mongoDB to a class within your code is as below
//Connect and Query from MongoDB
var db = client.GetDatabase("blog");
var col = db.GetCollection<BsonDocument>("users");
var result = await col.Find(new BsonDocument("Email",model.Email)).ToListAsync();
//read first row from the result
var user1 = result[0];
result[0] would be say "{ "_id" : ObjectId("569c05da09f251fb0ee33f5f"), "Name" : "fKfKWCc", "Email" : "pujkvBFU#kQKeYnabk.com" }"
//A user class with name and email
User user = new User();
// assign
User.Name = user1[1].ToString(); // user1[1] is "fKfKWCc"
User.Email = user1[2].ToString(); // user1[2] is "pujkvBFU#kQKeYnabk.com"
In case of you need a part of object, for example:
You have entity Teacher:
public class Teacher
{
public string Mail {get; set;}
public IEnumerable<Course> Courses {get; set;}
public string Name {get; set;}
}
And entity Course:
public class Course
{
public int CurseCode {get; set;}
public string CourseName {get; set;}
}
And you need only "Courses" from "Teacher" entity, you can use:
var db = conection.GetDatabase("school");
var collection = db.GetCollection<Teacher>("teachers"); // Or your collection Name
string mailForSearch="teacher#school.com"; // param for search in linq
var allCoursesBson = collection.Find(x => x.Mail == mailForSearch).Project(Builders<Teacher>.Projection.Include(x => x.Courses).Exclude("_Id")).ToList();
// allCoursesBson is BsonDocument list, then use a first BsonDocument an convert to string for convert to IEnumerable<Courses> type with BsonSerializer.Deserialize
string allCoursesText = resp.FirstOrDefault()[0].ToString();
IEnumerable<Courses> allCourses = BsonSerializer.Deserialize<IEnumerable<Courses>>(allCoursesText);
Now, you have a courses list from taecher and convert BsonDocument answer into "IEnumerable".
Use yield keyword to return data as you want.
public IEnumerable<string> GetMongoFields(string collectionName)
{
var connectionString = ConfigurationManager.ConnectionStrings[DbConfig.GetMongoDb()].ConnectionString;
var databaseName = MongoUrl.Create(connectionString).DatabaseName;
MongoClient client = new MongoClient(connectionString);
var server = client.GetServer();
var db = server.GetDatabase(databaseName);
var collection = db.GetCollection<BsonDocument>(collectionName);
var list = collection.FindAll().ToList();
yield return list.ToJson();
}
I'm having a difficult time understanding my options to return json from a query in my control, as there seems to be many ways to do this. Any clarification would be very much appreciated.
I would like to return json from the following:
public class MyController : ApiController
{
private MyEntities context = new MyEntities();
public IQueryable <string> Get()
{
var query =
from MY_ENTITY_1 in my_entity_1
from MY_ENTITY_2 in my_entity_2
from MY_ENTITY_3 in my_entity_3
where
MY_ENITITY_1.something == MY_ENTITY_2.something
select new
{
Result1 = MY_ENTITY_1.FOO1,
Result2 = MY_ENTITY_2.FOO2,
Result3 = MY_ENTITY_3.FOO3
};
foreach (var myResults in query)
{
Console.WriteLine(myResults);
};
return myResults; // JSON?
}
My understanding is that the ApiController automatically converts returned objects to JSON when those actions are invoked:
public IQueryable <MyGetResult> Get()
{
var query =
from MY_ENTITY_1 in my_entity_1
from MY_ENTITY_2 in my_entity_2
from MY_ENTITY_3 in my_entity_3
where
MY_ENITITY_1.something == MY_ENTITY_2.something
select new MyGetResult
{
Result1 = MY_ENTITY_1.FOO1,
Result2 = MY_ENTITY_2.FOO2,
Result3 = MY_ENTITY_3.FOO3
};
return query;
}
public class MyGetResult
{
public Foo Result1 {get;set;}
public Foo Result2 {get;set;}
public Foo Result3 {get;set;}
}
WebAPI uses a strategy called "Content Negotiation" to determine what data type the caller wants, and automatically serializes the results accordingly.
From ApiController it appears that you are using WebAPI. You don't have to return JSON or XML from your method, instead simply return the object. It is the responsibility of the caller to specify the return data type.
For example, if you browse to your service through IE you will get JSON back, since IE uses JSON as the default return type. If you browse the same URL in Chrome, you will get back XML, since thats the default for Chrome, it depends on the ContentType of the request if it is ContentType: application/json then you will get JSON back.