Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Web API - Entity Framework - 500 Internal Server Error On .Include(param => param.field)

I am currently working on a Web API project with a Database-First method using Entity Framework (which I know is not the most stable of platforms yet), but I am running into something very strange.

When the GET method within my APIController tries to return all records in a DbSet with a LINQ Include() method involved such as this, it will return a 500 error:

// GET api/Casinos
    public IEnumerable<casino> Getcasinos()
    {
            var casinos = db.casinos.Include(c => c.city).Include(c => c.state);
            return casinos.AsEnumerable();
        }

Yet, this method works fine, and returns my data from within my database:

// GET api/States
    public IEnumerable<state> Getstates()
    {
        return db.states.AsEnumerable();
    }

So I have proved in other instances that if it returns the entities without LINQ queries, it works great, yet when there is an Include method used upon the DbContext, it fails.

Of course, trying to find this error is impossible, even with Fiddler, Chrome/Firefox dev tools, and adding in GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;

If anyone has resolved this, it would be nice to know a nice resolution so I can start returning my data! Thanks!:)

P.S. I am using SQL Server 2012

like image 931
Logan B. Lehman Avatar asked Aug 01 '12 04:08

Logan B. Lehman


1 Answers

This is happening due to error in serialization (Json/XML). The problem is you are directly trying to transmit your Models over the wire. As an example, see this:

public class Casino
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual City City { get; set; }
}

public class State
{
    public int ID { get; set; }
    public string Name { get; set; }

    [XmlIgnore]
    [IgnoreDataMember]        
    public virtual ICollection<City> Cities { get; set; }
}

public class City
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual  State State { get; set; }

    [XmlIgnore]
    [IgnoreDataMember]
    public virtual ICollection<Casino> Casinos { get; set; }
}

public class Context : DbContext
{
    public Context()
        : base("Casino")
    {

    }

    public DbSet<Casino> Casinos { get; set; }
    public DbSet<State> States { get; set; }
    public DbSet<City> Cities { get; set; }
}

Pay attention to the XmlIgnore and IgnoreDataMember. You need to restrict avoiding serialization so it doesn't happen in circular manner. Further, the above model will still not work because it has virtual. Remove virtual from everywhere namely City, Cities, Casinos and State and then it would work but that would be inefficient.

To sum up: Use DTOs and only send data that you really want to send instead of directly sending your models.

Hope this helps!

like image 188
TCM Avatar answered Sep 28 '22 04:09

TCM