IHttpContextAccessor.HttpContext is null - .net-core

I'm using DotNet 5.0, and even though I register HttpContextAccessor in the Startup.ConfigureServices whenever I try to reach it inside the code, IHttpContextAccessor.HttpContext is always null.
This is my Startup.cs file's ConfigureServices Method
public void ConfigureServices(IServiceCollection services)
{
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
this.Configuration = new ConfigurationBuilder().SetBasePath(System.IO.Directory.GetCurrentDirectory()).AddJsonFile($"appsettings.{environmentName}.json").Build();
services.AddControllers();
services.AddSimpleInjector(container, options =>
{
options.AddAspNetCore();
});
services.AddHttpContextAccessor();
}
And this is the Configure method of the same file:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSimpleInjector(container);
container.Verify();
}
And also I'm using hangfire, but whenever a job gets triggered I cannot reach HttpContextAccessor through dependency injection. It is always null.
For example this is one of my business layer files:
public class FooService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public FooService(IHttpContextAccessor httpContextAcessor)
{
_httpContextAccessor = httpContextAccessor;
}
public DoSomething()
{
var tryoutVar = _httpContextAccessor.HttpContext;
}
}
The tryoutVar variable is set to null, always.
Why is this happening?

Related

How to get Blazor HotReload to work with Startup class

I have a Blazor WebAssembly app which is hosted by a .net Core app. I've been upgrading it from .net 6.0 and was using a Startup class to initialize the server app
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args)
.Build()
.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureHostConfiguration(conf =>
{
conf.AddJsonFile($"appsettings.{Environment.MachineName}.json", optional: true, reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
WebHostEnvironment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment WebHostEnvironment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddRazorPages();
/*Other services registered here*/
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Configure the HTTP request pipeline.
if (env.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
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.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
}
Now when I run this app, I can't get hot reloading of Blazor or CSS at all.
What I've found is that if I use the newer pattern implementing WebApplication.CreateBuilder, hot reloading works.
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
ConfigureServices(builder.Services, builder.Configuration);
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
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.UseBlazorFrameworkFiles();
app.UseStaticFiles();
var imagesPhysicalPath = app.Configuration.GetSection("ImagesDirectoryPath").Get<string>(); ;
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
RequestPath = "/product-images",
FileProvider = new PhysicalFileProvider(imagesPhysicalPath)
});
app.UseRouting();
app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile("index.html");
app.Run();
}
I marginally prefer the former version as it allows me to customise the Configuration mechanism.
Can anyone tell me what I'm missing in the original setup that might have broken the hot reload process?

No operations defined in spec! asp .net core 3.1, swagger is not showing controller

