【问题标题】:JsonConvert.SerializeObject Circular Reference Error While Serializing User.Identity序列化 User.Identity 时 JsonConvert.SerializeObject 循环引用错误
【发布时间】:2017-10-22 07:06:58
【问题描述】:

我正在尝试将一些信息(包括 ClaimsIdentity)从一个 Web Api 发送到另一个 Web Api。

问题在于错误:

Self referencing loop detected for property 'Subject' with type 'System.Security.Claims.ClaimsIdentity'. Path 'Actor.Claims[0]'.

这是我的代码:

CreateActivityModel.cs

public class CreateActivityModel {
    public string Action { get; set; }
    public ClaimsIdentity Actor { get; set; }
    public string Url { get; set; }
}

序列化代码:

var model = new CreateActivityModel {
    Actor = (ClaimsIdentity) User.Identity,
    Action = "Caller - call",
    Url = Request.RequestUri.ToString()
};

string json = JsonConvert.SerializeObject(model);

在我的 WebApiConfig.cs 中:

var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
jsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.Objects;

虽然我设置了ReferenceLoopHandling.Ignore,但错误依旧存在。

【问题讨论】:

  • 如何实现自己的 DefaultContractResolver 并从序列化中排除该循环属性?说实话,最好的方法是创建您自己的 DTO 并发送它 - 这是您的类型,您可以完全控制它。
  • @ArtavazdBalayan 您能否提供一个示例来创建我自己的 DTO?
  • jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 是解决方案。我认为您的 jsonFormatter 对象未被使用。
  • 不管我把设置放在哪里,我什至都把它放在了Startup.cs,但是没有用。 @约翰肯尼迪
  • 你使用的是dot net core吗?

标签: c# asp.net-mvc serialization json.net claims-based-identity


【解决方案1】:

创建您自己的 DTO 是什么意思 - 您只需将一种类型 (ClaimsIdentity) 转换为另一种 (ClaimsIdentityDTO):

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading;

namespace ClaimsIdentityExample
{
    public class Program
    {
        class ClaimDTO
        {
            public string Issuer { get; set; }
            public string OriginalIssuer { get; set; }
            public string Type { get; set; }
            public string Value { get; set; }
            public string ValueType { get; set; }
        }
        class ClaimsIdentityDTO
        {
            public string Name { get; set; }
            public string AuthenticationType { get; set; }
            public bool IsAuthenticated { get; set; }
            public string NameClaimType { get; set; }
            public string RoleClaimType { get; set; }
            public string Label { get; set; }

            public List<ClaimDTO> Claims { get; set; }

            public ClaimsIdentityDTO()
            {
                Claims = new List<ClaimDTO>();
            }
        }
        static ClaimsIdentityDTO CreateFrom(ClaimsIdentity ci)
        {
            ClaimsIdentityDTO ciDTO = new ClaimsIdentityDTO() {
                Name = ci.Name,
                AuthenticationType = ci.AuthenticationType,
                IsAuthenticated = ci.IsAuthenticated,
                Label = ci.Label,
                NameClaimType = ci.NameClaimType,
                RoleClaimType = ci.RoleClaimType
            };
            foreach (var claim in ci.Claims)
            {
                var claimDTO = new ClaimDTO() {
                    Issuer = claim.Issuer,
                    OriginalIssuer = claim.OriginalIssuer,
                    Type = claim.Type,
                    Value = claim.Value,
                    ValueType = claim.ValueType
                };
                ciDTO.Claims.Add(claimDTO);
            }
            return ciDTO;
        }
        public static void Main(string[] args)
        {
            // Just for test in Console Application
            Thread.GetDomain().SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
            ClaimsIdentity ci = new ClaimsIdentity(((WindowsPrincipal)Thread.CurrentPrincipal).Identity);
            // Create DTO object
            var ciDTO = CreateFrom(ci);
            // Serialize it to json
            var json = JsonConvert.SerializeObject(ciDTO, Formatting.Indented);
            Console.WriteLine(json);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-16
    相关资源
    最近更新 更多