Reputation: 6159
I have a Asp.NET MVC project, database first. I have an Create action in Place controller. In the action method I get my data like this:
// GET: /Place/Create
[Authorize]
public ActionResult Create()
{
string userId = User.Identity.GetUserId();
var places = db.Places.Where(p => p.UserId == userId);
var placesVM = new PlacesVM(places);
ViewBag.UserId = new SelectList(db.AspNetUsers, "Id", "UserName");
return View(placesVM);
}
My Place view model looks like this:
public class PlacesVM
{
public IQueryable<Place> Places { get; set; }
public Place Place { get; set; }
public PlacesVM(IQueryable<Place> places)
{
Places = places;
Place = new Place();
}
}
My Place Model:
public partial class Place
{
public string Id { get; set; }
public string UserId { get; set; }
//TODO: Validare cordonate
public decimal X { get; set; }
public decimal Y { get; set; }
[Display(Name = "Title")]
[Required]
[StringLength(250, MinimumLength = 5)]
public string Titlu { get; set; }
[Display(Name = "Description")]
[Required]
[StringLength(500, MinimumLength = 10)]
public string Descriere { get; set; }
[Required]
[Range(0, 1)]
public byte Public { get; set; }
public virtual AspNetUser AspNetUser { get; set; }
}
AspNetUser:
public partial class AspNetUser
{
public AspNetUser()
{
this.AspNetUserClaims = new HashSet<AspNetUserClaim>();
this.AspNetUserLogins = new HashSet<AspNetUserLogin>();
this.Places = new HashSet<Place>();
this.UserComments = new HashSet<UserComment>();
this.AspNetRoles = new HashSet<AspNetRole>();
}
public string Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string Discriminator { get; set; }
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual ICollection<Place> Places { get; set; }
public virtual ICollection<UserComment> UserComments { get; set; }
public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
}
Now I would like to use Model.Places proprietes in the javascript part of the page. How can I do this?
I've tried to the following:
<script>
var model = '@Html.Raw(Json.Encode(Model))';
</script>
But I got this error:
{"A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Place_084A987E8F6FBE574A22E813FE314F2894AF728F244BDD6582AF50929FF1161D'."}
I have checked the following links on SO, but didn't manage to solve my problem:
Upvotes: 0
Views: 1645
Reputation:
You PlacesVM
view model contains a property that is typeof Place
which in turn contains a property which is typeof AspNetUser
which in turn contains a property which is typeof Collection<Place>
.
When the Json.Encode()
method serializes you model, it serializes Place
which then serializes AspNetUser
which then serializes each Place
which throws the error, because if allowed to continue, it would serialize each AspNetUser
and so on and so on until the system ran out of memory.
Change you view model to include only those property that you need in the view - refer What is ViewModel in MVC?. Note that a view model should not generally contain properties which are data models, particularly when you editing data in a view. Instead, copy the properties from Place
into PlaceVM
that you need to edit, except AspNetUser
, and if you need to display some properties of AspNetUser
, then just include additional properties for then, for example public string UserName { get; set; }
.
Side note: Your current view model does not contain a default (parameterless) constructor so the DefaultModelBinder
will throw an exception when you submit.
Upvotes: 2