我试图将一些信息(包括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
,但错误仍然存在。
答案 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);
}
}
}