MongoDb C# failed to serialize the response - c#

Class (Entity)
public class Entity
{
public ObjectId Id { get; set; }
public Entity()
{
Id = ObjectId.GenerateNewId();
}
}
Class (Member)
public class Member : Entity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string MobileNumber { get; set; }
}
Action
public dynamic Get()
{
var response = UnitOfWork.MemberRepository.GetMembers();
return response;
}
I'm building a API using .NET WebAPI and using mongodb as a datastore, I'm have some troubles serializing the responding object from the database.
Can't understand why, search the internet a while and found similar problems with no solutions. Either I'm a bad google searcher or there answer is hidden somewhere deep:)
Full stack trace: http://pastie.org/8389787

This is little guessing, but the code really isn't too telling.
I'm pretty sure this is because the C# Mongo driver's BsonDocument exposes a ton of properties like AsBoolean, AsInt, AsString, etc. Calling those getters on data that isn't convertible to the respective type causes an exception. While I don't see them in the stack trace, that might be a compiler optimization.
One solution is to make the code strongly-typed (if it isn't already). I don't know what UnitOfWork.MemberRepository.GetMembers(); is, but it hides what you're doing and it's also not clear what it returns. You're losing a lot of the advantages of the C# driver. The Collection<T> class is pretty much a repository pattern already by the way.
A cleaner approach (they aren't mutually exclusive) is to not serialize the database object to the outside world, but use DTO for the WebAPI side and translate between them, for instance using AutoMapper. I would always do this, because you're throwing an object that might be decorated with DB-Attributes in a serializer you don't know - that could lead to all sorts of problems. Also, you often want to hide certain information from the outside, or make it read-only.
Another option is to use ServiceStack.Text as a JSON-serializer instead, which tends to cause less trouble in my experience.

Related

How to serialize circular referenced ef poco class using protobuf-net

I'm using marc gravell's protobuf-net and ef core in my project.
long story short, I'm using Inverseproperty attribute on my POCO class which causes a circular reference when I fetch results from database which causes me trauble when I try to serialize data using protobuf net.
I'm currenyl serializing data with Jsonconvert by setting ReferenceLoopHandling = ReferenceLoopHandling.Ignore and returning a json string to the client to keep the app in a working state but do not want to use this method as it doesnot make any sense.
I would like to know if it is possible to either prevent EF core generating circular reference when using Inverseproperty attribute or if protobuf-net has an ignore referenceloop handling feature when serializing data..
a simplified version of my poco class is like this:
[ProtoContract]
[Table("CATEGORIES_M")]
public class CATEGORIES_M
{
public CATEGORIES_M()
{
CATEGORIES_M_COLLECTION = new HashSet<CATEGORIES_M>();
//Product = new HashSet<Product>();
CM_DATE = DateTime.Now;
}
[Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[ProtoMember(1)]
public int CM_ROWID { get; set; }
[ProtoMember(2)]
public string CM_NAME { get; set; }
[ProtoMember(3)]
public int? CM_PARENT_REFNO { get; set; }
[ProtoMember(4)]
[ForeignKey(nameof(CM_PARENT_REFNO))]
[InverseProperty(nameof(CATEGORIES_M_COLLECTION))]
public CATEGORIES_M CATEGORIES_M_PARENT { get; set; }
[ProtoMember(5)]
[InverseProperty(nameof(CATEGORIES_M_PARENT))]
public ICollection<CATEGORIES_M> CATEGORIES_M_COLLECTION { get; set; }
}
any help is appreciated
Protobuf-net does not have good support for this scenario. V2 has some limited reference tracking capabilities, but these are deprecated in V3 because it caused more problems than it solved. My suggestions, as the library author:
serialize a simple tree model, and build your real model afterwards from it, or
use a different tool
Backreferences (parent level) can be tagged with [ProtoIgnore] to avoid circular references. That might change the behavior as a client might expect values there. Though, usually the client has the parent objects already and you might just need a key here. If that's the case, add an additional serializable property for the key value and mark as [ProtoMember(nn)], then.
Hint: Write test cases and use the Serialize class's static methods to check the behavior and get useful exceptions before trying to debug your server code.

Return only a subset of properties of an object from an API

Say I have a database in which I am storing user details of this structure:
public class User
{
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
}
I have a data access layer that works with this that contains methods such as GetById() and returns me a User object.
But then say I have an API which needs to return a users details, but not sensitive parts such as the PasswordHash. I can get the User from the database but then I need to strip out certain fields. What is the "correct" way to do this?
I've thought of a few ways to deal with this most of which involve splitting the User class into a BaseClass with non sensitive data and a derived class that contains the properties I would want kept secret, and then converting or mapping the object to the BaseClass before returning it, however this feels clunky and dirty.
It feels like this should be a relatively common scenario, so am I missing an easy way to handle it? I'm working with ASP.Net core and MongoDB specifically, but I guess this is more of a general question.
It seems for my purposes the neatest solution is something like this:
Split the User class into a base class and derived class, and add a constructor to copy the required fields:
public class User
{
public User() { }
public User(UserDetails user)
{
this.UserId = user.UserId;
this.Name = user.Name;
this.Email = user.Email;
}
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public class UserDetails : User
{
public string PasswordHash { get; set; }
}
The data access class would return a UserDetails object which could then be converted before returning:
UserDetails userDetails = _dataAccess.GetUser();
User userToReturn = new User(userDetails);
Could also be done using AutoMapper as Daniel suggested instead of the constructor method. Don't love doing this hence why I asked the question but this seems to be the neatest solution and requires the least duplication.
There are two ways to do this:
Use the same class and only populate the properties that you want to send. The problem with this is that value types will have the default value (int properties will be sent as 0, when that may not be accurate).
Use a different class for the data you want to send to the client. This is basically what Daniel is getting at in the comments - you have a different model that is "viewed" by the client.
The second option is most common. If you're using Linq, you can map the values with Select():
users.Select(u => new UserModel { Name = u.Name, Email = u.Email });
A base type will not work the way you hope. If you cast a derived type to it's parent type and serialize it, it still serializes the properties of the derived type.
Take this for example:
public class UserBase {
public string Name { get; set; }
public string Email { get; set; }
}
public class User : UserBase {
public string UserId { get; set; }
public string PasswordHash { get; set; }
}
var user = new User() {
UserId = "Secret",
PasswordHash = "Secret",
Name = "Me",
Email = "something"
};
var serialized = JsonConvert.SerializeObject((UserBase) user);
Notice that cast while serializing. Even so, the result is:
{
"UserId": "Secret",
"PasswordHash": "Secret",
"Name": "Me",
"Email": "something"
}
It still serialized the properties from the User type even though it was casted to UserBase.
If you want ignore the property just add ignore annotation in you model like this, it will skip the property when model is serializing.
[JsonIgnore]
public string PasswordHash { get; set; }
if you want ignore at runtime(that means dynamically).there is build function avilable in Newtonsoft.Json
public class User
{
public string UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
//FYI ShouldSerialize_PROPERTY_NAME_HERE()
public bool ShouldSerializePasswordHash()
{
// use the condtion when it will be serlized
return (PasswordHash != this);
}
}
It is called "conditional property serialization" and the documentation can be found here. hope this helps
The problem is that you're viewing this wrong. An API, even if it's working directly with a particular database entity, is not dealing with entities. There's a separation of concerns issue at play here. Your API is dealing with a representation of your user entity. The entity class itself is a function of your database. It has stuff on it that only matters to the database, and importantly, stuff on it that does not matter to your API. Trying to have one class that can satisfy multiple different applications is folly, and will only lead to brittle code with nested dependencies.
More to the point, how are you going to interact with this API? Namely, if your API exposes your User entity directly, then any code that consumes this API either must take a dependency on your data layer so it can access User or it must implement its own class representing a User and hope that it matches up with what the API actually wants.
Now imagine the alternative. You create a "common" class library that will be shared between your API and any client. In that library, you define something like UserResource. Your API binds to/from UserResource only, and maps that back and forth to User. Now, you have completely segregated your data layer. Clients only know about UserResource and the only thing that touches your data layer is your API. And, of course, now you can limit what information on User is exposed to clients of your API, simply by how you build UserResource. Better still, if your application needs should change, User can change without spiraling out as an API conflict for each consuming client. You simply fixup your API, and clients go on unawares. If you do need to make a breaking change, you can do something like create a UserResource2 class, along with a new version of your API. You cannot create a User2 without causing a whole new table to be created, which would then spiral out into conflicts in Identity.
Long and short, the right way to go with APIs is to always use a separate DTO class, or even multiple DTO classes. An API should never consume an entity class directly, or you're in for nothing but pain down the line.

Entity Framework DB first issues loading related entities (ASP.NET web api)

I've been looking for answers for this relatively simple task but with no success. So I thought I'd ask my question here. I have got a simple database with two tables, Books and Authors.
I got my models generated by the ADO.NET entity data model. This is the auto-generated Books model:
public partial class Book
{
public int BookID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int ISBN { get; set; }
public int AuthorID { get; set; }
public virtual Author Author { get; set; }
}
And this is the auto-generated Authors model:
public partial class Author
{
public Author()
{
this.Books = new HashSet<Book>();
}
public int AuthorID { get; set; }
public string Name { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
And this is a part of the controller, the method for getting a list of all the books in JSON format.
// api/books
public IQueryable<Book> GetBooks()
{
// return db.Books.Include(x => x.Authors); Don't work
return db.Books;
}
This is my JS for calling the endpoint:
$.getJSON("api/books")
.done(function (data) {
console.log(data);
})
.fail(function (xhr) { console.log(xhr.responseText) });
Nothing fancy, just trying to make a GET request and receiving a list of all the books and their related authors.
This is a portion of the error message:
{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Self referencing loop detected for property 'Author' with type 'System.Data.Entity.DynamicProxies.Author_5968F94A1BBB745A30D62CD59D0AC5F96A198B3F16F0EA2C2F61575F70034886'. Path '[0].Books[0]'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException","StackTrace":"
I have tried preserving object references in JSON but that mangles the response. Is that is the only option?
If you examine the inner exception it says:
Self referencing loop detected for property 'Author'
This tells you that your Author class references back to the parent (i.e. Books or vice versa).
In your web api config (App_Start/WebApiConfig.cs), add this:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Prevent "Self referencing loop detected" error occurring for recursive objects
var serializerSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
config.Formatters.JsonFormatter.SerializerSettings = serializerSettings;
}
}
This tells JSON.NET to ignore nested objects referring back to the parent object
adaam's answer is 100% correct but I thought I'd chime in with a bit of advice, but it's too long to fit in a comment so here goes.
Directly serialising Entity Framework objects is generally not a great idea; it's better to use simple DTO-style objects for passing data back to clients.
Of course this is just advice and YMMV :)
The benefits of using DTOs include
Proper decoupling from your Entity Framework objects in your Controllers (you could create a Repository abstraction and use that in your controller, meaning your controller is free from a dependency on Entity Framework and thus more testable)
Simpler serialization control - with Entity Framework you will have difficulty trying to control what public properties are send across the wire to clients when the Entity Framework proxy is directly serialized; typically in DB First the declarations for these properties are in auto-generated files that are re-written each time your edmx changes; threfore it becomes painful to have to maintain non-serialization attributes on the properties you don't want sent across the wire (e.g [IgnoreDataMember], etc.)
If you're planning on accepting models via POST, PUT, etc, then you'll rapidly find that it is a pain (if not impossible) to effectively serialize "inward" directly to the Entity Framework proxies so you'll have to write mapping code anyway; by using a DTO approach you accept that you have to map up-front.
Circular references don't happen therefore you never need to worry about it and more importantly, you don't pay the cost of ignoring it (albeit minor, but the serializer has to do some work to avoid these references)
You can easily perform extra transformations, for example flattening, to better suit the client and/or hide details you don't want sent across the wire.
Example
public class BookDTO
{
public int BookID {get;set;}
public string Title {get;set;}
public string Description {get;set;}
public int ISBN {get;set;}
public string AuthorName{get;set;}
}
public HttpResponseMessage GetBooks()
{
//ideally you'd be using a repository abstraction instead of db directly
//but I want to keep this simple.
var books = db.Books.Select(
book=>new BookDTO(){
BookID=book.BookID,
Title=book.Title,
Description=book.Description,
ISBN=book.ISBN,
AuthorName=book.Author.Name //<-flattening
});
return Request.CreateResponse(HttpStatusCode.OK, books);
}
This produces an array of nice, flat objects for the client to consume without having to expose for example the AuthorID which might to be an internal concept you don't particularly want clients to know.
Once you get the hang of it, you can then look at using something like Automapper which will greatly reduce the maintenance burden, and allow you to perform inline projection in your queries.
It is always best to create your own custom models while returning the data but you just want to use Entity Framework classes then along with ignoring refrenceLoopHandeling you would need disable ProxyCreation from you Entity Model.
Follow these steps :
Step 1 : Like adaam described Put his in WebApiConfig register function:
// Prevent "Self referencing loop detected" error occurring for recursive objects
var serializerSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
config.Formatters.JsonFormatter.SerializerSettings = serializerSettings;
Step 2 : Which is most important in my case with latest EF to disable Proxy from EF Contaxt.
Goto: [FILE].edmx file then your [FILE].Context.cs
and add the line below in your constructor..
Configuration.ProxyCreationEnabled = false;
Now you won't have related class results any more..

Converting JSON data into an object

I am very new to this.Pardon me if I make any mistakes.
I have data in JSON form.Can I read this data directly and use it in C# code ?
From what I understood from reading up on the internet,I think I have to convert it into an object form to use the data.Am I right ?
If yes,Then I saw this method to convert as below :
string data = JsonConvert.DeserializeObject<string>(getmyissue());
getmyissue is the function which returns a string which has data in json format.
This gives me an exception saying
"Error reading string.Unexpected Token."
Can someone guide me where am I going wrong ?
EDIT
MyIssue.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Example
{
public class MyIssue
{
public string name{get;set;}
public string description { get; set; }
public string created { get;set; }
public string updated{get;set;}
public string displayName { get; set; }
}
}
Program.cs
MyIssue obj=null;
try
{
obj = JsonConvert.DeserializeObject<MyIssue>(manager.getmyissue());
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("Name: "+obj.name);
The easiest way to de-serialize Json in a C#/.NET program is to use the brilliant NewtonSoft JSON library.
There are numerous ways to do it, but I have to admit that the NS libs just get on with the task (and no I'm not a member of the team etc, just an Avid User :-) ).
To do what you want for example, if you had:
{'Name': 'A person', 'AllowAccess': true,'Areas': ['Sales','Admin']}
You would first build an object to represent it as follows:
public MyObject
{
public string Name { get; set; }
public bool AllowAccess { get; set; }
public List<string> Areas { get; set; }
}
Once you've done this, it's a simple case of just doing the following:
string jsonString = "// Your json formated string data goes here";
MyObject myObject = JsonConvert.DeserializeObject<MyObject>(jsonString);
The properties in your object should at that point, reflect the properties in the JSON data you sent to it.
You will of course need to add the NS JSON Libs to your project, either via NuGet or Manually, which ever is easier for you, everything you need to know about that is here:
How to install JSON.NET using NuGet?
The really good thing about NS JSON however is not the ease of use, but the fact that it can also do dynamic de-serialization.
This comes in handy if you've no idea what to expect in the JSON you receive, and so don't know ahead of time how to construct an object to hold the results.
Rather than repeat what others have said however, you can find more information of doing things dynamically in this stack overflow post:
Deserializing JSON using JSon.NET with dynamic data
Update
Looking at your JSON data you have way more fields/properties in there than your trying to parse, and none of the libraries in common use (To the best of my knowledge) will pick and choose the fields to copy, you either have an object that represents them all, or not at all, the later of which I believe is the problem your facing.
I have a rather neat "JSON" plug in for chrome, than when given a chunk of JSON data formats the output for me nicely and makes it easy to read, it also helps massively when defining objects, allowing you to see the full nested structure of your data, here are a series of images showing your JSON data formatted using this plugin:
I'm not going to paste anymore images in, but that goes on for another 4 pages!!
Now, some extra information that may help you.
I know from experience (I had to write a parser in PHP for these Jira webhooks) that within the Jira control panel, you can configure your webhooks to ONLY return the information your interested in.
Right now, it looks like you've just told the system to dump everything, for every event that you've hooked too (Which looks like - all of them), it's been a while since I did any work with these, but as well as a global webhook, you also have individual webhooks, which only fire on specific events and produce JSON data that's very much smaller than what your dealing with here.
I'd therefore advise you, to take a look in your Jira control panel (Or ask your Admin/Lead Dev/etc to take a look) and seriously trim down as much of that data as you can.
Further more, if memory serves me right, you can also make various web API calls to the Jira service to get this info too, and in that case you can tell the API exactly what your interested in, meaning it will only return the fields you need.
Right now, your main problem is the sheer volume of data your trying to deal with, if you tackle that problem, you'll find the issues surrounding the code your trying to get working will be very much easier to deal with.
Update 2
Just to make it clearer what I mean by using a "dynamic" type to get at your data, you would use something like the following code:
string jsonString = "// Your json formated string data goes here";
var result = JsonConvert.DeserializeObject<dynamic>(jsonString);
The difference here is that your using the C# dynamic type rather than a strongly typed object of your own design.
"dynamic" is useful, because it's kind of like having an empty object, and then having the properties added for you, without you having to define it.
What this essentially means is that, if you pass in the following JSON:
{'Name': 'A person', 'AllowAccess': true,'Areas': ['Sales','Admin']}
You'll end up with a dynamic object that looks like:
result = dynamic
{
public string Name { get; set; }
public bool AllowAccess { get; set; }
public List<string> Areas { get; set; }
}
thus:
result.Name
will get you access to the contents of the Name field and so on.
If your JSON was then changed to become:
{'Name': 'A person', 'AllowAccess': true,'Areas': ['Sales','Admin'], 'Location': 'The World' }
Your object would magically have a property called 'Location' containing the value 'The World' which you could access using:
result.Location
In your case, this would allow you to define your concrete object EG:
public MyObject
{
public string Name { get; set; }
public string Email { get; set; }
}
and then do something like the following (Assuming that your inbound JSON had properties in called Name & Email):
string jsonString = "// Your json formated string data goes here";
var result = JsonConvert.DeserializeObject<dynamic>(jsonString);
MyObject myObject = new MyObject
{
Name = result.Name,
Email = result.Email
}
You'd then discard the dynamic object as you'd not need it anymore.
The BIG problem your going to have with this approach is maintaining your models. Manual property assignment is all fine and dandy for a small handful of properties and objects, but it soon becomes a huge maintenance nightmare as your software grows.
I'm sure it doesn't take much to imagine what kind of task you'd be facing if you had to do this for 100 different JSON requests and 50 different types of objects.
For this reason, using this approach you should really consider using some kind of mapping technology such as "AutoMapper", however for now I'm going to advise you leave that until later before you start researching it, as it'll not help you to be clear about dealing with this dynamic approach.
The JSON you get is already a string, so converting it to string doesn't make much sense. You need to create classes that reflect the structure represented by the JSON string.
For example to convert the following JSON into objects, you'd have to create a class for the users:
{"user":{"name":"asdf","teamname":"b","email":"c","players":["1","2"]}}
public class User
{
public string name { get; set; }
public string teamname { get; set; }
public string email { get; set; }
public Array players { get; set; }
}
Then you should be able to use this:
JavaScriptSerializer jss= new JavaScriptSerializer();
List<User> users = jss.Deserialize<List<User>>(jsonResponse);

ResponstDTO with complex Property in ServiceStack

Havin a Response with a complex property, i want to to map to my responseDTO properly. For all basic types it works out flawlessly.
The ResponseDTO looks like this:
public class ResponseDto
{
public string Id {
get;
set;
}
public struct Refs
{
public Genre GenreDto {
get;
set;
}
public Location LocationDto {
get;
set;
}
}
public Refs References {
get;
set;
}
}
Genre and Location are both for now simple classes with simple properties (int/string)
public class GenreDto {
public string Id {
get;
set;
}
public string Name {
get;
set;
}
}
Question:
Is there any way, without changing/replacing the generic unserializer ( and more specific example) (in this example JSON ) to map such complex properties?
One specific difference to the GithubResponse example is, that i cant use a dictionry of one type, since i have different types under references. Thats why i use a struct, but this seems not to work. Maybe only IEnumerable are allowed?
Update
There is a way using lamda expressins to parse the json manually github.com/ServiceStack/ServiceStack.Text/blob/master/tests/ServiceStack.Text.Tests/UseCases/CentroidTests.cs#L136 but i would really like to avoid this, since the ResponseDTO becomes kinda useless this way - since when writing this kind of manual mapping i would no longer us Automapper to map from ResponseDto to DomainModel - i though like this abstraction and "seperation".
Thanks
I used lambda expressions to solve this issue, a more complex example would be
static public Func<JsonObject,Cart> fromJson = cart => new Cart(new CartDto {
Id = cart.Get<string>("id"),
SelectedDeliveryId = cart.Get<string>("selectedDeliveryId"),
SelectedPaymentId = cart.Get<string>("selectedPaymentId"),
Amount = cart.Get<float>("selectedPaymentId"),
AddressBilling = cart.Object("references").ArrayObjects("address_billing").FirstOrDefault().ConvertTo(AddressDto.fromJson),
AddressDelivery = cart.Object("references").ArrayObjects("address_delivery").FirstOrDefault().ConvertTo(AddressDto.fromJson),
AvailableShippingTypes = cart.Object("references").ArrayObjects("delivery").ConvertAll(ShippingTypeDto.fromJson),
AvailablePaypmentTypes = cart.Object("references").ArrayObjects("payment").ConvertAll(PaymentOptionDto.fromJson),
Tickets = cart.Object("references").ArrayObjects("ticket").ConvertAll(TicketDto.fromJson)
});
So this lamda exprpession is used to parse the JsonObject response of the request and map everything inside, even nested ressources. This works out very well and flexible
Some time ago i stumbled upon a similar problem. Actually ServiceStack works well with complex properties. The problem in my scenario was that i was fetching data from a database and was passing the objects returned from the DB provider directly to ServiceStack. The solution was to either create DTOs out of the models returned by the DB provider or invoke .ToList() on those same models.
I'm just sharing some experience with SS but may be you can specify what's not working for you. Is there an exception thrown or something else.

Categories

Resources