EFCORE/ASP.NET核心多到许多关系:jsonserializer referenceCeloPhandling



我对asp.net core jsonserializer有一个问题。即使我明确将参考文献和引用属性设置为coreenceLophandling.ignore。

我有这个github问题中的详细信息:https://github.com/aspnet/entityframeworkcore/issues/14997

编辑:

整个启动配置代码:

public void ConfigureServices(IServiceCollection services)
{
  // Deserialize specific settings into living objects
  services.Configure<JwtSettings>(this.Configuration.GetSection("Jwt"));
  services.Configure<CookieSettings>(this.Configuration.GetSection("Cookies"));
  // Read settings to apply locally
  DatabasesSettings dbSettings = DatabasesSettings.GetDatabasesSettings(this.Configuration);
  JwtSettings jwtSettings = this.Configuration.GetSection("Jwt").Get<JwtSettings>();
  CookieSettings cookieSettings = this.Configuration.GetSection("Cookies").Get<CookieSettings>();
  switch (dbSettings[DatabaseConstants.DatabaseSettingsData].Provider)
  {
    case "mysql":
      services.AddEntityFrameworkMySql()
              .AddDbContext<DataContext>(options => options.UseMySql(ConnectionStringBuilder.BuildConnectionString(dbSettings[DatabaseConstants.DatabaseSettingsData])));
      break;
    case "mssql":
      services.AddEntityFrameworkSqlServer()
              .AddDbContext<DataContext>(options => options.UseSqlServer(ConnectionStringBuilder.BuildConnectionString(dbSettings[DatabaseConstants.DatabaseSettingsData])));
      break;
  }
  // Identity MUST precede AUTHENTICATION in order to produce correct 401 Unauthorized instead of 404 Not found
  services.AddIdentity<User, IdentityRole>(options =>
  {
    options.User.RequireUniqueEmail = true;
    options.Password.RequiredLength = 6;
    options.Password.RequireDigit = false;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireUppercase = false;
    options.Password.RequireLowercase = false;
  }).AddEntityFrameworkStores<DataContext>().AddDefaultTokenProviders();
  // JWT Bearer Token Authentication configuration secretKey contains a secret passphrase only your server knows
  Action<JwtBearerOptions> jwtOptions = options =>
  {
    options.Events = new JwtBearerEvents
    {
      OnTokenValidated = context =>
      {
        // Get the EF Context responsbile for authentication
        DataContext dbContext = context.HttpContext.RequestServices.GetRequiredService<DataContext>();
        List<Claim> claims = new List<Claim>
        {
          new Claim("AuthorizedAccess", "true"),
        };
        // Add claim(s) based on user -- todo
        ClaimsIdentity appIdentity = new ClaimsIdentity(claims);
        context.Principal.AddIdentity(appIdentity);
        return Task.CompletedTask;
      }
    };
    options.TokenValidationParameters = new TokenValidationParameters
    {
      // Do not validate lifetime. Need logout to invalidate. todo: verify if we can leave it this way
      ValidateLifetime = jwtSettings.Expiration.Enabled,
      // If you want to allow a certain amount of clock drift, set that here:
      ClockSkew = TimeSpan.FromMinutes(jwtSettings.Expiration.ClockDrift),
      // Validate the JWT Issuer (iss) claim
      ValidateIssuer = true,
      ValidIssuer = jwtSettings.Issuer,
      // Validate the JWT Audience (aud) claim
      ValidateAudience = true,
      ValidAudience = jwtSettings.Audience,
      // The signing key must match!
      ValidateIssuerSigningKey = true,
      IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Key)),
      SaveSigninToken = true
    };
  };
  // Authentication Service
  services.AddAuthentication(
    options =>
    {
      options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
      options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(jwtOptions).AddCookie();
  // Authorization Service
  services.AddAuthorization(
    options =>
    {
      options.AddPolicy(PolicyNames.AdministrationPolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.AdministrationPolicy)));
      options.AddPolicy(PolicyNames.PurchasePolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.PurchasePolicy)));
      options.AddPolicy(PolicyNames.TradePolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.TradePolicy)));
      options.AddPolicy(PolicyNames.ExchangePolicy, policy => policy.Requirements.Add(new AuthorizationNameRequirement(PolicyNames.ExchangePolicy)));
    });
  // Application Cookie
  services.ConfigureApplicationCookie(
    options =>
    {
      // Avoid redirecting REST clients on 401
      options.Events = new CookieAuthenticationEvents
      {
        OnRedirectToLogin = ctx =>
        {
          ctx.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
          return Task.FromResult(0);
        }
      };
      options.Cookie.Name = cookieSettings.ApplicationCookieName;
    });
  // Antiforgery
  services.AddAntiforgery(
    options =>
    {
      options.Cookie.Name = cookieSettings.AntiforgeryCookieName;
      options.Cookie.Domain = cookieSettings.AntiforgeryCookieDomain;
      options.Cookie.Path = "/";
      options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    });
  // Additional Services
  services.AddSingleton<IAuthorizationHandler, AuthorizationNameHandler>();
  // Cross Origin Policies
  services.AddCors(
    options =>
    {
      options.AddPolicy("AllowAnyOrigin", builder => { builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials().Build(); });
    });
  // Enable Response Compression
  services.AddResponseCompression();
  // MVC
  services.AddMvc(
    options =>
    {
      options.Filters.Add(new CorsAuthorizationFilterFactory("AllowAnyOrigin"));
      options.CacheProfiles.Add(
        "Default",
        new CacheProfile()
        {
          Duration = 60
        });
      options.CacheProfiles.Add(
        "Never",
        new CacheProfile()
        {
          Location = ResponseCacheLocation.None,
          NoStore = true
        });
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddJsonOptions(
    options =>
    {
      options.SerializerSettings.Formatting = Formatting.Indented;
      options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
      options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  if (Program.IsDebug)
  {
    app.UseDeveloperExceptionPage();
  }
  else
  {
    app.UseHsts();
  }
  app.UseCors("AllowAnyOrigin");
  // app.UseCorsMiddleware(); // Custom middleware
  app.UseHttpsRedirection();
  app.UseDefaultFiles();
  app.UseStaticFiles();
  app.UseAuthentication();
  app.UseResponseCompression();
  app.UseMvc();
}

您可以配置Json.NET以忽略对象图中找到的周期。这是在Startup.cs中的ConfigureServices(...)方法中完成的,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddMvc()
        .AddJsonOptions(
            options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
        );
    ...
}

在您的代码中,用以下内容替换options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Error;

options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore

最新更新