Failed to serialize the response in Web API with Json

223,404

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;
}

Asp.Net Web API Error: The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'

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();
    }
}
Share:
223,404

Related videos on Youtube

CampDev
Author by

CampDev

Updated on June 13, 2020

Comments

  • CampDev
    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
      mckeejm about 10 years
      What does the value object look like that you are trying to pass to the consumer?
    • Jared Whittington
      Jared Whittington almost 9 years
      Thanks 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
      Edvaldo Silva over 7 years
  • CampDev
    CampDev about 10 years
    When you refer to Models, you want say what I am doing? Return IEnumerable of Users who is a Model.
  • jensendp
    jensendp about 10 years
    You 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
    mckeejm about 10 years
    ncampuzano 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
    codegrid almost 9 years
    What if you are using linq pivot with dynamic columns?
  • Guillaume Raymond
    Guillaume Raymond almost 9 years
    [KnownTypeAttribute(typeof(TestClass))] solved my issue
  • Sonic Soul
    Sonic Soul almost 9 years
    there 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
    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
    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
    Bimal Das over 8 years
    your code will be removed if we update model from database.
  • Md. Alim Ul Karim
    Md. Alim Ul Karim about 8 years
    You 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
    Matthieu about 8 years
    Even 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
    Francisco G almost 8 years
    To avoid overwritten, you can disable lazy load, from edmx properties. It worked for me.
  • Md. Alim Ul Karim
    Md. Alim Ul Karim almost 8 years
    @FranciscoG it works but it gets lost if we remove edmx and regenerate .
  • Md. Alim Ul Karim
    Md. Alim Ul Karim almost 8 years
    @BimalDas try this youtube.com/… . It will not remove
  • jacktric
    jacktric over 7 years
    Wow, it worked for me. But why? What the ProxyCreationEnabled property does?
  • Jacob
    Jacob about 7 years
    Some explanations about what this code does and its implications would be welcomed.
  • RK_Aus
    RK_Aus over 6 years
    Thank I was facing the similar problem, this answer helped me to solve the issue.
  • Jav_1
    Jav_1 over 6 years
    Works great thanks!, Could you explain better why do we have to remove the Xml Formatter to make it work?
  • NH.
    NH. over 6 years
    What 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
    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
    Waleed A. Elgalil over 6 years
    worked with me but what this code ? i noted also that all sub classes retrieved with null !!
  • Dr. MAF
    Dr. MAF over 5 years
    It works for me. No need to add using System.Data.Entity; to global.asax. Thank you.
  • TarakPrajapati
    TarakPrajapati over 5 years
    Thanks 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
    Arun Prasad E S almost 5 years
    thanks a lot. don't know what this does to security though.
  • James
    James almost 5 years
    Phrased 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
    TheKrogrammer almost 5 years
    You deserve a Medal.
  • Hemant Ramphul
    Hemant Ramphul over 4 years
    It works. Simple add code above on Global.asax, thats all, No need to import using System.Data.Entity;
  • LosManos
    LosManos over 4 years
    There 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".