C# 从.Net核心API返回复杂对象

C# 从.Net核心API返回复杂对象,c#,angular,entity-framework,typescript,asp.net-core,C#,Angular,Entity Framework,Typescript,Asp.net Core,我正在使用带有Entity Framework的.Net core后端将对象检索到angular2前端。 只要我从后端返回平面对象,我就没有问题。但是当我使用LinqInclude时,我得到一个net::ERR\u CONNECTION\u RESET错误。该错误似乎在调用从后端返回时立即发生,但它从未进入结果处理程序 如何返回对象中包含列表的复杂对象 DocumentsController.cs: 文档.components.ts: 从'@angular/core'导入{Component,I

我正在使用带有Entity Framework的.Net core后端将对象检索到angular2前端。 只要我从后端返回平面对象,我就没有问题。但是当我使用Linq
Include
时,我得到一个
net::ERR\u CONNECTION\u RESET
错误。该错误似乎在调用从后端返回时立即发生,但它从未进入结果处理程序

如何返回对象中包含列表的复杂对象

DocumentsController.cs:

文档.components.ts:

从'@angular/core'导入{Component,Inject};
从'@angular/Http'导入{Http};
@组成部分({
选择器:“文档”,
templateUrl:“./documents.component.html”
})
导出类文档组件{
公共文件:文件[];
构造函数(http:http,@Inject('BASE_URL')baseUrl:string){
http.get(baseUrl+'api/Documents').subscribe(结果=>{
this.documents=result.json()作为文档[];
},error=>console.error(error));
}
}
接口文档{
标题:字符串;
备选标题:字符串;
pageCount:数字;
页面:数组;
}
界面页{
原文:字符串;
排序:编号;
}

过了一会儿,我突然想到了一个想法;这可能是一个永无止境的文档循环的问题,其中包含嵌套文档的页面,等等。 我创建了一个不包含反向引用的DTO(数据传输对象)

public class DocumentDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string AlternativeTitle { get; set; }
    public ICollection<PageDto> Pages { get; set; }
    public string OriginalLanguage { get; set; }
    public string TranslationLanguage { get; set; }
}
public class PageDto
{
    public int Id { get; set; }
    public string OriginalText { get; set; }
    public int Sorting { get; set; }
    public string Translation { get; set; }
}
公共类文档到
{
公共int Id{get;set;}
公共字符串标题{get;set;}
公共字符串AlternativeTitle{get;set;}
公共ICollection页{get;set;}
公共字符串原始语言{get;set;}
公共字符串TranslationLanguage{get;set;}
}
公共类PageDto
{
公共int Id{get;set;}
公共字符串原始文本{get;set;}
公共整数排序{get;set;}
公共字符串转换{get;set;}
}

工作正常。

连接重置错误是由于您的操作方法引发未处理的异常,并将500返回给客户端。这是因为序列化程序启动时,无限循环
文档
=>
页面
=>
文档

在不破坏关系的情况下解决此问题的一种简单方法(即使在使用DTO时也可能需要它们)是更改默认序列化过程:

public IActionResult GetDocuments()
{
    var documents = ...;

    var options = new JsonSerializerSettings 
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    };

    return Json(documents, options);
}
因此,您应该始终返回
IActionResult
async Task
,而不是直接返回类型(如
IEnumerable
)。
此外,如果您发现自己必须连续使用上述代码,您可能希望在启动时更改应用程序级别的默认选项

public class Page : IEntity
{
    public Document Document { get; set; }
    public int DocumentId { get; set; }
    public int Id { get; set; }
    public string OriginalText { get; set; }
    public int Sorting { get; set; }
}
import { Component, Inject } from '@angular/core';
import { Http } from '@angular/http';

@Component({
    selector: 'documents',
    templateUrl: './documents.component.html'
})
export class DocumentsComponent {
    public documents: Document[];

    constructor(http: Http, @Inject('BASE_URL') baseUrl: string) {
        http.get(baseUrl + 'api/Documents').subscribe(result => {
            this.documents = result.json() as Document[];
        }, error => console.error(error));
    }
}

interface Document {
    title: string;
    alternativeTitle: string;
    pageCount: number;
    pages: Array<Page>;
}
interface Page {
    originalText: string;
    sorting: number;
}
public class DocumentDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string AlternativeTitle { get; set; }
    public ICollection<PageDto> Pages { get; set; }
    public string OriginalLanguage { get; set; }
    public string TranslationLanguage { get; set; }
}
public class PageDto
{
    public int Id { get; set; }
    public string OriginalText { get; set; }
    public int Sorting { get; set; }
    public string Translation { get; set; }
}
public IActionResult GetDocuments()
{
    var documents = ...;

    var options = new JsonSerializerSettings 
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore
    };

    return Json(documents, options);
}