I tried this and also this several links but not getting the answer.
this is my startup.cs file
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddCommonService(Configuration);
services.AddSecurityServiceRepositories();
services.AddSwaggerService();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwaggerService();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseStaticFiles();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
//app.UseMvc();
}
Adding service class, it adds the repositories
namespace Microsoft.Extensions.DependencyInjection
{
public static class SecurityServiceRepositoryCollectionExtension
{
public static IServiceCollection AddSecurityServiceRepositories(this
IServiceCollection
services)
{
services.AddTransient<IUserRepository, UserRepository>();
return services;
}
}
}
this is my swagger class file, it adds and uses the basic swagger service
namespace Microsoft.Extensions.DependencyInjection
{
public static class SwaggerServiceExtension
{
public static IServiceCollection AddSwaggerService(this IServiceCollection services)
{
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Sample API",
Version = "v1",
Description = "REST API for Sample "
});
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = #"JWT Authorization header using the Bearer scheme. \r\n\r\n
Enter 'Bearer' [space] and then your token in the text input below.
\r\n\r\nExample: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header
},
new List<string>()
}
});
});
return services;
}
public static IApplicationBuilder UseSwaggerService(this IApplicationBuilder app)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Sample Api V1");
});
return app;
}
}
}
This is my controller, I have tried the both attribute
[Route("api/[controller]")]
[ApiController]
public class UserController : SecuredRepositoryController<IUserRepository>
{
public UserController(IUserRepository repository) : base(repository) { }
[HttpPost("register-user")]
// [Route("register-user")] I also tried this routing
[AllowAnonymous]
[ProducesResponseType(typeof(User), 200)]
public async Task<IActionResult> AddNewUser([FromBody] User user)
{
try
{
var result = await this.Repository.RegisterUser(user);
return Ok(result);
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
}
This is coming on swagger UI instead of Controller, check the screenshot
In my case I had to reference the project to the Host project which contains the Program
I encountered this error when creating a new ASP.NET core web api project, but forgot to check "Use controllers (uncheck to use minimal APIs)" in Visual Studio. Recreating the project with that box checked solved the issue for me.

Api Routing in .net core 3.0

I am new to .net core and I want to set a MapRoute to my api.
I config endpoint in startup.cs like
app.UseEndPoints(endpoints=>{
endpoints.MapController("defaultApi","v1/{controller="cont"}/{action}/{id?}");
endpoints.MapController("defaultNonActionApi","v1/{controller="cont"}/{id?}")l
endpoints.MapHealthChecks("/healthz");
});
and in controller.cs
[ApiController]
[Route("[controller]")]
public class contController:ControllerBase{
[HttpGet]
public ActionResult Get(){}
}
The config in useEndpoints is useless, if I goto https://localhost:port/v1/cont it return a 404 and if i goto https://localhost:port/cont it can return an expected result.
It seems like the RouteAttribute override the config in useEndpoints but I can't remove RouteAttribute for an ApiController.
I know change Route("[controller]") to Route("v1/[controller]") can solve this problem, but what I want is something more global that can be configured in startup.cs.
Thanks.
Here is a simple demo like below:
1.Create a custom MvcOptionsExtensions:
public static class MvcOptionsExtensions
{
public static void UseGeneralRoutePrefix(this MvcOptions opts, IRouteTemplateProvider routeAttribute)
{
opts.Conventions.Add(new RoutePrefixConvention(routeAttribute));
}
public static void UseGeneralRoutePrefix(this MvcOptions opts, string prefix)
{
opts.UseGeneralRoutePrefix(new RouteAttribute(prefix));
}
}
public class RoutePrefixConvention : IApplicationModelConvention
{
private readonly AttributeRouteModel _routePrefix;
public RoutePrefixConvention(IRouteTemplateProvider route)
{
_routePrefix = new AttributeRouteModel(route);
}
public void Apply(ApplicationModel application)
{
foreach (var selector in application.Controllers.SelectMany(c => c.Selectors))
{
if (selector.AttributeRouteModel != null)
{
selector.AttributeRouteModel = AttributeRouteModel.CombineAttributeRouteModel(_routePrefix, selector.AttributeRouteModel);
}
else
{
selector.AttributeRouteModel = _routePrefix;
}
}
}
}
2.Register in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(o => { o.UseGeneralRoutePrefix("v1"); });
}
// 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.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
3.Controller:
[ApiController]
[Route("[controller]")]
public class contController:ControllerBase{
[HttpGet]
public ActionResult Get(){}
}

Swagger failing with Failed to load API definition (yet another thread)

I tried to add swagger to an existing api and after failing alot, i decided to create a new solution, create a new asp.net core 2.2 api and added swagger as per
https://learn.microsoft.com/en-us/aspnet/core/tutorials/getting-started-with-swashbuckle?view=aspnetcore-2.2&tabs=visual-studio
The other posts regarding this issue seem all to indicate a situation where there are multiple httpverbs or none, which is not the case with the default valuescontroller. It gives me the error
Failed to load API Definition.
Fetch error, Service unavailable /swagger/v1/swagger.json
The actual json file at api/swagger/v1/swagger.json actually renders correctly
My startup class is
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSwaggerGen(c =>{
c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
app.UseMvc();
}
}
Im using Swachbuckle.AspNetCore v 4.01.
String SwaggerEndpoint = "/swagger/v1/swagger.json";
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
SwaggerEndpoint = "/andi/swagger/v1/swagger.json";
}
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint(SwaggerEndpoint, "My API");
//options.RoutePrefix = string.Empty;
});

Google authentication with cookies (without DB) in ASP.Net Core 2

I want to authenticate users using Google and persist authentication using cookies.
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.AddMvc();
services.AddMediatR(typeof(UpdateClientsCommandHandler));
services
.AddEntityFrameworkSqlServer()
.AddDbContext<DbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
sqlOptions.EnableRetryOnFailure(10, TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
});
options.EnableSensitiveDataLogging();
}
);
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "YourCustomScheme";
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie("YourCustomScheme")
.AddGoogle(options =>
{
options.ClientId = "client-id";
options.ClientSecret = "client-secret";
options.CallbackPath = new PathString("/AuthCallback/IndexAsync");
options.SignInScheme = "YourCustomScheme";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseAuthentication();
}
}
The user is successfully redirected to Google Auth and I can see that cookie .AspNetCore.YourCustomScheme is created. But then the user is just redirected back to the Google login page.
Am I missing something?
It appears that my problem is caused by the fact that I put UseAuthentication after UseMvc

Resources