C# 接收500个内部服务器错误,即使我从LINQ接收数据

C# 接收500个内部服务器错误,即使我从LINQ接收数据,c#,asp.net-web-api,https,entity-framework-6,C#,Asp.net Web Api,Https,Entity Framework 6,堆栈溢出 我今天遇到的问题是,当我向localhost发送get请求时:xxxxx试图通过ID获取单个食物项目,我收到一个500内部服务器错误 我不明白的是,我在调试时检查了代码,它显示它从我的数据库中找到了它需要的所有信息,但是当它以“OK(food)”的形式发送时,我收到了一个500内部服务错误,即使它有这些信息 我对web api还很陌生,所以请您解释一下。我使用的是Visual Studio 2015、实体框架6和SQL管理服务器数据库 我很抱歉发布链接,它说我需要10个声誉才能发布图像

堆栈溢出

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

我不明白的是,我在调试时检查了代码,它显示它从我的数据库中找到了它需要的所有信息,但是当它以“OK(food)”的形式发送时,我收到了一个500内部服务错误,即使它有这些信息

我对web api还很陌生,所以请您解释一下。我使用的是Visual Studio 2015、实体框架6和SQL管理服务器数据库

我很抱歉发布链接,它说我需要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; }
}
受保护的无效页面加载(对象发送方,事件参数e)
{
HttpClient=新的HttpClient();
client.BaseAddress=新Uri(“http://localhost:63591/");
client.DefaultRequestHeaders.Accept.Add(新的System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(“应用程序/json”);
HttpResponseMessage response=client.GetAsync(“api/foods/”+Request.QueryString[“ID”])。结果;
if(响应。IsSuccessStatusCode)
{
string foodstring=response.Content.ReadAsStringAsync().Result;
Food editFood=JsonConvert.DeserializeObject(foodstring);
EditFoodName.Text=editFood.FoodName;
editCarries.Text=editFood.carries.ToString();
EditNotes.Text=editFood.Notes;
}
}
[响应类型(食物类型))]
公共IHttpActionResult GetFood(int id)
{
Food=db.Foods.Find(id);
如果(食物==null)
{
返回NotFound();
}
返回Ok(食物);
}
公共部分类食品
{
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”,“CA2214:DoNotCallOverridableMethodsInConstructors”)]
公共食品
{
this.MealFoods=new HashSet();
}
公共int{get;set;}
公共字符串FoodName{get;set;}
公共整数{get;set;}
公共字符串注释{get;set;}
[System.Diagnostics.CodeAnalysis.SuppressMessage(“Microsoft.Usage”,“CA2227:CollectionPropertiesShouldBreadOnly”)]
公共虚拟ICollection度量对象{get;set;}
}


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

这意味着该行:

 Food food = db.Foods.Find(id);
将不会返回
食品
对象,而是食品的动态子类。这也可以从您在评论中发布的错误中看出,该错误表示该操作不希望返回类型
Food\u 31C9E7DC…


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

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

与其直接使用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。

在调试过程中是否提供了有关500异常的额外信息?没有。我之前遇到过这个问题,并且被告知创建一个伪类来绕过一个关于从数据库获取所有食物的错误,但当时我甚至无法连接到数据库。在这一点上我可以,但它返回一个500,即使它有信息。看起来您正在从asp.net页面调用此api。你能试着直接从浏览器/小提琴手那里调用它吗?id=123我的意思是,我可以,但它不会显示任何内容,因为我正在尝试在asp.net上显示它。我不确定我是否在跟踪。它只是说,这个XML文件似乎没有任何与之关联的样式信息。文档树如下所示。我尝试禁用代理并删除虚拟服务器,但没有帮助。我决定返回并删除我的自定义poco类,当我最初检索所有食物时,我得到一个stackoverflowexception。@JonWisniewski您是否在EntityContext的构造函数中禁用了代理生成?如果序列化程序遍历具有循环引用的导航属性,可能会发生堆栈溢出。我正在使用一个名为MealFood的食物和膳食连接表。是的,我确实在构造器中禁用了它。有人告诉我,因为食物有米食,而且米食有一个对食物的引用,所以它不能被序列化。@JonWisniewski奇怪的是,根据文档,它仍然在创建代理,但它不应该。您可以删除
ResponseType
属性,从而禁用对类型的验证。这应该可以防止它抛出异常,但您可能仍然会得到stackoverflowexception,因为它很可能包含循环引用。至于序列化,可以对其进行序列化,但不能使用默认设置(或所有设置)。您需要检查是否可以指示序列化程序忽略导航属性。