Problems encountered using Autofac - c#

Program.cs
var builder = WebApplication.CreateBuilder(args);
// Use Autofac
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Replace the default controller activator
//builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, CustomControllerActivator>());
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
CustomControllerActivator.cs
public class CustomControllerActivator : IControllerActivator
{
public object Create(ControllerContext context)
{
// `serviceProvider` the object is `Autofac.Extensions.DependencyInjection.AutofacServiceProvider` type
var serviceProvider = context.HttpContext.RequestServices;
...
}
public void Release(ControllerContext context, object controller)
{
...
}
}
WeatherForecastController.cs
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
private readonly IServiceScope serviceProvider;
public WeatherForecastController(ILogger<WeatherForecastController> logger,IServiceProvider serviceProvider)
{
_logger = logger;
//`serviceProvider` the object is `Autofac.Extensions.DependencyInjection.AutofacServiceProvider` type
serviceProvider = serviceProvider;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
I checked the source code and didn't see you replace 'IControllerActivator' or 'IControllerActivatorProvider', so I don't quite understand how you operate the activation of the controller
I don't understand how you replace the object of 'HttpContext.RequestServices' with the type of 'Autofac.Extensions.DependencyInjection.AutofacServiceProvider'
Thank you very much for asking for relief

Related

How to return custom Exception

I added the [Authorization] attribute to the below action to protect it from unauthorized access. I'm wondering if it's possible to return a custom error/exception for this?
In postman, it only shows the 401 status but the response of the body is empty.
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[Authorize]
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
If you are using.NET 5 and above you can implement the IAuthorizationMiddlewareResultHandler and return whatever http response code and data you want on the failed authorization. You can even return different response codes and data based on different authorization policy failures that you can define yourself
public class CustomAuthorizationMiddlewareResultHandler :
IAuthorizationMiddlewareResultHandler
{
private readonly AuthorizationMiddlewareResultHandler defaultHandler = new();
public async Task HandleAsync(
RequestDelegate next,
HttpContext context,
AuthorizationPolicy policy,
PolicyAuthorizationResult authorizeResult)
{
if (policyAuthorizationResult.Forbidden &&
policyAuthorizationResult.AuthorizationFailure.FailedRequirements.OfType<Show404Requirement>().Any();)
{
var bytes = Encoding.UTF8.GetBytes("Not found bro");
await HttpContext.Response.Body.WriteAsync(bytes, 0, bytes.Length);
context.Response.StatusCode = StatusCodes.Status404NotFound;
return;
}
await DefaultHandler.HandleAsync(requestDelegate, httpContext, authorizationPolicy,
policyAuthorizationResult);
}
}
More details on the topic here https://learn.microsoft.com/en-us/aspnet/core/security/authorization/customizingauthorizationmiddlewareresponse?view=aspnetcore-5.0

New controller does not respond to requests

I created a new project from the ASP.NET Core Web API template in Visual Studio, and attempted to add a new controller, but I get a 404 response with this message when trying to GET from it:
Cannot GET /navigation
My program.cs:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (builder.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
The working controller that came with the template:
using Microsoft.AspNetCore.Mvc;
namespace Test.API.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}
My new controller:
using Microsoft.AspNetCore.Mvc;
using Test.API.Navigation;
namespace Test.API.Controllers
{
[ApiController]
[Route("[controller]")]
public class NavigationController : ControllerBase
{
public NavigationController()
{
}
[HttpGet(Name = "GetNavigation")]
public IEnumerable<NavigationItem> Get()
{
return new List<NavigationItem>
{
new NavigationItem()
{
Title = "Home",
Url = "test",
AltText = "Home page"
}
};
}
}
}
How can I get this controller to work? The project seems to have no extra config files that are relevant, just launchsettings.json and applicationsettings.json.
I tried changing the name of the WeatherForecastController, which led to it returning the same response, so it feels like it is hardcoded somehow.
Did you update your proxy.conf.js file? Change the context to /navigation. The target is your target you have now.
const PROXY_CONFIG = [
{
context: [
"/navigation",
],
target: "https://localhost:7105",
secure: false
}
]
module.exports = PROXY_CONFIG;

Minimal API in .NET 6 using multiple files

In .NET 6 it is possible to create minimal APIs:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/products/{id}", (int id) => { return Results.Ok(); })
app.MapGet("/users/{id}", (int id) => { return Results.Ok(); })
app.Run();
What would be an approach to group endpoints in multiple files instead of having all in Program file?
ProductEndpoints.cs:
app.MapGet("/products/{id}", (int id) => { return Results.Ok(); })
UserEndpoints.cs
app.MapGet("/users/{id}", (int id) => { return Results.Ok(); })
Only one file with top-level statement is allowed per project. But nobody forbids moving endpoints to some static method of another class:
public static class ProductEndpointsExt
{
public static void MapProductEndpoints(this WebApplication app)
{
app.MapGet("/products/{id}", (int id) => { return Results.Ok(); });
}
}
And in the Program file:
app.MapProductEndpoints();
We can use partial Program.cs files too
Example: "Program.Users.cs"
partial class Program
{
/// <summary>
/// Map all users routes
/// </summary>
/// <param name="app"></param>
private static void AddUsers(WebApplication app)
{
app.MapGet("/users", () => "All users");
app.MapGet("/user/{id?}", (int? id) => $"A users {id}");
///post, patch, delete...
}
}
And in "Program.cs"
...
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//add...
AddUsers(app);
...
What I did is creating a interface IEndPoint that each class that need to define endpoints must implement, and an extension method to find all implementations to call the interface mapping method.
You just have to call that extension method in your Program.cs or Startup to register all the endpoints.
// IEndpoint.cs
public interface IEndPoint
{
void MapEndpoint(WebApplication app);
}
// FeatureA.cs
public class FeatureA: IEndPoint
{
public void MapEndpoint(WebApplication app)
{
app.MapGet("api/FeatureA/{id}", async (int id) => $"Fetching {id} data");
}
}
// WebApplicationExtension.cs
public static class WebApplicationExtensions
{
public static void MapEndpoint(this WebApplication app)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var classes = assemblies.Distinct().SelectMany(x => x.GetTypes())
.Where(x => typeof(IEndPoint).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract);
foreach (var classe in classes)
{
var instance = Activator.CreateInstance(classe) as IEndPoint;
instance?.MapEndpoint(app);
}
}
}
// Program.cs
...
app.MapEndpoint();
...
I think the best way is to use Controller based web service. Although, you can this approach like this:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapWeatherForecastRoutes();
app.Run();
internal static class WeatherForecastController
{
internal static void MapWeatherForecastRoutes(this WebApplication app)
{
app.MapGet("/weatherforecast", () =>
{
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
}
}
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
The only thing we need to consider is how to make the best use of extension methods.
It is enough to implement each group of web services in a static class and add them to the program using Extension methods.
Another option is to use Carter project
Add carter project to Nuget dotnet add package carter
Modify Program.cs to use carter
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCarter();
var app = builder.Build();
app.MapCarter();
app.Run();
Notice that .AddControllers() can be removed
Add Carter Module, it will be later auto-discovered
using Carter;
using MapEndpoints;
public class WeatherModule : ICarterModule
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("/GetWeatherForecast", (ILoggerFactory loggerFactory) => Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray());
}
}
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}

