JavaScriptSerializer [ScriptIgnore]对虚拟属性无效?

3

我已经返回了一个Json(myObj)的操作结果。myObj是徽章(Badge)类型。

唯一可能导致序列化器出现循环的两个Badge对象是:

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

我已经给它加了属性,但是没有起到任何帮助作用...?
3个回答

13

你应该将ScriptIgnoreApplyToOverrides参数设置为true

[ScriptIgnore(ApplyToOverrides = true)]

4
这里的问题在于你的虚拟参数被覆盖到一个动态创建的类中。在这种情况下,[ScriptIgnore]属性也被覆盖了。
因此,你应该使用[ScriptIgnore(ApplyToOverrides = true)],以便保持[ScriptIgnore]属性在派生类中有效。

1

JavaScriptSerializer(在使用return Json时使用的内容)绝对会遵守[ScriptIgnore]属性。

以下是证明:

模型:

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

控制器:

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

如果您从 Users 属性中删除 [ScriptIgnore] 属性,则会出现循环引用错误。
所以我猜你的问题可能出在别处。
但个人建议您使用视图模型而不是那些 [ScriptIgnore] 属性。
因此,您只需定义一个视图模型,其中仅包含给定视图所需的属性:
public class BadgeViewModel
{
    public int ID { get; set; }
    public string Name { get; set; }
}

在您的控制器操作中,您需要将领域模型和视图模型之间进行映射,并将视图模型传递给视图:
public class HomeController : Controller
{
    public ActionResult Index()
    {
        Badge badge = ...
        BasgeViewModel vm = new BasgeViewModel
        {
            Id = badge.Id,
            Name = badge.Name
        };

        return Json(vm, JsonRequestBehavior.AllowGet);
    }
}

如果您已经厌倦了在控制器中编写映射代码,只需前往NuGet包控制台并输入以下命令:

Install-Package AutoMapper

为了充分利用优秀的AutoMapper库。

由于某些原因,我认为视图模型是一种多余的方法,我会阅读一些页面,做一些研究。显然,我错了,听起来它可能正是我需要的。为了解决我目前遇到的问题和验证问题(你也做了评论),非常感谢Darin的博文! - williamsandonz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接