序列化User.Identity

时间:2017-10-22 07:06:59

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

我试图将一些信息(包括ClaimsIdentity)发送到另一个网络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,但错误仍然存​​在。

1 个答案:

答案 0 :(得分: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);
        }
    }
}