सेल्फ रेफरेंसिंग लूप का पता चला - वेबएपीआई से ब्राउज़र में डेटा वापस प्राप्त करना


80

मैं एंटिटी फ्रेमवर्क का उपयोग कर रहा हूं और ब्राउज़र में माता-पिता और बच्चे के डेटा प्राप्त करने में समस्या हो रही है। यहाँ मेरी कक्षाएं हैं:

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

सी # तरफ यह काम करने लगता है लेकिन मुझे लगता है कि उत्तर वस्तुओं में प्रश्न के संदर्भ हैं। जब मैं ब्राउज़र को डेटा प्राप्त करने के लिए WebAPI का उपयोग करता हूं तो मुझे निम्न संदेश मिलता है:

'ObjectContent`1' प्रकार की सामग्री / एप्लिकेशन / json के लिए प्रतिक्रिया निकाय को क्रमबद्ध करने में विफल रहा; charset = utf-8 '।

टाइप 'मॉडल.कोर.क्वेस्टियन' के साथ संपत्ति 'प्रश्न' के लिए सेल्फ रेफरेंसिंग लूप का पता चला।

क्या ऐसा इसलिए है क्योंकि प्रश्न के उत्तर हैं और उत्तर में प्रश्न का संदर्भ है? सभी जगहों पर मैंने देखा कि बच्चे में माता-पिता का संदर्भ है इसलिए मुझे यकीन नहीं है कि मुझे क्या करना है। क्या कोई मुझे इस बारे में कुछ सलाह दे सकता है।


6
अपने वेब एपी के लिए Dto का उपयोग करें, अपने एंटीन में सीधे एंटिटी वापस करने से बचें
cuongle

Dto क्या है? हमारा पूरा एप्लिकेशन EF का उपयोग करता है, हम क्लाइंट पर AngularJS का उपयोग कर रहे हैं, और हमें इस एक मामले के अलावा कोई समस्या नहीं है।

1
मेरा मतलब है कि आपको अपने वेब एपीआई के लिए अपने Dto को परिभाषित करना चाहिए, Dto MVC में ViewModel के साथ समान है। Dto अपने ग्राहक (कोणीयार) को डेटा प्रदान करने के लिए आपके EF मॉडल के रैपर की तरह है।
congongle


JSON.Net पेज के साथ "सेल्फ रेफरेंसिंग लूप डिटेक्ट" अपवाद पर मेरे जवाब पर आपकी नज़र हो सकती है ।
मूरत येल्डज़

जवाबों:


73

क्या ऐसा इसलिए है क्योंकि प्रश्न के उत्तर हैं और उत्तर में प्रश्न का संदर्भ है?

हाँ। इसे क्रमबद्ध नहीं किया जा सकता है।

EDIT: तल्मरीस के उत्तर और ओटो की टिप्पणी को देखें क्योंकि यह सरल है और इसे विश्व स्तर पर स्थापित किया जा सकता है।

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

3
मैं जोड़ना चाहूंगा, मेरे लिए ReferenceLoopHandling को सेट करना। मैंने काम नहीं किया, इसे वैश्विक रूप से या एपीआई स्टार्टअप पर काम नहीं किया। मैं इसे [JsonIgnore] के साथ बाल वर्ग की नेविगेशन संपत्ति को सजाने में काम करने में कामयाब रहा। मुझे अभी भी पेरेंटआईड मिलता है लेकिन धारावाहिक बनाते समय पेरेंट नेविगेशन को नजरअंदाज किया जाता है।
क्लिटन लोवेटो

हैलो, क्रमिकता को अनदेखा करने से परिपत्र निर्भरता प्रश्न> उत्तर> प्रश्न टूट जाएगा। क्या डीटीओ दृष्टिकोण इसे संरक्षित करता है?
बार्टोज़

मुझे एक पुराने ASP.NET MVC प्रोजेक्ट में यह समस्या है। GlobalConfiguration.Configuration में Formatters नहीं हैं। क्या आप यह बता सकते हैं कि इसके लिए क्या किया जा सकता है?
रेन

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Re ferenceLoopHandling = ReferenceLoopHandling.Ignore; -> कोड की यह लाइन कहाँ रखनी है ???
ahtv13

56

आप यह भी अपने में कोशिश कर सकते हैं Application_Start():

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

यह कई हुप्स के माध्यम से जाने के बिना आपकी समस्या को ठीक करना चाहिए।


संपादित करें: नीचे दिए गए ओटो की टिप्पणी के अनुसार, ReferenceLoopHandling.Ignoreइसके बजाय : का उपयोग करें ।

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

78
मुझे पता है कि यह एक पुराना धागा है, लेकिन भविष्य में इस पर ठोकर खाने वालों के लिए, कोशिश करें: GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
ओटो

@ ओटो, आपके सुझावों ने मेरे लिए काम किया। बहुत बहुत धन्यवाद।
जे ६

2
कोड अनंत लूप में जाता है और इस लाइन को जोड़ने के बाद स्टैक ओवरफ्लो अपवाद दिखाता है।
माइक्रोसॉफ्ट डेवलपर

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; बेहतर काम करता है
ड्रैगोस डर्लुट