AllowAnonymous is not ignored in ASP.NET Core custom AuthenticationHandler after migrating from .NET Core 2.2 to 3.1

I have an ASP.NET Core 2.2 Web API which was working with the Basic Authentication. So far it worked fine and has no troubles. In one of the Controller, one Action Method is Decorated with [AllowAnonymous] to make the User Login, as usual.
[Produces("application/json")]
[Route("user")]
[AllowAnonymous]
[ApiController]
public class LoginController : ControllerBase
{
private readonly IConfiguration _configuration;
private readonly IMessagingService _messageService;
private readonly IBasicAuthenticationService _basicAuthenticationService;
private readonly string PWAPIBaseUrl;
public LoginController(IConfiguration configuration, ILogger<LoginController> logger, IMessagingService messagingService, IBasicAuthenticationService authenticationService)
{
_configuration = configuration;
_logger = logger;
_messageService = messagingService;
_basicAuthenticationService = authenticationService;
}
[HttpGet]
[AllowAnonymous]
[Route("login/{username}/{clientID}")]
public async Task<IActionResult> UserLogin(string username, string clientID)
{
// Check the Credentials Manually
string failReason = "";
if (!CheckCredentials(out failReason))
{
return StatusCode(StatusCodes.Status403Forbidden, userInfo);
}
// Load the Roles and UI Preferences ...
}
}
As the end of .NET Core 2.2 is near, I have tried upgrading to the .NET Core 3.1 and followed the official Migration Guide and made necessary changes. Though the Application started out smoothly, there is one bugging issue which forbids the upgrade.
On the above controller, the [AllowAnonymous] is not ignored and the Authentication is evaluated and thrown out with an error. But the Login method is executed after. This causes Login to break in all the dependent applications. I have tried all the suggestions from Stackoverflow like this, this and this.
Basic Authentication Handler:
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private readonly ILogger<BasicAuthenticationHandler> _logger = null;
private readonly IBasicAuthenticationService _basicAuthenticationService;
public BasicAuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
UrlEncoder encoder,
ILoggerFactory loggerFactory,
ISystemClock clock,
IBasicAuthenticationService authenticationService)
: base(options, loggerFactory, encoder, clock)
{
_logger = loggerFactory.CreateLogger<BasicAuthenticationHandler>();
_basicAuthenticationService = authenticationService;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
var config = Util.GetConfig();
if (!Request.Headers.ContainsKey("Authorization"))
{
_logger.LogError("No authorization credentials");
return AuthenticateResult.NoResult();
}
if (!Request.Headers.ContainsKey("ClientID"))
{
_logger.LogError("Missing header client token");
return AuthenticateResult.Fail("Missing header client token");
}
var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
if (authHeader.Scheme != "Basic")
{
_logger.LogError("Authentication scheme not recognized");
return AuthenticateResult.Fail("Authentication scheme not recognized");
}
var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':');
var username = credentials[0];
var password = credentials[1];
string fullname = "";
string failReason = "";
bool t = false;
IPrincipal principal = null;
// Do Business Validation against the DB
if (!t) // login failed
{
byte[] bEncodedResponse = Encoding.UTF8.GetBytes(failReason);
await Context.Response.Body.WriteAsync(bEncodedResponse, 0, bEncodedResponse.Length);
return AuthenticateResult.Fail(failReason);
}
else
{
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, username),
new Claim(ClaimTypes.Name, fullname),
};
var identity = new ClaimsIdentity(claims, Scheme.Name);
principal = principal==null?new ClaimsPrincipal(identity): principal;
var ticket = new AuthenticationTicket(principal as ClaimsPrincipal, Scheme.Name);
return AuthenticateResult.Success(ticket);
}
}
}
Startup.cs
public class Startup
{
public Startup(IWebHostEnvironment environment, IConfiguration configuration, ILoggerFactory loggerFactory)
{
Environment = environment;
Configuration = configuration;
LoggerFactory = loggerFactory;
}
public IConfiguration Configuration { get; }
public ILoggerFactory LoggerFactory { get; }
public IWebHostEnvironment Environment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("BasicAuthentication")
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);
// Adding the Configuration Options -- Extension Methods to Inject Configuration as IOption POCOs
services.ConfigureAPIOptions(Configuration);
// configure DI for application services -- Other DI Objects
services.ConfigureDependencies(Configuration, LoggerFactory);
Common.APIConfiguration.Current = Configuration;
services.AddControllers();
services.AddAuthorization();
if (Environment.IsDevelopment())
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My Materials API", Version = "v1" });
});
}
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
if (env.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My Materials API v1");
c.RoutePrefix = string.Empty;
});
}
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
I am still clueless on what I did wrong and I might be missing something in ASP.NET Core 3.1. Please help me in getting this working. Thanks in advance.
EDIT 1:
ServiceExtensions.cs
public static class ServiceExtensions
{
public static void ConfigureAPIOptions(this IServiceCollection services, IConfiguration configuration)
{
services.AddOptions();
services.Configure<DataSetting>(configuration.GetSection("DataSettings"));
services.Configure<UrlSetting>(configuration.GetSection("UrlSettings"));
services.Configure<SiteSettings>(configuration.GetSection("SiteSettings"));
}
public static void ConfigureDependencies(this IServiceCollection services, IConfiguration configuration, ILoggerFactory loggerFactory)
{
services.AddSingleton<IConfiguration>(configuration);
services.AddScoped<IBasicAuthenticationService, BasicAuthenticationService>();
services.AddScoped<IMessagingService>(s => new MessagingServices(configuration, loggerFactory.CreateLogger<MessagingServices>()));
services.AddHostedService<TimedHostedService>();
}
}
A Small Kludge for accessing the Configuration, where DI is not possible.
public static class APIConfiguration
{
public static IConfiguration Current { get; set; }
}
I tried this and it really helps me.
private static bool HasAllowAnonymous(AuthorizationFilterContext context)
{
var filters = context.Filters;
for (var i = 0; i < filters.Count; i++)
{
if (filters[i] is IAllowAnonymousFilter)
{
return true;
}
}
// When doing endpoint routing, MVC does not add AllowAnonymousFilters for AllowAnonymousAttributes that
// were discovered on controllers and actions. To maintain compat with 2.x,
// we'll check for the presence of IAllowAnonymous in endpoint metadata.
var endpoint = context.HttpContext.GetEndpoint();
if (endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null)
{
return true;
}
return false;
}
https://github.com/dotnet/aspnetcore/blob/bd65275148abc9b07a3b59797a88d485341152bf/src/Mvc/Mvc.Core/src/Authorization/AuthorizeFilter.cs#L236
It was mentioned here https://learn.microsoft.com/en-us/dotnet/core/compatibility/2.2-3.1#authorization-iallowanonymous-removed-from-authorizationfiltercontextfilters

