I have a Blazor app that I want to use Azure app config.
I've successfully setup getting config values, however it doesn't find my feature flag.
When I inject an IConfiguration and query the value of a config value, like so Configuration["value"] the proper data is retrieved.
But when I try and check if my only feature flag is enabled (and it is) the result is always false, which I imagine is because the app can't find the feature flag, not because it's reading the value wrong (passing the name of a non-existant feature flag causes the method to return "false").
Startup.cs:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
using Microsoft.FeatureManagement;
namespace OreNoAppu
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));
services.AddControllersWithViews().AddMicrosoftIdentityUI();
// By default, all incoming requests will be authorized according to the default policy
services.AddAuthorization(options => options.FallbackPolicy = options.DefaultPolicy);
services.AddRazorPages();
services.AddServerSideBlazor().AddMicrosoftIdentityConsentHandler();
services.AddFeatureManagement();
services.AddAzureAppConfiguration();
}
// 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();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days.You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAzureAppConfiguration();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
Program.cs:
using Azure.Core;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using BoomiLogReader.Utility;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
namespace OreNoAppu
{
public class Program
{
public static void Main(string[] args)
{
InitKeyVault();
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
webBuilder.ConfigureAppConfiguration(config =>
{
var connection = KeyVaultReader.GetSecretValue("AzureAppConfigConnStr");
config.AddAzureAppConfiguration(options =>
options.Connect(connection).UseFeatureFlags());
}).UseStartup<Startup>());
// Initialises KeyVaultReader, which is used to retrieve secrets from Azure Key Vault.
public static void InitKeyVault()
{
// N'importe quoi, access to KeyVault and getting of the conn string works fine.
}
}
}
Code that should be getting the flag:
#using Microsoft.FeatureManagement
#inject IFeatureManager featureManager
#if (featureEnabled)
{
<h1>Yes</h1>
}
#code
{
bool featureEnabled = true;
protected override async Task OnInitializedAsync()
{
featureEnabled = featureManager.IsEnabledAsync("OreNoFlaggu").Result;
}
}
Debugging, I see that the method call "IsEnabledAsync" returns "false", but there is a "OreNoFlaggu" feature flag in my app config, that the application successfully connects and retrieves config values from, and said flag is enabled.
Any idea why it isn't working?
#Tessaract, does your feature flag happen to have a label in your App Config store. If so, please don't forget to pass the label when calling UseFeatureFlags() via FeatureFlagOptions.Label.
I want to enable CORS with Asp.Net Core 3.0 API project. This is the basic generated Asp.Net Core Api template. Everything is default from the template, except I added CORS settings from the documentation: Enable Cross-Origin Requests (CORS) in ASP.NET Core
Here it is my Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.WithOrigins("localhost", "www.google.com")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
}
// 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.UseCors("CorsPolicy");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
And these are my response headers:
What should I set up for getting corret CORS headers in Response?
Here it is my fetch api test:
Oops, I successed to solve this.
This combination was the only one to me, what is working:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddCors(); //This needs to let it default
}
// 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.UseCors(
options => options.SetIsOriginAllowed(x => _ = true).AllowAnyMethod().AllowAnyHeader().AllowCredentials()
); //This needs to set everything allowed
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
If you put the API URL directly in the browser, CORS is not involved.
It isn't a cross-origin request.
That only happens when you have a page hosted at one origin, e.g. localhost:5000, which has JavaScript code that calls an API at origin localhost:5001.
(or otherwise fetches resources from another origin)
But in your case the only origin is the API origin and thus CORS is not needed.
I have just created a default dotnet core 3.0 API project with the basic weather forecast API. I wanted to get CORS working before I did anything else with the project.
In startup i have the following code....
private readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
}
// 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.UseCors(MyAllowSpecificOrigins);
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
As you can see, I am not doing anything special or seemingly incorrect. This is directly from the MSDN documentation....
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.0
The problem is that when sending requests through both the browser and postman, There are none of the expected headers in the given responses.
I have googled the crap out of this and have not got anywhere. Am i missing something? could it be environmental? has it changed from a previous version of core?
I had an Asp.Net core 2.2 project.
Recently, I changed the version from .net core 2.2 to .net core 3.0 Preview 8. After this change I see this warning message:
using 'UseMvc' to configure MVC is not supported while using Endpoint
Routing. To continue using 'UseMvc', please set
'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices'.
I understand that by setting EnableEndpointRouting to false I can solve the issue, but I need to know what is the proper way to solve it and why Endpoint Routing does not need UseMvc() function.
I found the solution, in the following official documentation "Migrate from ASP.NET Core 2.2 to 3.0":
There are 3 approaches:
Replace UseMvc or UseSignalR with UseEndpoints.
In my case, the result looked like that
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//Old Way
services.AddMvc();
// New Ways
//services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}");
});
}
}
OR
2. Use AddControllers() and UseEndpoints()
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
OR
3. Disable endpoint Routing. As the exception message suggests and as mentioned in the following section of documentation: use mvcwithout endpoint routing
services.AddMvc(options => options.EnableEndpointRouting = false);
//OR
services.AddControllers(options => options.EnableEndpointRouting = false);
This worked for me (add in Startup.cs > ConfigureServices method):
services.AddMvc(option => option.EnableEndpointRouting = false)
but I need to know what is the proper way to solve it
In general, you should use EnableEndpointRouting instead of UseMvc, and you could refer Update routing startup code for detail steps to enable EnableEndpointRouting.
why Endpoint Routing does not need UseMvc() function.
For UseMvc, it uses the IRouter-based logic and EnableEndpointRouting uses endpoint-based logic. They are following different logic which could be found below:
if (options.Value.EnableEndpointRouting)
{
var mvcEndpointDataSource = app.ApplicationServices
.GetRequiredService<IEnumerable<EndpointDataSource>>()
.OfType<MvcEndpointDataSource>()
.First();
var parameterPolicyFactory = app.ApplicationServices
.GetRequiredService<ParameterPolicyFactory>();
var endpointRouteBuilder = new EndpointRouteBuilder(app);
configureRoutes(endpointRouteBuilder);
foreach (var router in endpointRouteBuilder.Routes)
{
// Only accept Microsoft.AspNetCore.Routing.Route when converting to endpoint
// Sub-types could have additional customization that we can't knowingly convert
if (router is Route route && router.GetType() == typeof(Route))
{
var endpointInfo = new MvcEndpointInfo(
route.Name,
route.RouteTemplate,
route.Defaults,
route.Constraints.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value),
route.DataTokens,
parameterPolicyFactory);
mvcEndpointDataSource.ConventionalEndpointInfos.Add(endpointInfo);
}
else
{
throw new InvalidOperationException($"Cannot use '{router.GetType().FullName}' with Endpoint Routing.");
}
}
if (!app.Properties.TryGetValue(EndpointRoutingRegisteredKey, out _))
{
// Matching middleware has not been registered yet
// For back-compat register middleware so an endpoint is matched and then immediately used
app.UseEndpointRouting();
}
return app.UseEndpoint();
}
else
{
var routes = new RouteBuilder(app)
{
DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
};
configureRoutes(routes);
routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));
return app.UseRouter(routes.Build());
}
For EnableEndpointRouting, it uses EndpointMiddleware to route the request to the endpoints.
The issue I found to be due to updates on the .NET Core framework. The latest .NET Core 3.0 released version requires explicit opt-in for using MVC.
This issue is most visible when one tries to migrate from older .NET Core(2.2 or preview 3.0 version) to .NET Core 3.0
If migrating from 2.2 to 3.0, please use the below code to fix the issue.
services.AddMvc(options => options.EnableEndpointRouting = false);
If using .NET Core 3.0 template,
services.AddControllers(options => options.EnableEndpointRouting = false);
ConfigServices method after fix as below,
Thank You
Endpoint Routing is disabled by default on ASP.NET 5.0
Just configure as in Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options => options.EnableEndpointRouting = false);
}
This worked for me
You can use :
in ConfigureServices method:
services.AddControllersWithViews();
And for Configure method:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//Old Way
services.AddMvc();
// New Ways
//services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}");
});
}
}
This works also in .Net Core 5
For DotNet Core 3.1
Use below
File : Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
-> In ConfigureServices method - Startup.cs
//*****REGISTER Routing Service*****
services.AddMvc();
services.AddControllers(options => options.EnableEndpointRouting = false);
-> In Configure Method - Startup.cs
//*****USE Routing*****
app.UseMvc(Route =>{
Route.MapRoute(
name:"default",
template: "{Controller=Name}/{action=Name}/{id?}"
);
});
This worked for me
services.AddMvc(options => options.EnableEndpointRouting = false); or
OR
services.AddControllers(options => options.EnableEndpointRouting = false);
Use Below Code
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
I am trying to use the Azure SignalR Service in a web app that only contains a hub class. When I try to access from another domain to the hub I get the following error
"Access to XMLHttpRequest at 'https://*/genericSocketHub/negotiate' from origin 'https://localhost:44303' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.".
In the startup.cs class of my project I have:
` public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddCors(o => o.AddPolicy("Policy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
}));
services.AddSignalR().AddAzureSignalR(Configuration.GetConnectionString("AzureSignalRConnectionString")).AddJsonProtocol(options => options.PayloadSerializerSettings = new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = new DefaultContractResolver()});
services.AddSingleton(Configuration);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCors("Policy");
app.UseAzureSignalR(routes =>
{
routes.MapHub<GenericSocketHub>("/genericSocketHub");
});
app.UseMvc();
}
}`
Without using Azure SignalR Service I didn't have any CORS issues
Try adding .WithOrigins("[THE_DOMAIN_TO_UNBLOCK]"); to your policy:
services.AddCors(o => o.AddPolicy("Policy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.WithOrigins("[THE_DOMAIN_TO_UNBLOCK]");
}));
Also make sure that you have the latest version of Microsoft.Asure.SignalR installed on the server along with the latest #aspnet/signalr installed on the client.
NOTE The signalr npm package is not compatible with Azure SignalR. I learned this the hard way..
The following worked for my setup which is Angular7, .NET CORE 2.1 and Azure SignalR. My setup looks like this:
ConfigureServices
// Add CORS
services.AddCors(options =>
{
options.AddPolicy("AllowAllOrigins",
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowCredentials()
.AllowAnyMethod()
.WithOrigins("http://localhost:4200");
});
});
// Add Azure SignalR
services.AddSignalR().AddAzureSignalR();
Configure
app.UseCors("AllowAllOrigins");
app.UseAzureSignalR(routes =>
{
routes.MapHub<NextMatchHub>("/nextmatch");
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "api/{controller=Home}/{action=Index}/{id?}");
});
NOTE Make sure that the various implementations are added in the same order as my example shows above. I cannot explain why it is sensitive about the order but this was also an issue on my end.