@Demodave आपको स्टैटिक Create()विधि का उपयोग करके अपना JsonSerializer बनाना होगा जो एक सेटिंग को पैरामीटर के रूप में स्वीकार करता है। डॉक्स: newtonsoft.com/json/help/html/…
टैल्मोरिस

21

यदि OWIN का उपयोग करते हैं, तो याद रखें, आपके लिए और अधिक GlobalSettings नहीं हैं! आपको HttpConfiguration ऑब्जेक्ट में इसी सेटिंग को संशोधित करना होगा जो IAppBuilder UseWebApi फ़ंक्शन (या आप जिस भी सेवा प्लेटफ़ॉर्म पर हैं) में पास हो जाते हैं

कुछ इस तरह दिखेगा।

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

1
आपने मेरा दिन बचाया। मैं सोच रहा था कि ऊपर का जवाब काम क्यों नहीं कर रहा था। हां, Global.asax में OWIN सेटिंग का उपयोग करने से काम नहीं चलेगा।
सिथू 11

21

ASP.NET Core में फिक्स इस प्रकार है:

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

5

अगर 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);
        });
    }

1
Asp-net rc-1-final में मेरा मानना ​​है कि यह "services.Configure <MvcOptions>" अब है
Michał W.

JsonOutputFormatter नामस्थान Microsoft.AspNet.Mvc.Formatters में है
सैम

2
.NET कोर 1.0 RTM के लिए: नया JsonOutputFormatter (serializerSettings, ArrayPool <char> .Sared);
एरिक जूल

5

ASP.NET कोर वेब-एपीआई (.NET कोर 2.0):

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

2

इसका उपयोग करना:

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

मेरे लिए काम नहीं किया। इसके बजाय मैंने सिर्फ टेस्ट करने के लिए अपने मॉडल वर्ग का एक नया, सरलीकृत संस्करण बनाया और वह ठीक लौट आया। यह आलेख उन कुछ मुद्दों पर जाता है जो मैं अपने मॉडल में कर रहा था, जो ईएफ के लिए बहुत अच्छा काम करते थे, लेकिन धारावाहिक नहीं थे:

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


1

ReferenceLoopHandling.Ignore ने मेरे लिए काम नहीं किया। एक ही तरीका है कि मैं इसे प्राप्त कर सकता था, कोड के माध्यम से हटाने के लिए माता-पिता के लिए लिंक वापस चाहिए जो मैं नहीं चाहता था और जो मैंने किया था उसे रखें।

parent.Child.Parent = null;

1

.Net फ्रेमवर्क 4.5 का उपयोग करके एक नए Asp.Net वेब अनुप्रयोग के लिए:

वेब एपि: गोटो ऐप_स्टार्ट -> वेबएपिकऑनफिग.कैंस:

कुछ इस तरह दिखना चाहिए:

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

1

ASP.NET Core 3.0 के भाग के रूप में, टीम डिफ़ॉल्ट रूप से Json.NET सहित दूर चली गई। आप इसके बारे में और अधिक सामान्य रूप से [Json.Net सहित netcore 3.x में] [1] https://github.com/aspnet/Announcements/issues/325 पर पढ़ सकते हैं

आपके द्वारा lazyloading का उपयोग करने के कारण कोई त्रुटि हो सकती है: Services.AddDbContext (विकल्प => options.UseLazyLoadingProxies () ... या db.Configuration.LazyLoadingEnabled - true;

फिक्स: स्टार्टअप में जोड़ें

 services.AddControllers().AddNewtonsoftJson(options =>
        {
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });

0

आलसी लोडिंग के कारण आपको यह त्रुटि मिल रही है। इसलिए मेरा सुझाव संपत्ति से आभासी कुंजी को हटाने का है। यदि आप एपीआई के साथ काम कर रहे हैं तो आलसी लोडिंग आपके एपीआई स्वास्थ्य के लिए अच्छा नहीं है।

अपनी कॉन्फ़िग फ़ाइल में अतिरिक्त पंक्ति जोड़ने की आवश्यकता नहीं है।

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

0

मुझे लगा कि यह त्रुटि तब हो रही है जब मैंने एक मौजूदा डेटाबेस का एक edmx (XML फ़ाइल जो एक वैचारिक मॉडल को परिभाषित करता है) उत्पन्न किया और इसमें अभिभावक और बच्चे दोनों के लिए नेविगेशन गुण थे। मैंने मूल वस्तुओं के सभी नेविगेशन लिंक हटा दिए, क्योंकि मैं केवल बच्चों को नेविगेट करना चाहता था, और समस्या हल हो गई थी।


0

इकाइयाँ db = नई इकाइयाँ ()

db.Configuration.ProxyCreationEnabled = false;

db.Configuration.LazyLoadingEnabled = false;


0

आप इस समस्या को आसानी से हल करने के लिए गतिशील रूप से एक नया बाल संग्रह बना सकते हैं।

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

0

उपरोक्त उत्तरों में से कोई भी विन्यास ASP.NET Core 2.2 में मेरे लिए काम नहीं करता है।

मेरे पास JsonIgnoreमेरे वर्चुअल नेविगेशन गुणों पर विशेषताएँ थीं ।

public class Question
{
    public int QuestionId { get; set; }
    public string Title { get; set; }
    [JsonIgnore]
    public virtual ICollection<Answer> Answers { get; set; }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.