System.Text.Json.ThrowHelper.ThrowJsonException_SerializerCycleDetected - c#

I got this error:
JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.
System.Text.Json.ThrowHelper.ThrowJsonException_SerializerCycleDetected
I've already added:
.AddJsonOptions(x =>
{
x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
}
);
to the configuration, but this doesn't seem take effect.
The only way I can remove this error is adding the attribute [JsonIgnore] on the navigation properties of my models
but i'm sure i'm not applying .AddJsonOptions in the right place
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
services.AddNotyf(o =>
{
o.DurationInSeconds = 10;
o.IsDismissable = true;
o.HasRippleEffect = true;
});
services.AddApplicationLayer();
services.AddInfrastructure(_configuration);
services.AddPersistenceContexts(_configuration);
services.AddRepositories();
services.AddSharedInfrastructure(_configuration);
services.AddMultiLingualSupport();
services.AddControllersWithViews()
.AddJsonOptions(x =>
x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve; //<-- **** added this
);
services.AddAutoMapper(Assembly.GetExecutingAssembly());
services.AddDistributedMemoryCache();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped<IViewRenderService, ViewRenderService>();
}
or maybe the JSON serializer is configured correctly at controller level but the error is originated from another source?
Looking deeper in the stacktrace of the error it's generated from:
await _distributedCache.SetAsync(cacheKey, anagReparto);
where
_distributedCache is Microsoft.Extension.Caching.Distributed.IDistributedCache
maybe this package needs a its own JSON configuration and don't use the controller's JSON serializer options that i've configured?

Related

Change default cookie names in ASP.NET Core MVC

I would like to change the default Cookie name for .AspNetCore.Antiforgery.xxx in ASP.NET Core 3.X MVC, however I do not seem to find any documentation on it. Is it even possible?
The only one I found to be able to alter was this:
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
options.ConsentCookie.Name = "GDRP";
});
This is achievable using AddAntiforgery. Here's an example taken from the docs and modified accordingly:
services.AddAntiforgery(options =>
{
options.Cookie.Name = "YourCookieName";
});
There's a useful page in the docs that lists the built-in ASP.NET Core cookies and where the configuration for each comes from.
For .NET 5.0 and higher
in ProjectRoot/Startup.cs class
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "your_cookie_name";
});
// ...
services.AddControllers();
}
ok, found it already, for those that are looking
services.AddAntiforgery(options =>
{
options.Cookie.Name = "my-x-name";
options.HeaderName = "my-x-name";
});
It will accept any string, need to validate if it works or if something else needs to be updated...

How to add XML output formatter to ASP.Net Boilerplate?

ASP.NET Core 2.2, ASP.Net Boilerplate version 4.1, Modul Zero Core version 4.4.0 is used.
The API accepts JSON objects as input and returns JSON objects. I was faced with the task of ensuring the possibility of using XML in conjunction with JSON.
I tried it like this:
// file RootNs.Web.Mvc Startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services) {
// ...
services.AddMvc(options => {
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
options.ReturnHttpNotAcceptable = true;
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
options.RespectBrowserAcceptHeader = true;
options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
// so also tried
// options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
options.FormatterMappings
.SetMediaTypeMappingForFormat("xml", MediaTypeHeaderValue.Parse("application/xml"));
})
}
After that, I decorated the method in the API with the FormatFilter attribute. But it did not help.
How to add support for XML output formater? In which project (*.Web.Mvc or *.Web.Host) should the file Startup.cs be edited?

Scope was not available. Did you forget to call container.BeginScope()?

Hello I want to using castle windosr in .net core and I have get bellow error in .net core:
Scope was not available. Did you forget to call
container.BeginScope()?
my code is :
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
var container = new WindsorContainer();
//container.BeginScope();
Bootstrapper.WireUp(container);
FrameworkBootstrapper.WireUp(container);
var configureServices = WindsorRegistrationHelper.CreateServiceProvider(container, services);
return configureServices;
}
I added the error image .
in your option if i add container.BeginScope(); after var container = new WindsorContainer(); Is it the right way? Is there any problem?
WindsorRegistrationHelper is a package between .net core built in ioc and castle
you can see on below link:
https://github.com/volosoft/castle-windsor-ms-adapter

