Nice programing

자체 참조 루프 감지 됨-WebApi에서 브라우저로 데이터 가져 오기

nicepro 2020. 10. 11. 11:17
반응형

자체 참조 루프 감지 됨-WebApi에서 브라우저로 데이터 가져 오기


Entity Framework를 사용하고 있으며 브라우저에 부모 및 자식 데이터를 가져 오는 데 문제가 있습니다. 내 수업은 다음과 같습니다.

 public class Question
 {
    public int QuestionId { get; set; }
    public string Title { get; set; }
    public virtual ICollection<Answer> Answers { get; set; }
}

public class Answer
{
    public int AnswerId { get; set; }
    public string Text { get; set; }
    public int QuestionId { get; set; }
    public virtual Question Question { get; set; }
}

다음 코드를 사용하여 질문 및 답변 데이터를 반환하고 있습니다.

    public IList<Question> GetQuestions(int subTopicId, int questionStatusId)
    {
        var questions = _questionsRepository.GetAll()
            .Where(a => a.SubTopicId == subTopicId &&
                   (questionStatusId == 99 ||
                    a.QuestionStatusId == questionStatusId))
            .Include(a => a.Answers)
            .ToList();
        return questions; 
    }

C # 측면에서 이것은 작동하는 것처럼 보이지만 대답 개체에 질문에 대한 참조가 있음을 알 수 있습니다. WebAPI를 사용하여 데이터를 브라우저로 가져올 때 다음 메시지가 표시됩니다.

'ObjectContent`1'유형이 콘텐츠 유형 'application / json;에 대한 응답 본문을 직렬화하지 못했습니다. charset = utf-8 '입니다.

유형이 'Models.Core.Question'인 속성 'question'에 대해 자체 참조 루프가 감지되었습니다.

질문에 답변이 있고 답변에 질문에 대한 참조가 있기 때문입니까? 내가 본 모든 장소는 아이의 부모에 대한 언급을 제안하므로 어떻게 해야할지 모르겠습니다. 누군가 나에게 이것에 대한 조언을 줄 수 있습니까?


질문에 답변이 있고 답변에 질문에 대한 참조가 있기 때문입니까?

예. 직렬화 할 수 없습니다.

편집 : Tallmaris의 답변과 OttO의 의견을 참조하십시오. 더 간단하고 전역 적으로 설정할 수 있습니다.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Re‌​ferenceLoopHandling = ReferenceLoopHandling.Ignore;

이전 답변 :

EF 개체 Question를 자신의 중간 또는 DataTransferObject에 투영합니다 . 그러면이 Dto를 성공적으로 직렬화 할 수 있습니다.

public class QuestionDto
{
    public QuestionDto()
    {
        this.Answers = new List<Answer>();
    } 
    public int QuestionId { get; set; }
    ...
    ...
    public string Title { get; set; }
    public List<Answer> Answers { get; set; }
}

다음과 같은 것 :

public IList<QuestionDto> GetQuestions(int subTopicId, int questionStatusId)
{
    var questions = _questionsRepository.GetAll()
        .Where(a => a.SubTopicId == subTopicId &&
               (questionStatusId == 99 ||
                a.QuestionStatusId == questionStatusId))
        .Include(a => a.Answers)
        .ToList();

    var dto = questions.Select(x => new QuestionDto { Title = x.Title ... } );

    return dto; 
}

다음에서 시도해 볼 수도 있습니다 Application_Start().

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;

많은 후프를 거치지 않고 문제를 해결해야합니다.


편집 : 아래 OttO의 의견에 따라 ReferenceLoopHandling.Ignore대신 사용하십시오 .

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

OWIN을 사용하는 경우 더 이상 GlobalSettings가 필요하지 않습니다! IAppBuilder UseWebApi 함수 (또는 사용중인 서비스 플랫폼)에 전달되는 HttpConfiguration 개체에서 이와 동일한 설정을 수정해야합니다.

