Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JSON响应不包括所有项_C#_.net_Json_Api_Asp.net Core - Fatal编程技术网

C# JSON响应不包括所有项

C# JSON响应不包括所有项,c#,.net,json,api,asp.net-core,C#,.net,Json,Api,Asp.net Core,出于某种原因,每个数组中只有第一项作为JSON返回,有什么线索吗 以下是我在调试期间看到的内容,正如您所知,我在“类别”中有两项,在“任务”中有两项: Postman JSON结果(它应该返回所有项目,不是吗?) 以下是我的“Category.cs”,仅供参考: public class Category { public int CategoryId { get; set; } public string Name { get; set; } public Date

出于某种原因,每个数组中只有第一项作为JSON返回,有什么线索吗

以下是我在调试期间看到的内容,正如您所知,我在“类别”中有两项,在“任务”中有两项:

Postman JSON结果(它应该返回所有项目,不是吗?)

以下是我的“Category.cs”,仅供参考:

public class Category
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
    public string Username { get; set; }

    public ApplicationUser ApplicationUser { get; set; }

    public virtual ICollection<Task> Tasks { get; set; }
}
我的Api:

    [HttpGet]
    public JsonResult Get()
    {
        var result = _repo.GetAllForUser("lucas@test.com");

        return Json(result);
    }
和存储库:

    public IEnumerable<Category> GetAllForUser(string name)
    {
        return _ctx.Categories
                    .Where(c => c.ApplicationUser.UserName == name)
                    .Include(c => c.Tasks)
                    .ToList();           
    }
public IEnumerable GetAllForUser(字符串名称)
{
返回_ctx.Categories
.Where(c=>c.ApplicationUser.UserName==name)
.包括(c=>c.任务)
.ToList();
}
以下是我在数据库中插入的内容,以及我应该从Api中检索的内容:

        categories.Add(new Category
        {
            Name = "cat 1",
            Tasks = new List<Task>
            {
                new Task { Name="task 1" },
                new Task { Name="task 2" }
            }
        });
        categories.Add(new Category
        {
            Name = "cat 2",
            Tasks = new List<Task>
            {
                new Task { Name="task 3" },
                new Task { Name="task 4" }
            }
        });
类别。添加(新类别)
{
Name=“第1类”,
任务=新列表
{
新任务{Name=“Task 1”},
新任务{Name=“Task 2”}
}
});
类别。添加(新类别)
{
Name=“第2类”,
任务=新列表
{
新任务{Name=“Task 3”},
新任务{Name=“Task 4”}
}
});

正如Kiran指出的,您的模型中有循环引用,这导致了异常。错误地使请求看起来是用部分数据完成的。(循环引用为类别->任务->任务->类别)

实际发生的是在响应的JSON序列化进行到一半时出现了一个未处理的异常。ASP.NET Core没有中止连接(应该如此),而是发回在错误发生之前序列化的所有内容

您可以定义不包含从
任务
返回到
类别
的引用的DTO类,也可以返回匿名类型:

[HttpGet]
public JsonResult Get()
{
    var result = _repo.GetAllForUser("lucas@test.com");

    var response = new {
        categoryId: result.CategoryId,
        name: result.Name,
        timestamp: result.Timestamp,
        username: result.Username,
        tasks: result.Tasks.Select(t => new {
            taskId: t.TaskId,
            name: t.Name,
            timestamp: t.Timestamp
        })
    };

    return Json(response);
}

如果您经常这样做,那么创建DTO类并使用AutoMapper之类的工具为您进行映射是有意义的。

Nate的回答很完美,他给出了很好的建议,指出我需要为我的场景找到很好的解决方案。我已经决定分享它,以防有人会遇到类似的问题。作为提醒,这是ASP.NET核心模型第一个使用Api的MVC项目。我已经使用AutoMapper将我的模型第一个类映射到相应的视图模型

以下是我的第一节课:

public class Category
{
    public Category()
    {
        Tasks = new HashSet<Task>();
    }

    public int CategoryId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
    public string Username { get; set; }

    public ApplicationUser ApplicationUser { get; set; }

    public virtual ICollection<Task> Tasks { get; set; }
}

public class Task
{
    public int TaskId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
    public int CategoryId { get; set; }

    public virtual Category Category { get; set; }
}
公共类类别
{
公共类别()
{
Tasks=newhashset();
}
public int CategoryId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
公共字符串用户名{get;set;}
公共应用程序用户应用程序用户{get;set;}
公共虚拟ICollection任务{get;set;}
}
公开课任务
{
public int TaskId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
public int CategoryId{get;set;}
公共虚拟类别{get;set;}
}
相应的视图模型:

public class CategoryViewModel
{
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }

    public IEnumerable<TaskViewModel> Tasks { get; set; }
}

public class TaskViewModel
{
    public int TaskId { get; set; }
    public string Name { get; set; }
    public DateTime Timestamp { get; set; }
}
public类CategoryViewModel
{
public int CategoryId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
公共IEnumerable任务{get;set;}
}
公共类任务视图模型
{
public int TaskId{get;set;}
公共字符串名称{get;set;}
公共日期时间时间戳{get;set;}
}
“setup.cs”文件中的自动映射设置:

Mapper.Initialize(config =>
        {
            config.CreateMap<Category, CategoryViewModel>().ReverseMap();
            config.CreateMap<Task, TaskViewModel>().ReverseMap();
        });
Mapper.Initialize(配置=>
{
config.CreateMap().ReverseMap();
config.CreateMap().ReverseMap();
});
最后是我的完整Api方法:

[HttpGet]
    public JsonResult Get()
    {
        var result = Mapper.Map<IEnumerable<CategoryViewModel>>(_repo.GetAllForUser("lucas@test.com"));

        return Json(result);
    }
[HttpGet]
publicjsonresult Get()
{
var result=Mapper.Map(_repo.GetAllForUser(“lucas@test.com"));
返回Json(结果);
}

你能分享一下你的
任务
模型的样子吗?通过添加更多相关的代码来提供更相关的代码编辑问题code@mic4ael:没有Json类,它是来自controller的Json方法,是状态代码为的新JsonObjectResult的快捷方式。您是否在Windows上运行应用程序?根据您的模型,您似乎有循环引用(任务引用类别,反之亦然),这会导致Json.net引发异常:…请尝试以下操作:启用日志记录,并查看是否有任何异常被记录…还可以尝试非IIS场景(示例:直接在控制台中执行
dotnet运行
并启用控制台日志记录)很好的解释,谢谢。事实上,这是循环引用,一旦我从我的任务类中删除了Category变量,它就如预期的那样工作了。对我来说奇怪的是,这就是EF建议连接模型第一个类的方式。在执行查询时,也很容易在类之间导航。那么实际的建议是什么呢n、 我应该在创建模型第一类时阻止循环引用,或者我应该从Api返回一个匿名类型,就像上面指定的那样。thanks@lucas直接返回实体模型作为响应通常不是一个好主意,因为它们通常有您不想要或不需要用户看到的东西(包括循环引用)。我认为最好的解决方案是拥有另一组可以映射到的模型(DTO或“响应模型”)。
[HttpGet]
    public JsonResult Get()
    {
        var result = Mapper.Map<IEnumerable<CategoryViewModel>>(_repo.GetAllForUser("lucas@test.com"));

        return Json(result);
    }