检测到自检参考循环 – 从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”types未能序列化内容types为“application / json; 字符集= UTF-8' 。

对于types为“Models.Core.Question”的属性“问题”检测到自回参考循环。

这是因为问题有答案和答案有一个参考回到问题? 我所看过的所有地方都build议参考孩子的父母,所以我不知道该怎么做。 有人可以给我一些build议吗?

这是因为问题有答案和答案有一个参考回到问题?

是。 它不能被序列化。

编辑:看到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; 

它应该解决您的问题,而不会经过很多的箍。

如果使用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); } 

在ASP.NET Core中,修复如下所示:

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

如果使用DNX / MVC 6 / ASP.NET vNext等等,甚至HttpConfiguration丢失。 您必须在Startup.cs文件中使用以下代码来configuration格式化程序。

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

使用这个:

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

没有为我工作。 相反,我创build了一个新的,我的模型类的简化版本只是为了testing,并返回罚款。 这篇文章进入了我的模型中,EF的伟大工作,但不是可序列化的一些问题:

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

ReferenceLoopHandling.Ignore没有为我工作。 唯一的办法就是通过代码去掉我不想要的父母的链接,并保留我所做的。

 parent.Child.Parent = null; 

由于延迟加载你得到这个错误。 因此,我的build议是从属性中删除虚拟键。 如果您正在使用API​​,则延迟加载对您的API健康状况不利。

无需在configuration文件中添加额外的行。

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

我发现这个错误是在我生成一个现有的数据库的edmx(XML文件,定义了一个概念模型)并导航属性到父和子表时导致的。 我删除了所有的父对象的导航链接,因为我只想导航到孩子,问题就解决了。

实体db =新实体()

db.Configuration.ProxyCreationEnabled = false;

db.Configuration.LazyLoadingEnabled = false;

对于使用.Net Framework 4.5的新的Asp.Net Web应用程序:

Web Api:转到App_Start – > WebApiConfig.cs:

应该看起来像这样:

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