Receiving 500 internal server error even though I receive data from LINQ

asp.net-web-api c# entity-framework-6 https

Question

StackOverflow.

The issue I am having today is when I send a get request to localhost:xxxxx trying to obtain a singular food item by ID, I receive a 500 internal server error.

What I do not understand about this is, I went through the code in debugging and it shows that it finds the item from my database with all the information it needs, but when it is sending it in a "OK(food)", I receive a 500 internal service error even though it has the information.

I am pretty new to web api, so some explanation would be appreciated. I am using Visual Studio 2015, Entity Frame Work 6, and a SQL Management Server DB.

I am sorry for posting links, it says I need 10 reputation to post images

protected void Page_Load(object sender, EventArgs e)
    {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("http://localhost:63591/");
            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync("api/foods/" + Request.QueryString["ID"]).Result;

            if (response.IsSuccessStatusCode)
            {
                string foodstring = response.Content.ReadAsStringAsync().Result;
                Food editFood = JsonConvert.DeserializeObject<Food>(foodstring);
                EditFoodName.Text = editFood.FoodName;
                EditCalories.Text = editFood.Calories.ToString();
                EditNotes.Text = editFood.Notes;
            }
    }

    [ResponseType(typeof(Food))]
    public IHttpActionResult GetFood(int id)
    {
        Food food = db.Foods.Find(id);
        if (food == null)
        {
            return NotFound();
        }

        return Ok(food);
    }



public partial class Food
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Food()
    {
        this.MealFoods = new HashSet<MealFood>();
    }

    public int FoodID { get; set; }
    public string FoodName { get; set; }
    public int Calories { get; set; }
    public string Notes { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<MealFood> MealFoods { get; set; }
}

https://i.imgur.com/8h6EaZM.png

https://i.imgur.com/YkD8Ijp.png

1
1
2/5/2018 7:37:23 AM

Accepted Answer

Instead work directly with db.Foods, it's better to create your own public object and manage your query with Linq or if you persist to work directly with the object created by EntityFramework you must disable lazy-loading and proxy generation. Using your own implementation, the method should be like this:

[ResponseType(typeof(PseudoFood))]
public IHttpActionResult GetFood(int id)
{
    //Food food = db.Foods.Find(id);
    PseudoFood food = (from a in db.Foods
                       where a.FoodID == id
                       select new PseudoFood()
                       {
                           FoodName = a.FoodName,
                           FoodID = a.FoodID,
                           Calories = a.Calories,
                           Notes = a.Notes
                       }).FirstOrDefault();

    if (food == null)
    {
        return NotFound();
    }

    return Ok(food);
}

Attention for the [ResponseType(typeof(PseudoFood))], that use PseudoFood instead Food.

0
2/6/2018 11:34:54 PM

Popular Answer

In the action GetFood you specified that the return type is Food. By default the EntityFramework generate proxy objects around your entities for lazy-loading.

Meaning that the line:

 Food food = db.Foods.Find(id);

Will not return a Food object, but a dynamic subclass of food. This can also be seen in the error you posted in the comments, stating that the action is not expecting type Food_31C9E7DC... to be returned.


There are 3 ways to fix this:

  • Simply disable proxy generation in your EntityContext,
  • Remove virtual properties (lazy-loading properties) on your entity (EF will skip proxy generation if its not needed),
  • Map your EntityObject into a DataContract object and return it.

See here for more info on proxies.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow