How can i add net5.0 Worker Application AddJsonOptions - c#

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
});

Related

How to configure json Name Case policy while using MinimalApi

I'm trying to get result from my minimal API who configured in endpoints of my MVC web application
my Get action configured like this :
endpoints.MapGet(
"HO-CFDZU4/api/Currency/Get",
[PermissionAuthorize(PermissionName.ReadCurrencyDictionary)]
async ([FromServicesAttribute] CurrencyService curency) =>
{
var result = await DataSourceLoader.LoadAsync(curency.Get(), new DataSourceLoadOptions());
return Results.Ok(result);
});
As result i get response with object where property names changed to lowercase, and its not suit for me.
I want to get exactly same name in same case like i return form action.
To get similar effect in MVC i used this code :
services
.AddMvc()
.AddFluentValidation(x => x.RegisterValidatorsFromAssembly(AppDomain.CurrentDomain.GetAssemblies().Where(x => x.FullName.Contains("ApplicationCore")).Single()))
.AddMvcLocalization()
.AddMvcOptions(options =>{})
.AddRazorRuntimeCompilation()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
Which setup property naming policy for Json while using action in controllers, and i dont know how to setup same policy for minimalApi.
What Ive tried is to set [JsonPropertyName(name)] And it working good but we have lot of classes and i looking for more global solution.
I also tried configure JsonOptions globally like this:
services.Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
But it do nothing
Use JsonOptions from Microsoft.AspNetCore.Http.Json namespace (docs):
services.Configure<JsonOptions>(options =>
{
options.SerializerOptions.PropertyNamingPolicy = null;
options.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
UPD
If your application uses both Minimal APIs endpoints and MVC ones, then you try to configure options from both namespaces:
services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(options =>
{
options.SerializerOptions.PropertyNamingPolicy = null;
options.SerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
services.Configure<Microsoft.AspNetCore.Mvc.JsonOptions>(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});

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...

migration project from netcore2.2 to netcore3.0

I have a project with Identity Server 4 in netcore2.2
Now I want to migrate to netcore3.0
I have install sdk hosting bundle and so on...
Change version sdk in appsetting change target framework
If I compile tell me ok but...
my old startup.cs have in ConfigureService this call:
services.AddMvc(options => options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build())))
.AddJsonOptions(options =>
{
options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Include;
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});
and netcore 3.0 tell me that options.SerializerSettings.DefaultValueHandling
and options.SerializerSettings.NullValueHandling
they are not recognized as valid
so I take out... another problem is that when with debug see the different step the breakpoint inside this call doesn't enter
'
services.AddDbContext<DBPLATFORMContext>(options =>
{
options.UseSqlServer(connectionString,
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(maxRetryCount: 5,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
});
});
and when I go to start my indexpage
in Configure
by
'
app.Use(async (context, next) => {
await next();
if (context.Response.StatusCode == 404 &&
!Path.HasExtension(context.Request.Path.Value) &&
!context.Request.Path.Value.StartsWith("/api/"))
{
context.Request.Path = "/index.html";
await next();
});
variable context give me response 404 and contenttype is null
Could you help me? Thanks

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?

ASP.NET Core web service does not load appsettings.json into configuration

I have an ASP.NET Core 2.1 Web Application with Razor Pages which has AAD authentication information defined in the appsettings.json file (courtesy of the default application template - see below on how I got there). However, when trying to configure the authentication in Startup.cs the configuration does not have any of the config values from my appsettings.json. If I inspect the IConfiguration object in the debugger then it appears to only have the environment variable configurations:
Here's the Startup.ConfigureServices method where the issue lies:
public void 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.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options =>
{
// This is from the default template. It should work, but the relevant settings aren't there so options isn't populated.
this.Configuration.Bind("AzureAd", options);
// This of course works fine
options.Instance = "MyInstance";
options.Domain = "MyDomain";
options.TenantId = "MyTenantId";
options.ClientId = "MyClientId";
options.CallbackPath = "MyCallbackPath";
});
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
And the service configuration in case it's important (note that this is being built on top of a service fabric stateless service):
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
listenOptions.UseHttps(GetCertificateFromStore());
listenOptions.NoDelay = true;
});
})
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
};
}
To create this service, I used the wizard in VS2017. I selected an existing service fabric project (.sfproj) and chose Services > Add > New Service Fabric Service and chose Stateless ASP.NET Core [for .NET Framework], then on the next page I chose Web Application (the one with Razor Pages, not MVC) and clicked Change Authentication where I chose Work or School Accounts and entered my AAD info. The only changes I have made to this template were adding the code inside the call to AddAzureAD in Startup.ConfigureServices and setting the appsettings.json files to always be copied to the output directory.
Why doesn't the appsettings.json file get loaded into the configuration? As I understand, this is supposed to happen by default, but something seems to be missing...
WebHostBuilder doesn't load appsettings.json by default, you need to manually call AddJsonFile. For example:
return new WebHostBuilder()
.UseKestrel(opt =>
{
//snip
})
.ConfigureAppConfiguration((builderContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: false);
})
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
Alternatively you can use WebHost.CreateDefaultBuilder which will load more defaults.
Another approach, would be to manually create the configuration via ConfigurationBuilder then use the UseConfiguration method.
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.Build();
var host = new WebHostBuilder()
.UseConfiguration(configuration)
.UseKestrel()
.UseStartup<Startup>();
The primary intent is core to provide a bit of flexibility when implementing, they often error on less is more. You have to explicitly say what you would like, that way the pipeline remains relatively small.
For others like me who find this issue:
It might be that you're not copying the appsettings.json file during build.
The OP does say he's doing this, but it's kind of a small print thing - and was what I was failing to do.
The more you know ...
Below mentioned steps worked for me
Go to Appsettings.json
Right click and goto properties
select the build action from the drop down to none if its content
Make the copy to Output directory as Copy Always
As mentioned before WebHostBuilder do not execute this default behavior CreateDefaultBuilder needs to be called instead.
I prefer following implementation:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
try
{
logger.LogInformation("Starting up");
host.Run();
}
catch (Exception ex)
{
logger.LogCritical(ex, "Application start-up failed");
}
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
Make sure your file name is all lower case.
My mistake was to name the file appSettings.json instead of appsettings.json. When running within a Linux container, the camel-cased file was not loaded.

Categories

Resources