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?
Related
There are API project and Worker project in the solution. The API project is written in net5.0 Microsoft.NET.Sdk.Web.
In Startup.cs
services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.IgnoreNullValues = true;
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); // for enum as strings
});
This code block is available in Startup.cs.
I also want to add these JsonOptions to net5.0 Worker project but Controller and Startup.cs are not available in worker project. How can i add?
I tried this
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
and this
services.AddMvc().AddJsonOptions(o =>
{
o.JsonSerializerOptions.PropertyNamingPolicy = null;
o.JsonSerializerOptions.DictionaryKeyPolicy = null;
});
but not works for me
AddJsonOptions are only used to bind/send json via endpoints, worker project does not expose any endpoints (at least by default), so there is no point adding them unless you resolve IOptions<JsonOptions> somewhere in the code directly. In this case you can always call Configure:
services.Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.IgnoreNullValues = true;
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); // for enum as strings
});
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?
I'm trying OpenIddict 3.0. I followed the steps in the documentation, created an Authorize controller, and added a test application. When I try to run I get this exception:
The OpenIddict ASP.NET Core server cannot be used as the default
scheme handler. Make sure that neither DefaultAuthenticateScheme,
DefaultChallengeScheme, DefaultForbidScheme, DefaultSignInScheme,
DefaultSignOutScheme nor DefaultScheme point to an instance of the
OpenIddict ASP.NET Core server handler
I cannot find what I'm doing wrong.
Here is my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
{
// Configure the context to use Microsoft SQL Server.
options.UseInMemoryDatabase("Identity");
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict<Guid>();
});
AddIdentityCoreServices(services);
services.AddOpenIddict()
// Register the OpenIddict core components.
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and models.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>()
.ReplaceDefaultEntities<Guid>();
})
// Register the OpenIddict server components.
.AddServer(options =>
{
// Enable the token endpoint (required to use the password flow).
options.SetTokenEndpointUris("/connect/token");
// Allow client applications to use the grant_type=password flow.
options.AllowPasswordFlow();
// Mark the "email", "profile" and "roles" scopes as supported scopes.
//options.RegisterScopes(OpenIddictConstants.Scopes.Email,
// OpenIddictConstants.Scopes.Profile,
// OpenIddictConstants.Scopes.Roles);
// Accept requests sent by unknown clients (i.e that don't send a client_id).
// When this option is not used, a client registration must be
// created for each client using IOpenIddictApplicationManager.
options.AcceptAnonymousClients();
// Register the signing and encryption credentials.
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
// Register the ASP.NET Core host and configure the ASP.NET Core-specific options.
options.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough() // Add this line.
.EnableTokenEndpointPassthrough()
.DisableTransportSecurityRequirement(); // During development, you can disable the HTTPS requirement.
})
// Register the OpenIddict validation components.
.AddValidation(options =>
{
// Import the configuration from the local OpenIddict server instance.
options.UseLocalServer();
// Register the ASP.NET Core host.
options.UseAspNetCore();
});
// ASP.NET Core Identity should use the same claim names as OpenIddict
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme;
});
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
private static void AddIdentityCoreServices(IServiceCollection services)
{
var builder = services.AddIdentityCore<ApplicationUser>();
builder = new IdentityBuilder(
builder.UserType,
typeof(ApplicationRole),
builder.Services);
builder.AddRoles<ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddSignInManager<SignInManager<ApplicationUser>>();
}
Please assist me on what I'm doing wrong.
I finally figured out where I went wrong. #Train Thanks for pointing me in the right direction.
changing the services.AddAuthentication(...) from
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme;
});
to
services.AddAuthentication(options =>
{
options.DefaultScheme = OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});
What's you're method of authentication? Cookie? JWT?
You need to change this line of code. You can't set OpenIddictServerAspNetCoreDefaults.AuthenticationScheme; as the default scheme
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme;
});
Default Authentication Scheme
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);
or overload
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
Here are the docs on Authentication with a lot more to read up on.
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...
I have following code inside Startup.cs and expecting it to override default serialization options. I want it to override every single serialization throughout my asp net core 2.0 project, but action return value that is not correct, I think this global property is not working in core 2.0
I have it written inside Configure exactly before app.UseMvc();
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Objects,
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Converters = new List<JsonConverter> { new StringEnumConverter() }
};
In ASP.NET Core, this is configured when wiring up the services on the application in Startup.ConfigureServices. There is an fluent AddJsonOptions(Action<MvcJsonOptions>) extension to the IMvcBuilder returned by the AddMvc() extension. MvcJsonOptions exposes a SerializerSettings property which you can configure in your action code.
So instead of configuring once before registering MVC, it's done as part of the MVC registration.
Example incorporating your setup:
services.AddMvc()
.AddJsonOptions( options =>
{
options.SerializerSettings.Formatting = Formatting.Indented;
options.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.Converters.Add(new StringEnumConverter());
});