Failed to serialize the response in Web API with Json
Solution 1
When it comes to returning data back to the consumer from Web Api (or any other web service for that matter), I highly recommend not passing back entities that come from a database. It is much more reliable and maintainable to use Models in which you have control of what the data looks like and not the database. That way you don't have to mess around with the formatters so much in the WebApiConfig. You can just create a UserModel that has child Models as properties and get rid of the reference loops in the return objects. That makes the serializer much happier.
Also, it isn't necessary to remove formatters or supported media types typically if you are just specifying the "Accepts" header in the request. Playing around with that stuff can sometimes make things more confusing.
Example:
public class UserModel {
public string Name {get;set;}
public string Age {get;set;}
// Other properties here that do not reference another UserModel class.
}
Solution 2
If you are working with EF, besides adding the code below on Global.asax
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Dont`t forget to import
using System.Data.Entity;
Then you can return your own EF Models
Simple as that!
Solution 3
Given right answer is one way to go, however it is an overkill when you can fix it by one config settings.
Better to use it in the dbcontext constructor
public DbContext() // dbcontext constructor
: base("name=ConnectionStringNameFromWebConfig")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
Solution 4
Add this code to global.asax
below on Application_Start
:
Update from .Ignore
to .Serialize
. It must work.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Solution 5
public class UserController : ApiController
{
Database db = new Database();
// construction
public UserController()
{
// Add the following code
// problem will be solved
db.Configuration.ProxyCreationEnabled = false;
}
public IEnumerable<User> GetAll()
{
return db.Users.ToList();
}
}
Related videos on Youtube
CampDev
Updated on June 13, 2020Comments
-
CampDev almost 4 years
I am working with ASP.NET MVC 5 Web Api. I want consult all my users.
I wrote
api/users
and I receive this:"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'"
In WebApiConfig, already I added these lines:
HttpConfiguration config = new HttpConfiguration(); config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType); config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
But it still doesn't work.
My function for return data is this:
public IEnumerable<User> GetAll() { using (Database db = new Database()) { return db.Users.ToList(); } }
-
mckeejm about 10 yearsWhat does the value object look like that you are trying to pass to the consumer?
-
Jared Whittington almost 9 yearsThanks so much! Just fyi - I think that should read: using (Database db = new Database ()) { List<UserModel> listOfUsers = new List<UserModel>(); foreach(var user in db.Users) { UserModel userModel = new UserModel(); userModel.FirstName = user.FirstName; userModel.LastName = user.LastName; listOfUsers.Add(userModel); } IEnumerable<UserModel> users = listOfUsers; return users; } ..as the results were all returning the same values.
-
Edvaldo Silva over 7 yearsPossible duplicate of failed to serialize the response in Web API
-
-
CampDev about 10 yearsWhen you refer to Models, you want say what I am doing? Return IEnumerable of Users who is a Model.
-
jensendp about 10 yearsYou are returning an Entity. An entity refers to an object in the DB that can be retrieved by a unique id. You are returning all the User entities from your database. I'm suggesting that you create a new class called "UserModel" and for each of the User entities you get from the database, create a new instance of the data model class populated with the necessary info you want to expose. The return an IEnumerable of UserModel objects as opposed to User entities. Make sure the model Properties don't refer to instances of the UserModel class. That is what is getting you into this problem.
-
mckeejm about 10 yearsncampuzano is correct, you don't want to return auto generated entities. If you were using stored procedures for database access the separation would be more clear. You would need to have generated a C# value object and mapped values from the IDataReader to the value object. Since you're using EF, there are classes being generated for you, but those are special EF classes that know more then value objects do. You should only return "dumb" value objects to your client.
-
codegrid almost 9 yearsWhat if you are using linq pivot with dynamic columns?
-
Guillaume Raymond almost 9 years[KnownTypeAttribute(typeof(TestClass))] solved my issue
-
Sonic Soul almost 9 yearsthere are more elegant ways to handle the translation for you so that you don't have to maintain every property .. AutoMapper and ValueInjecter are 2 notable ones
-
Donald N. Mafa over 8 years@jensendp using your suggested method of implementing the model objects, at which point do you map the entity to the model. Is this done in your Api controller or is it done in a separate layer?
-
ben over 8 years@Donny If you're using DBContext or a Repository in your controller that is returning entities back from the DB, then you can just map the objects to models (a DTO for example) in the controller... but I prefer to have the controller call a service that returns the model/DTO. Check out AutoMapper - great tool for handling mapping.
-
Bimal Das over 8 yearsyour code will be removed if we update model from database.
-
Md. Alim Ul Karim about 8 yearsYou can separate it easily by removing the .tt files and have disjoint context. Every time you generate model just add new class in the place. @Brimal : You can follow this youtube.com/watch?v=yex0Z6qwe7A
-
Matthieu about 8 yearsEven if it might help for EF, the solution is not specific to EF, and work also with other kind of models. The using doesn't seem to be necessary in Global.asax. Was it intended for the controllers?
-
Francisco G almost 8 yearsTo avoid overwritten, you can disable lazy load, from edmx properties. It worked for me.
-
Md. Alim Ul Karim almost 8 years@FranciscoG it works but it gets lost if we remove edmx and regenerate .
-
Md. Alim Ul Karim almost 8 years@BimalDas try this youtube.com/… . It will not remove
-
jacktric over 7 yearsWow, it worked for me. But why? What the ProxyCreationEnabled property does?
-
Jacob about 7 yearsSome explanations about what this code does and its implications would be welcomed.
-
RK_Aus over 6 yearsThank I was facing the similar problem, this answer helped me to solve the issue.
-
Jav_1 over 6 yearsWorks great thanks!, Could you explain better why do we have to remove the Xml Formatter to make it work?
-
NH. over 6 yearsWhat a pain, though! What is the point of the entire LINQ-to-SQL schenangains if we can't even use the classes it auto-generates?!?!
-
jensendp over 6 years@NH. You can absolutely use the aforementioned shenanigans, but everything has it's place. The "entities" provided by access to the Data Layer should typically stay in the Data Layer. Anything that wants to use this data within the Business Layer of the application will typically use the "entities" in a transformed form as well (Domain Objects). And then the data that is returned to and input from the user will typically be another form as well (Models). Agreed it can be tedious to do this type of transformation everywhere, but that is where tools like AutoMapper really come in handy.
-
Waleed A. Elgalil over 6 yearsworked with me but what this code ? i noted also that all sub classes retrieved with null !!
-
Dr. MAF over 5 yearsIt works for me. No need to add using System.Data.Entity; to global.asax. Thank you.
-
TarakPrajapati over 5 yearsThanks Suman. I was having the same issue. I was testing my web API & stuck with this issue. your solution resolves the issue. thanks a lot.
-
Arun Prasad E S almost 5 yearsthanks a lot. don't know what this does to security though.
-
James almost 5 yearsPhrased like this, one could almost think that every one who answered this post before was dumb ;)… Well, I seriously doubt they were, so it probably means that this solution was simply not applicable when the question was asked, back in 2015… I don't know much about that syntax myself, but I have the feeling that either it is relatively new, or there might be some drawbacks to it that makes it unusable in certain use cases. I have the feeling that your solution could be useful to future readers reaching this question, but it would certainly help if you'd clarify its limitations.
-
TheKrogrammer almost 5 yearsYou deserve a Medal.
-
Hemant Ramphul over 4 yearsIt works. Simple add code above on Global.asax, thats all, No need to import using System.Data.Entity;
-
LosManos over 4 yearsThere is no need to add the json serialiser (at least in my case) but removing the Xml formatting was needed. I guess the xml serialiser can't serialise anonymous types and by removing it the result is serialised as json. If my guess is correct one would be able to get data out of the controller by asking for MIME type "application/json".