3

I have a simple Article class like this:

   public class Article
   {
    [Key]
    public int ArticleId { get; set; }
    public string Title { get; set; }
    public string PageContent { get; set; }
    public System.DateTime PostedDate { get; set; }
    public int? ArticlePostedBy { get; set; }

    public virtual ApplicationUser ApplicationUser { get; set; }
  }

and this is my ApplicationUser class which have one to many relationship with article class :

 public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
  {
    public ApplicationUser()
    {
        this.Articles = new HashSet<Article>();
    }
    public virtual ICollection<Article> Articles { get; set; }

I have configured the one to many relationship using fluent api like this:

    modelBuilder.Entity<Article>()
                   .HasOptional<ApplicationUser>(a => a.ApplicationUser)
                   .WithMany(a => a.Articles)
                   .HasForeignKey(s => s.ArticlePostedBy);

Now, this is my controller for posting the article:

    [HttpPost]
    public JsonResult Index(Article article)
    {
        article.ArticlePostedBy = User.Identity.GetUserId<int>();
        article.PostedDate = DateTime.UtcNow;
        db.Articles.Add(article);
        db.SaveChanges();
        var usr = db.Users.FirstOrDefault(x => x.Id == article.ArticlePostedBy);
        var ret = new
        {
            Title = article.Title,
            PostedBy = article.ArticlePostedBy,
            PostedByName = usr.UserName,
            PostedByAvatar = db.Users.Include(s => s.Files).SingleOrDefault(s => s.Id == article.ArticlePostedBy),
            PostedDate = article.PostedDate,
            ArticleId = article.ArticleId
        };
        return Json(ret, JsonRequestBehavior.AllowGet);
    }

Now, the problem arises when i try to post the data. On Submit button click, data got saved in the dbase but gives this server error--- A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.ApplicationUser_04102CD9A296DF3EA26BCA4B5FDF758BC1CD8B55C5601C2EA864BBE5FE4B7F46'. Now, i have read many articles on stack overflow but did not get any simple solution. The solution was given to disable lazy loading but I can't disable lazy loading as it is my primary need. many functions in my application would get affected due to that. Somewhere it was suggested to use ScriptIgnore. Should I use that? If yes, where to apply that or there is any other better approach. I want to apply changes only for this particular class.

sandy
  • 181
  • 2
  • 3
  • 12
duke
  • 1,816
  • 2
  • 18
  • 32
  • 1
    Either return a view-model instead of your entity, or check http://stackoverflow.com/questions/7109967/using-json-net-as-the-default-json-serializer-in-asp-net-mvc-3-is-it-possible – haim770 Nov 19 '15 at 08:05
  • 2
    Also, you don't need the `JsonRequestBehavior.AllowGet` because the action is already restricted to `[HttpPost]` – haim770 Nov 19 '15 at 08:06
  • 1
    best practice is to NOT pass your DB objects around (i.e your entity). map them to a DTO/VM and use that for the view. – Ahmed ilyas Nov 19 '15 at 08:07
  • okk i will try to use view model @haim770 – duke Nov 19 '15 at 08:12
  • 2
    The `PostedByAvatar` property in your anonymous `ret` object is causing the issue. Just change it to return a property of `User`, not the whole object (a view model is not really the solution because an anonymous object will work just fine) –  Nov 19 '15 at 08:16
  • @Stephen you are correct for code given. – Parth Trivedi Nov 19 '15 at 08:22
  • @StephenMuecke yupp u r right sir, that property was the root cause and i was misguided to whole new topic bcoz error was something different thnxx for suggestion – duke Nov 19 '15 at 08:52
  • Not sure what you mean by _"error was something different"_ - the error is occurring because `PostedByAvatar = db.Users()...` is returning `ApplicationUser` which contains a collection of `Article` and `Article` contains `ApplicationUser` and `ApplicationUser` contains a collection of `Article` and so on and so on (i.e. 'circular refererence') –  Nov 19 '15 at 08:57
  • @StephenMuecke actually instead of correcting postedbyAvatar property i was searching how to eager load lazy load how to disable enable etc etc that was i was saying but after ur suggestion problem solved without even doing something extra thnxxx once again – duke Nov 20 '15 at 05:20

1 Answers1

0

Your error is occurring because the anonymous object your returnind (ret) includes property PostedByAvatar which is typeof ApplicationUser.

ApplicationUser contains a collection of Article and Article contains a property for ApplicationUser which in turn contains a collection of Article which contains ApplicationUser and so on and so on. Serializing it generates a circular reference exception.

Instead of returning ApplicationUser, just return a property (or properties) of ApplicationUser that you need in the view.

var user = db.Users.Include(s => s.Files).SingleOrDefault(s => s.Id == article.ArticlePostedBy);

var ret = new
{
    Title = article.Title,
    ....
    PostedByAvatar = user.Files.someProperty;
    ....
}

Side note. It appears you have already the user defined by var usr = db.Users.FirstOrDefault(x => x.Id == article.ArticlePostedBy); so it's unnecessary to call the database again (the only difference appears to be the .Include() clause so that should just be included in the var usr = .. statement).