Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
423 views
in Technique[技术] by (71.8m points)

c# - Return complex object from .Net core API

I'm using a .Net core backend with Entity Framework to retrieve objects to my angular2 frontend. As long as I return flat objects from the backend I have not problems. But when I use an Linq Include I get an net::ERR_CONNECTION_RESET error. The error seems to occur as soon as the call returns from backend, but it never enters the result handler.

How can I return a complex object with lists inside the objects?

DocumentsController.cs:

[Produces("application/json")]
[Route("api/[controller]")]
public class DocumentsController : Controller
{
    private readonly DatabaseContext _context;

    public DocumentsController(DatabaseContext context)
    {
        _context = context;
    }

    // GET: api/Documents
    [HttpGet]
    public IEnumerable<Document> GetDocuments()
    {
        var documents = _context.Documents
            .Include(x => x.Pages);

        return documents;
    }
}

Document.cs:

public class Document : IEntity
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string AlternativeTitle { get; set; }
    public ICollection<Page> Pages { get; set; }
}

Page.cs:

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

documents.components.ts:

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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The connection reset error is due to your Action method throwing an unhandled exception, returning a 500 to the client. This happens because of the infinite loop Document => Page => Document when the serializer kicks in.
An easy way to solve this problem without breaking the relationship (you might need them even when using DTOs) is to change the default serialization process:

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

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

    return Json(documents, options);
}

With that said, you should always return either IActionResult or async Task<IActionResult> instead of the type directly (like IEnumerable<Document>).
Also, if you find yourself having to use the above code continuously, you might want to change the default options at the application level in Startup


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...