이렇게 보일 것입니다.

    public void Configuration(IAppBuilder app)
    {      
       //auth config, service registration, etc      
       var config = new HttpConfiguration();
       config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
       //other config settings, dependency injection/resolver settings, etc
       app.UseWebApi(config);
}

ASP.NET Core에서 수정 사항은 다음과 같습니다.

services
.AddMvc()
.AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

DNX / MVC 6 / ASP.NET vNext를 사용하는 경우 어쩌구 저쩌구, 심지어 HttpConfiguration누락되었습니다. Startup.cs파일 에서 다음 코드를 사용하여 포맷터를 구성해야 합니다.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().Configure<MvcOptions>(option => 
        {
            //Clear all existing output formatters
            option.OutputFormatters.Clear();
            var jsonOutputFormatter = new JsonOutputFormatter();
            //Set ReferenceLoopHandling
            jsonOutputFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            //Insert above jsonOutputFormatter as the first formatter, you can insert other formatters.
            option.OutputFormatters.Insert(0, jsonOutputFormatter);
        });
    }

ASP.NET Core 웹 API (.NET Core 2.0) :

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.Configure<MvcJsonOptions>(config =>
    {
        config.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    });
}

이것을 사용하여 :

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore

나를 위해 일하지 않았다. 대신 테스트를 위해 모델 클래스의 새롭고 단순화 된 버전을 만들었는데 제대로 돌아 왔습니다. 이 기사는 EF에서 훌륭하게 작동했지만 직렬화 할 수 없었던 내 모델에서 겪었던 몇 가지 문제에 대해 설명합니다.

http://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-4


ReferenceLoopHandling.Ignore didn't work for me. The only way I could get round it was to remove via code the links back to the parent I didn't want and keep the ones I did.

parent.Child.Parent = null;

For a new Asp.Net Web Application using .Net Framework 4.5:

Web Api: Goto App_Start -> WebApiConfig.cs:

Should look something like this:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

        // ReferenceLoopHandling.Ignore will solve the Self referencing loop detected error
        config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

        //Will serve json as default instead of XML
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

Due to lazy loading you are getting this error. Hence my suggestion is to remove virtual key from property. If you are working with API then lazy loading is not good for your API health.

No need to add extra line in your config file.

public class Question
 {
    public int QuestionId { get; set; }
    public string Title { get; set; }
    public ICollection<Answer> Answers { get; set; }
}

public class Answer
{
    public int AnswerId { get; set; }
    public string Text { get; set; }
    public int QuestionId { get; set; }
    public Question Question { get; set; }
}

I found this error was being caused when I generated an edmx (XML file that defines a conceptual model) of an existing database and it had Navigation properties to both the parent and child tables. I deleted all the navigation links to the parent objects, as I only wanted to navigate to children, and the problem was solved.


Entities db = new Entities()

db.Configuration.ProxyCreationEnabled = false;

db.Configuration.LazyLoadingEnabled = false;


You can dynamically create a new child collection to easily work around this problem.

public IList<Question> GetQuestions(int subTopicId, int questionStatusId)
    {
        var questions = _questionsRepository.GetAll()
            .Where(a => a.SubTopicId == subTopicId &&
                   (questionStatusId == 99 ||
                    a.QuestionStatusId == questionStatusId))
            .Include(a => a.Answers).Select(b=> new { 
               b.QuestionId,
               b.Title
               Answers = b.Answers.Select(c=> new {
                   c.AnswerId,
                   c.Text,
                   c.QuestionId }))
            .ToList();
        return questions; 
    }

None of the configurations in the answers above worked for me in ASP.NET Core 2.2.

I had the add the JsonIgnore attributes on my virtual navigation properties.

public class Question
{
    public int QuestionId { get; set; }
    public string Title { get; set; }
    [JsonIgnore]
    public virtual ICollection<Answer> Answers { get; set; }
}

참고URL : https://stackoverflow.com/questions/17313632/self-referencing-loop-detected-getting-back-data-from-webapi-to-the-browser

반응형