AspNetCore unable to resolve service

I'm adding Microsoft.AspNetCore.Identity to a project, and I get
InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.SignInManager'1[Web.Security.Entities.IUser'1[System.Int32]]' while attempting to activate 'Web.Security.Services.SecurityService'2[Web.Security.Entities.IUser'1[System.Int32],System.Int32]'.
Exception is copypasted from postman, it encoded some symbols.
Here's my Startup.cs:
public class Startup
{
ServiceProvider serviceProvider;
IConfigurationRoot configurationRoot;
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
configurationRoot = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddIniFile("3CXPhoneSystem.ini")
.Build();
}
// 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)
{
serviceProvider = services
.AddLogging((builder) => builder.SetMinimumLevel(LogLevel.Trace))
.AddSingleton<ISecurityService, SecurityService<IUser<int>, int>>()
.AddSingleton<ITaskService, TaskService>()
.AddTransient<IEmailSender, EmailSender>()
.AddSingleton<ITranslation, Translation>()
.BuildServiceProvider();
services.AddDbContext<SecurityDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("dataContext")));
services.AddIdentity<Web.Security.Entities.User<int>, IdentityRole>()
.AddEntityFrameworkStores<SecurityDbContext>()
.AddDefaultTokenProviders();
services.AddCors(o => o.AddPolicy("CorsPolicy", builder =>
{
builder
.AllowAnyMethod()
.AllowAnyHeader()
.WithOrigins("http://localhost:52170");
}));
services.AddMvc();
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
});
}
// 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.UseDeveloperExceptionPage();
}
app.UseDefaultFiles();
app.UseStaticFiles();
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.Response.Redirect("/");
}
});
app.UseMvc(routes =>
{
routes.MapRoute(name: "DefaultApi", template: "api/{controller}/{action}/{id?}");
routes.MapRoute("RouteToAngular", "{*url}", defaults: new { controller = "Route", action = "Index" });
});
app.UseAuthentication();
app.UseCors("CorsPolicy");
}
Here, SecurityService is a class that will handle registration/login/other identity related requests, it looks like this
public class SecurityService<TUser, TKey> : ISecurityService where TUser : class, IUser<TKey>
{
SignInManager<TUser> signInManager;
IConfiguration configuration;
private readonly IHttpContextAccessor httpContextAccessor;
UserManager<TUser> userManager;
IEmailSender emailSender;
IUrlHelper urlHelper;
ISession session;
ILogger<SecurityService<TUser, TKey>> logger;
ITranslation translation;
public SecurityService(
SignInManager<TUser> signInManager,
UserManager<TUser> userManager,
IConfiguration configuration,
IHttpContextAccessor httpContextAccessor,
IEmailSender emailSender,
IUrlHelper urlHelper,
ISession session,
ILogger<SecurityService<TUser, TKey>> logger,
ITranslation translation)
{
this.signInManager = signInManager;
this.userManager = userManager;
this.configuration = configuration;
this.httpContextAccessor = httpContextAccessor;
this.urlHelper = urlHelper;
this.session = session;
this.logger = logger;
this.translation = translation;
this.emailSender = emailSender;
}
IUser.cs:
public interface IUser<TKey>
{
TKey Id { get; set; }
string UserName { get; set; }
string Email { get; set; }
bool EmailConfirmed { get; set; }
}
You need to use the IdentityBuilder extension method AddSignInManager explicitly.
services.AddIdentity<Web.Security.Entities.User<int>, IdentityRole>()
.AddEntityFrameworkStores<SecurityDbContext>()
// Replace ApplicationUser with your concrete user class
.AddSignInManager<SignInManager<ApplicationUser>>()
.AddDefaultTokenProviders();
If you need access to it in your security service then you can inject it:
public class SecurityService<TUser, TKey> ...
{
public SecurityService(SignInManager<ApplicationUser> signInManager)
{
this.signInManager = signInManager;
}
}

Categories