I have returning a Json(myObj) action result. The myObj is of type Badge
The only two objects that Badge has that could cause a loop from a serializer, are:
public class Badge
{
public Badge() { }
public Badge(String Name, String Description)
{
this.Name = Name;
this.Description = Description;
}
[ScriptIgnore]
public virtual BadgeType BadgeType { get; set; }
[ScriptIgnore]
public virtual ICollection<User> Users { get; set; }
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string PrerequisiteCriteriaRef { get; set; }
//PrerequisiteID
public static Badge CreateForSeeder(BaseDBContext db, String Name, String Description, int TypeID)
{
Badge b = new Badge();
b.Name = Name;
b.Description = Description;
b.BadgeType = db.BadgeTypes.Where(x => x.TypeID == TypeID).FirstOrDefault();
return b;
}
}
Which I've given the attribute, but it's not helping out at all...?
The JavaScriptSerializer
(which is what is used when you return Json
) definitely honors the [ScriptIgnore]
attribute.
Here's a proof:
Model:
public class User
{
public Badge Badge { get; set; }
}
public class Badge
{
[ScriptIgnore]
public virtual ICollection<User> Users { get; set; }
public int ID { get; set; }
public string Name { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var badge = new Badge
{
ID = 1,
Name = "badge"
};
var user = new User
{
Badge = badge
};
badge.Users = new[] { user }.ToList();
return Json(badge, JsonRequestBehavior.AllowGet);
}
}
If you remove the [ScriptIgnore]
attribute from the Users property you will get a circular reference error.
So I guess that your problem is somewhere else.
But personally I would recommend you using view models instead of those [ScriptIgnore]
attributes.
So you simply define a view model that will contain only the properties you need for the given view:
public class BadgeViewModel
{
public int ID { get; set; }
public string Name { get; set; }
}
and then in your controller action you map between the domain model and the view model and you pass the view model to the view:
public class HomeController : Controller
{
public ActionResult Index()
{
Badge badge = ...
BasgeViewModel vm = new BasgeViewModel
{
Id = badge.Id,
Name = badge.Name
};
return Json(vm, JsonRequestBehavior.AllowGet);
}
}
and if you are sick of writing mapping code in your controllers you simply head over to your NuGet package console and type the following command:
Install-Package AutoMapper
in order to take full advantage of the excellent AutoMapper library.