.NET CORE 3 Upgrade CORS and Json(cycle) XMLHttpRequest Error - json

I had my working project written in asp.net core 2.1 for a long time, but yesterday, I was forced to upgrade it to .net core 3.0 (due to 2.1 cannot call Dll' s which are written in 3.0 already).
With that, a lot of functions were obsolete or already removed. I fixed almost all of it, but one problem with CORS.
Like many people before me, I used:
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
in Configure function. And services.AddCors() in ConfigureServices function.
I was able to fixed this quite easily with setting WithOrigins() or .SetIsOriginAllowed(_ => true) instead of AllowAnyOrigin() which does not work anymore with AllowCredentials().
After that, I was able to start the application and I thought everything is fine, but then I get stuck until now with problem I do not know, how to fix.
I have DB relation N:N and relation table which handle that, that means I have Admin entity with AdminProject list property, then I have AdminProject entity with Admin list and Project list properties and Project entity with AdminProject list property once again.
When I am listing my projects of certain admin, I am returning in Controller this return Ok(projects), where I just use getAll on AdminProject entity and then with Select return only project.
For that, I have to use[JsonIgnore] in project/admin for properties which I do not need to avoid cycling when creating json.
With that said: NOW IN .NET CORE 3.0 AND CORS SETTINGS IT DOES NOT WORK.
I am getting an error:
System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
when debugging in console and error Access to XMLHttpRequest at 'http://localhost:5000/api/project/adminlist/1' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. in WEB browser
I think I tried almost everything with Cors settings etc and I do not know why is this happening now. I also tried to JsonConvert.SerializeObject() before return it ---> return Ok(JsonConvert.SerializeObject(projects)) and this is working, but I am not able (mentally) to do this in every single controllers functions.
Please help! Thanks a lot!

The problem was occurring because in .NET Core 3 they change little bit the JSON politics. Json.Net is not longer supported and if you want to used all Json options, you have to download this Nuget: Microsoft.AspNetCore.Mvc.NewtonsoftJson.
After that in your Startup.cs file change/fix/add line where you are adding MVC (in the ConfigureServices method.
So: here is what I did and what fixed my issue:
services.AddMvc(option => option.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddNewtonsoftJson(opt => opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
I hope it will help somebody else.
Cheers!

A couple other things have changed in .net core 3 and now instead of using addMVC you can use addControllers. So your code might look like the follow:
services.AddControllers().AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

Related

Blazor WebAssembly JsonException: A possible object cycle was detected which is not supported

I get this error because I have circular references defined in my object model. My question is, is there any way to resolve this using one of the following two options?
Using Newtonsoft.Json and options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
Using System.Text.Json and options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve;
I'm not seeing a way to switch to Newtonsoft.Json in a Blazor WebAssembly application and I tried implementing option 2 in the ConfigureServices function of Startup.cs in my Server project but I still kept getting the error.
I'm just trying to find a solution that doesn't require me redefining my object model. The JsonIgnore attribute does not appear to be an option either because I assume, and it appears, that then any fields I define it on do not exist in the Json on the client which breaks my application.
Update: I found this site which looks to me like discusses exactly what I'm referring to here and how to implement the solution but I have not got it to work yet. If anyone is successfully using Blazor WebAssembly with circular references in your object model please let me know what you're doing.
https://github.com/dotnet/aspnetcore/issues/28286
Thank you for pointing out this error in Blazor. I found the answer in the issue you mentioned (this comment). You need to change json options also on the Client side. This works for me:
On server
services.AddControllersWithViews().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve;
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
On client
var response = await Http.GetFromJsonAsync<T>("{Address}", new JsonSerializerOptions
{
ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve,
PropertyNamingPolicy = null
});
To the two options you mentioned there is a third option available if you use .NET 6 or above.
Using System.Text.Json and options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
Beware that ignoring cycles have issues on its own (such as data corruption) but if you were depending on it when you were using Newtonsoft.Json then you will be fine as it is basically the same behavior.
If you prefer to go with ReferenceHandler.Preserve, please share more info on what error you are getting and I can try to help you out.
One way to go about this is specify how much depth an object is allowed to have. Please see the documentation here regarding how to do this with System.Text.Json. I think this may help.

Library class doesn't know of ConfigureWebHostDefaults extension method

I'm building a suite of REST micro-services using .Net Core 3.0 Preview 6. All these services will have the same start up logic. So, I'm trying to place all the code in a .Net Standard library.
The goal is to have the IHostBuilder:CreateHostBuilder method, as well as the Startup:Configure and Startup:ConfigureServices class and methods in the library. The library will also contain error handling logic, customized http response messages, etc.
However, I can't seem to find the correct package that contains the ConfigureWebHostDefaults method. I tried adding the Microsoft.AspNetCore package 2.2.0, but that didn't resolve the issue.
I added the Microsoft.Extensions.Hosting (3.0.0-preview-6) package, that also doesn't resolve the issue.
Is what I'm attempting even possible?
Thanks
-marc
I resolved it, not the best way, but it works. I decided to make the library targeted specifically for .NET Core 3.0. So, I changed the targetframework in the project file. That change automatically resolved my other issue.
Import the Microsoft.AspNetCore package, and use WebHost.CreateDefaultBuilder() instead. According to the code it is built from, both CreateDefaultBuilder() and ConfigureWebHostDefaults() call the same internal method: ConfigureWebDefaults().
The only downside of this is that the returned host will be an IWebHost instead of an IHost.

Windsor WcfFacility: Setting ServiceBehavior properties

I'm hosting a service using Windsor's WCF Facility, but I can't get UseSynchronisationContext and ConcurrencyMode set that one would normally do using the ServiceBehaviorAttribute. I've seen two options that apparently should work (but tried both to no avail):
Registering ServiceBehaviorAttribute as a Component for IServiceBehavior
Modifying the Description collection of Behaviors in the OnCreated configuration callback in the WCF registration.
A third method that I've tried is using AddExtensions, but that results in an exception because there's already a ServiceBehaviorAttribute (by default?) in the list of Behaviors. This is also the case with method 2, but in that case I can remove it and add a new one, or modify the existing entry.
It's really frustrating that there doesn't seem any documentation on this except a line stating 'Remove the ServiceBehaviorAttribute' from your services, apparently because it can conflict with the WcfFacility.
Can someone point me on how to properly do this? Any hint is appreciated!
Unfortunately I didn't properly test. Modifying the properties of the ServiceBehaviorAttribute in the list of Behaviors of the Description property in the OnCreated action actually works as intended.
Sample registration:
container.Register(Component.For<IWCFWarehouseServiceAsyncCallback>()
.ImplementedBy<WarehouseService>()
.AsWcfService(new DefaultServiceModel()
.AddBaseAddresses(baseAddress)
.OnCreated(host =>
{
var sb = host.Description.Behaviors.Find<ServiceBehaviorAttribute>();
sb.UseSynchronizationContext = false;
sb.ConcurrencyMode = ConcurrencyMode.Reentrant;
})
.AddEndpoints(WcfEndpoint.BoundTo(binding).At("WarehouseService"))));

"Calling 'Read' when the data reader is closed is not a valid operation.", but only on one of the Include paths

I'm using the Entity Framework in C# with a MySQL back-end. Here's the problem section of the code:
using (var entities = new myEntities()) {
Parties = new ObservableCollection<t_party>(
entities.SalesParties
.Include("SalesReps")
.Include("InventoryReservation")
.Include("InventoryReservation.InventoryAssignment")
.Include("InventoryReservation.InventoryAssignment.Inventory")
.ToList()
);
}
When the code runs, I get an error: "Calling 'Read' when the data reader is closed is not a valid operation." The interesting part is that if I remove the .Include("SalesReps") it works just fine. SalesReps and InventoryReservation are both 0..1 multiplicity from the SalesParty end and * from the other end.
I'm using the Entity Framework 4.1 with the "MySQL Connector Net 6.3.7" library. I tried 6.4.x initially, but ran into some other problems between it and the Entity Framework and had to roll back.
The truly mystifying thing is that I recently switched laptops, and it was running fine on the old one! The old one was running Windows 7 on a 32-bit processor, the new one is 64-bit. Not sure if that would affect things by using different libraries, but it's the only other variable I can think of.
I also got the same issue and found that once the using block has been executed, the entities variable will be disposed. So if you try to use it again outside of the block, you will get this error. To solve this problem create entities variable without any using block and then try to run the code.

JSF 2.0 Custom Exception Handler

I’m struggling fully understanding when/how exceptions are thrown in JSF 2.0. I’ve looked for a solution longer than I care to admit. Ultimately, the goal I want to achieve is “handle” an unhandled exceptions. When an exception is thrown, I want to be able to capture information of interest about the exception, and email that to the appropriate site administrators. I’m forcing an error by throwing a new FacesException() in the constructor of one of my backing beans. I had this working great in JSF 1.1 using MyFaces implementation. I was able to get this working by wrapping the Default Lifecycle and simply overriding the execute() and render() methods. I followed this awesome post by Hanspeter to get that working:
"http://insights2jsf.wordpress.com/2009/07/20/using-a-custom-lifecycle-implementation-to-handle-exceptions-in-jsf-1-2/#comment-103"
I am now undergoing a site upgrade to JSF 2.0 using Mojarra’s. And things work great still as long as the exception is thrown/caught in the execute() method, however; the moment I enter the render(), the HttpServletResponse.isCommitted() equals true, and the phase is PhaseId RENDER_RESPONSE which of course means I can’t perform a redirect or forward. I don’t understand what has changed between JSF 1.1 and 2.0 in regards to when/how the response is committed. As I indicated, I had this working perfectly in the 1.1 framework.
After much searching I found that JSF 2.0 provides a great option for exception handling via a Custom ExceptionHandler. I followed Ed Burns’ blog, Dealing Gracefully with ViewExpiredException in JSF2:
"http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2"
As Ed indicates there is always the web.xml way by defining the tag and what type of exception/server error code and to what page one wants sent to for the error. This approach works great as long as I’m catching 404 errors. One interesting thing to note about that however, is if I force a 404 error by typing a non-exsitant URL like /myApp/9er the error handler works great, but as soon as I add “.xhtml” extension (i.e. /myApp/9er.xhtml) then the web.xml definition doesn’t handle it.
One thing I noticed Ed was doing that I hadn’t tried was instead of trying to do a HttpServletRespone.sendRedirect(), he is utilizing the Navigationhandler.handleNavigation() to forward the user to the custom error page. Unfortunately, this method didn’t do anything different than what Faclets does with the error by default. Along with that of course, I was unable to do HttpServletResponse.sendRedirect() due to the same problems as mentioned above; response.isCommitted() equals true.
I know this post is getting long so I will make a quick note about trying to use a PhaseListener for the same purposes. I used the following posts as a guide with this route still being unsuccessful:
"http://ovaraksin.blogspot.com/2010/10/global-handling-of-all-unchecked.html" "http://ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-session-timeout.html"
All and all I have the same issues as already mentioned. When this exception is thrown, the response is already in the committed phase, and I’m unable to redirect/forward the user to a standard error page.
I apologize for such a long post, I’m just trying to give as much information as possible to help eliminate ambiguity. Anyone have any ideas/thoughts to a work around, and I’m curious what might be different between JSF 1.1 and 2.0 that would cause the response to be committed as soon as I enter the render() phase of the Lifecycle.
Thanks a ton for any help with this!!!
So this question is actually not just about a custom exception handler (for which JSF 2 has the powerful ExceptionHandlerFactory mechanism), but more about showing the user a custom error page when the response has already been committed.
One universal way to always be able to redirect the user even if the last bit has already been written to the response is using a HttpServletResponse wrapper that buffers headers and content being written to it.
This does have the adverse effect that the user doesn't see the page being build up gradually.
Maybe you can use this technique to only capture the very early response commit that JSF 2.0 seems to do. As soon as render response starts, you emit the headers you buffered till so far and write out the response content directly.
This way you might still be able to redirect the user to a custom error page if the exception occurs before render response.
I have successfully implemented a filter using response wrapper as described above which avoids the response being commited and allows redirection to a custom page even on an exception in the middle of rendering the page.
The response wrapper sets up its own internal PrintWriter on a StringWriter, which is returned by the getWriter method so that the faces output is buffered. In the happy path, the filter subsequently writes the internal StringWriter contents to the actual response. On an exception, the filter redirects to an error jsp which writes to the (as yet uncommitted) response.
For me, the key to avoiding the response getting committed was to intercept the flushBuffer() method (from ServletResponse, not HttpServletResponse), and avoid calling super.flushBuffer(). I suspect that depending on circumstances and as noted above, it might also be necessary to also override some of the other methods, eg the ones that set headers.