.NET Core 2.0 - Still seeing No 'Access-Control-Allow-Origin' header error

I'm at wit's end on this one. I've already researched other answers to similar questions on SO w/o any luck.
I'm fairly certain I've got CORS enabled correctly to allow incoming requests (in this case, POST requests) from all origins, but I'm seeing the error below:
Failed to load http://localhost:5000/expenses: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4200' is therefore not allowed
access. The response had HTTP status code 500.
Here's how I've enabled CORS in my webAPI project:
relevant methods in Startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddMvc();
services.AddDbContext<ExpensesDbContext>(options =>
options.UseMySQL(Configuration.GetConnectionString("DefaultConnection")));
services.AddTransient<IBaseDa<Accounts>, AccountsDataAccess>();
services.AddTransient<IExpensesDa, ExpensesDa>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
env.EnvironmentName = "Development";
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
.AllowCredentials());
app.UseMvc();
}
If i'm using .AllowAnyOrigin() and .AllowAnyMethod(), why am I seeing the error above?
Was scratching my head on this situation here for a while. I had CORS enabled properly, but some calls were still returning the Access-Control-Allow-Origin error. I found the problem... the sneaky sneaky problem...
Our problem was caused by how we were using app.UseExceptionHandler. Specifically, here's the code we were using, except our original code didn't have the context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); line.
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
var errorFeature = context.Features.Get<IExceptionHandlerFeature>();
var exception = errorFeature.Error;
var problemDetails = new ProblemDetails
{
Title = R.ErrorUnexpected,
Status = status,
Detail =
$"{exception.Message} {exception.InnerException?.Message}"
};
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.StatusCode = problemDetails.Status.GetValueOrDefault();
context.Response.WriteJson(problemDetails, "application/problem+json");
await Task.CompletedTask;
});
});
app.UseExceptionHandler is a much lower level function than controller actions, and thus does not take part in anything related to CORS natively. Adding context.Response.Headers.Add("Access-Control-Allow-Origin", "*"); fixed the problem.
The combination of netCore2.0 (http://localhost:5000/) + Angular (http://localhost:4200) + chrome = Access-Control-Allow-Origin. I have had this issue before and it took me 3 days to realize that chrome will always throw this error. I think it is because chrome views localhost as the origin disregarding the port even tho the middleware explicitly tells it not too especially on POST requests.
I would try and define a policy in your startup.cs Configure services:
public void ConfigureServices(IServiceCollection services)
{
//add cors service
services.AddCors(options => options.AddPolicy("Cors",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
then in your Configure method I would add that:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//authentication added
app.UseAuthentication();
app.UseCors("Cors");
app.UseMvc();
}
... This most likely wont work and but try it any who.... This drove me mad and I needed the satisfaction of seeing if the request even attempted to hit the asp.netCore backend:
I used
If you really want to see I would clear your cache and cookies then add
IHttpContextAccessor to get low level control of whats going on in the request.
In my dilema with the same problem I needed angular to send an image. I was getting the annyoing
Origin error then through exprimenting I got the Image by injecting IHttpContextAccessor into my controller and
debugging
public void ConfigureServices(IServiceCollection services)
{
//add cors service
services.AddCors(options => options.AddPolicy("Cors",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
services.AddMvc();
// register an IHttpContextAccessor so we can access the current
// HttpContext in services by injecting it
//---we use to this pull out the contents of the request
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
you want to inject this into whatever controller u are
using to retrieve the json object of the POST request. Im going to use the example as Home controller:
public class HomeController : Controller
{
// make a read only field
private readonly IHttpContextAccessor _httpContextAccessor;
//create ctor for controller and inject it
public UserService(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
// now in your post method use this to see what the if anything came in through the request:
public async Task<IActionResult> Picload(IFormFile file){//---always null
// in my problem I was loading and image from.
var file = _httpContextAccessor.HttpContext.Request.Form.Files[0];
}
Using this it gave me access to the image chrome was giving me an Origin error about.
My crystal ball tells me that somewhere in your C# code an error appear in time of execution and this way the "return" statement of the service is never executed. So debug your code and fix the error so the response is returned to the browser.

OData v4 on .Net Core 1.1 missing /$metadata

Using .net Core 1.1, with the Microsoft.AspNetCore.OData libraries, I am able to get an OData endpoint working with my simple controller to perform get, $expand, and other queries. However, I can't get it to return the $metadata to be returned. This question ($Metadata with WebAPi OData Attribute Routing Not Working) is for the same problem, however the .Net APIs have changed since this was posted.
Is there a setting, flag, or something else I need to enable?
This (http://localhost:52315/odata) seems to return the meta data,
{
"#odata.context":"http://localhost:52315/odata/$metadata","value":[
{
"name":"Users","kind":"EntitySet","url":"Users"
},{
"name":"HelloComplexWorld","kind":"FunctionImport","url":"HelloComplexWorld"
}
]
}
this (http://localhost:52315/odata/$metadata) gives me the error:
An unhandled exception occurred while processing the request.
NotSupportedException: No action match template '$metadata'
in 'MetadataController'
Microsoft.AspNetCore.OData.Routing.Conventions.DefaultODataRoutingConvention.SelectAction(RouteContext routeContext)
My Startup.cs looks like this:
public void Configure(IApplicationBuilder app) {
app.UseDeveloperExceptionPage();
app.UseOData("odata");
app.UseMvcWithDefaultRoute();
}
public void ConfigureServices(IServiceCollection services) {
services.AddMvc().AddWebApiConventions();
services.AddSingleton<ISampleService, ApplicationDbContext>();
services.AddOData<ISampleService>(builder =>
{
builder.Namespace = "Sample";
builder.EntityType<ApplicationUser>();
builder.EntityType<Product>();
builder.Function("HelloComplexWorld").Returns<Permissions>();
});
}
NOTE: I can work around it by adding this at the start of my ConfigureServices(...) method, though it seems wrong given $metadata support should be part of the core platform.
app.Use(async (context, next) => {
if (0 == string.Compare(context.Request.Path, #"/odata/$metadata", true)) {
context.Request.Path = "/odata";
}
await next.Invoke();
});
I revisited this today and had more success using the Microsoft.AspNetCore.OData.vNext 6.0.2-alpha-rtm package. Referencing this example, the metadata and default OData routing worked as expected. My minimal configuration is:
public void ConfigureServices(IServiceCollection services)
{
services.AddOData();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Document>("Documents");
app.UseMvc(builder =>
{
builder.MapODataRoute("odata", modelBuilder.GetEdmModel());
});
}
The /odata/$metadata route should return "an XML representation of the service’s data model" (EDMX) (according to the OData v4 Web API documentation). This is not the same as the service root /odata/, which returns the top level description of resources published by the OData service (as shown in your example).
I encountered the same issue using the pre-release Microsoft.AspNetCore.OData 1.0.0-rtm-00015, since an official release is not yet available (see open issue on OData Web API repo).
To illustrate the point, you could manually emit the metadata, as in the crude example below. (You can find the InMemoryMessage class in the OData/odata.net GitHub repo.)
However, I would suggest waiting for an official release of OData ASP.NET Core as, quoting from the above issue, the "branch is still in its early stages and we may take a different approach once we have our architecture finalized". So things may well change... and $metadata should definitely work "out of the box"!
app.Use((context, func) =>
{
if (context.Request.Path.StartsWithSegments(new PathString("/data/v1/$metadata"), StringComparison.OrdinalIgnoreCase))
{
var model = app.ApplicationServices.GetService<IEdmModel>();
MemoryStream stream = new MemoryStream();
InMemoryMessage message = new InMemoryMessage() {Stream = stream};
ODataMessageWriterSettings settings = new ODataMessageWriterSettings();
ODataMessageWriter writer = new ODataMessageWriter((IODataResponseMessage)message, settings, model);
writer.WriteMetadataDocument();
string output = Encoding.UTF8.GetString(stream.ToArray());
return context.Response.WriteAsync(output);
}
return func();
});

Categories

Resources