【问题标题】:Receiving 500 internal server error even though I receive data from LINQ即使我从 LINQ 接收数据,仍收到 500 内部服务器错误
【发布时间】:2018-07-15 00:26:48
【问题描述】:

堆栈溢出。

我今天遇到的问题是,当我向 localhost:xxxxx 发送一个 get 请求,试图通过 ID 获取单个食物项目时,我收到 500 内部服务器错误。

对此我不明白的是,我在调试中检查了代码,它显示它从我的数据库中找到了包含它需要的所有信息的项目,但是当它以“OK(food) ",即使它有信息,我也会收到 500 内部服务错误。

我对 web api 还很陌生,所以我将不胜感激。我正在使用 Visual Studio 2015、Entity Frame Work 6 和 SQL Management Server DB。

很抱歉发布链接,它说我需要 10 声望才能发布图片

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

【问题讨论】:

  • 在调试时是否提供了有关 500 异常的任何额外信息?
  • 没什么。我之前遇到过这个问题,并被告知要创建一个伪类来解决一个关于从数据库中获取所有食物的错误,但当时我什至无法连接到数据库。此时我可以,但即使它有信息,它也会返回 500。
  • 看起来你是从 asp.net 页面调用这个 api 的。您可以尝试直接从浏览器/提琴手调用它吗:localhost:63591/api/foods? id=123
  • 我的意思是,我可以,但它不会显示任何东西,因为我试图在 asp.net 上显示它。
  • 我不确定我是否在关注。它只是说,这个 XML 文件似乎没有任何与之关联的样式信息。文档树如下所示。 i.imgur.com/A5cQwcS.png

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


【解决方案1】:

在操作GetFood 中,您指定返回类型为Food。默认情况下,EntityFramework 会在您的实体周围生成代理对象以进行延迟加载。

意思是行:

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

不会返回 Food 对象,而是食物的动态子类。这也可以在您在 cmets 中发布的错误中看到,指出该操作不期望返回类型 Food_31C9E7DC...


有 3 种方法可以解决此问题:

  • 只需在 EntityContext 中禁用代理生成,
  • 删除实体上的虚拟属性(延迟加载属性)(如果不需要,EF 将跳过代理生成),
  • 将您的 EntityObject 映射到 DataContract 对象并返回它。

See here for more info on proxies.

【讨论】:

  • 我尝试禁用代理并删除虚拟,但没有帮助。我决定返回并删除我的自定义 poco 类,并且当我最初检索所有食物时,我得到了 stackoverflowexception。
  • @JonWisniewski 您是否在 EntityContext 的构造函数中禁用了代理生成?如果您的序列化程序正在通过具有循环引用的导航属性,则可能会发生堆栈溢出。
  • 我正在使用名为 MealFood 的食物和膳食连接表。是的,我确实在构造函数中禁用了它。
  • 有人告诉我,因为 Food 有 MealFood 并且 MealFood 有对 Food 的引用,所以它不能被序列化。
  • @JonWisniewski 奇怪的是它仍在创建代理,根据文档它不应该这样做。您可以删除 ResponseType 属性,禁用类型验证。这应该可以防止它抛出异常,但您可能仍然会得到一个 stackoverflowexception,因为它很可能包含一个循环引用。至于序列化,可以序列化,只是不使用默认设置(或全部设置)。您需要检查是否可以指示序列化程序忽略您的导航属性。
【解决方案2】:

与其直接使用 db.Foods,不如创建自己的公共对象并使用 Linq 管理查询,或者如果您坚持直接使用 EntityFramework 创建的对象,则必须禁用延迟加载和代理生成。 使用你自己的实现,方法应该是这样的:

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

注意 [ResponseType(typeof(PseudoFood))],它使用 PseudoFood 代替 Food。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多