AspNetCore.Identity UserManager in Repository Pattern - asp.net-core

I want to use Repository with AspNetCore.Identity UserManager. But I am getting error when defined in Controller.
Repository
public class TestRepository
{
private readonly UserManager<tblApplicationUser> _userManager;
public TestRepository(UserManager<tblApplicationUser> userManager)
{
this._userManager = userManager;
}
}
Controller:
private TestRepository _testRepository;
public TestController()
{
this._testRepository = new TestRepository(new UserManager<tblApplicationUser>);
}
I am getting error in controller at new UserManager

It seems you are missing braces (for UserManager constructor) before the last brace?
this._testRepository = new TestRepository(new UserManager<tblApplicationUser>());
You should let the DI handle instantiation of UserManager and Repository. You can check out this article on official docs for ASP.NET Core.

Related

Is it correct to use Autofac IComponentContext in controller?

I connected Autofac to my ASP.NET CORE WEB-API application.
Registered two implementations of IService in the container by keys (enum).
Through the IComponentContext container, using the key, I get one of the implementations in the Get method of the controller (BotController):
_container.ResolveKeyed ((ServiceEnum) serviceType).
I read on the forum that it is not correct to use IComponentContext.
Questions:
-1. Why is it wrong?
-2. If not correct how can I resolve Named and Keyed implementations?
Example controller:
[ApiController]
[Route("api/message/update")]
public class BotController : Controller
{
private readonly IMainDbConnection _connection;
private readonly IComponentContext _container;
public BotController(IMainDbConnection connection, IComponentContext container)
{
_connection = connection;
_container = container;
}
[HttpGet]
public IActionResult Get(int serviceType)
{
var service = _container.ResolveKeyed<IService>((ServiceEnum) serviceType);
var result = service.Get(serviceType.ToString());
return Ok(result);
}
}

How to get HttpContext.Current.Session in ASP.NET Core?

I need to migrate an MVC project to .net Core, I know it has System.Web removed from ASP.net Core.
I need to convert
HttpContext.Current.Session ["name"]! = Null at asp.net core.
I added:
using Microsoft.AspNetCore.Http
but I have an error.
Use like this:
HttpContext.Session.SetString("priceModel", JsonConvert.SerializeObject(customobject));
var priceDetails = HttpContext.Session.GetString("priceModel");
Make sure below points in startup class:
AddSession in ConfigureServices method
services.AddSession();
Usesession in configure method:
app.UseSession();
you don't have System.Web.HttpContext.Current.Session in ASP.NET Core. To access session in non-controller class
step1:
First, register the following service in Startup.ConfigureServices;
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
step2:
register a class (example - TestOrder) where you want to access the Session in
Startup.ConfigureServices;
services.AddScoped<TestOrder>();
Now, in TestOrderclass, add the following code.
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ISession _session;
public TestOrder(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
_session = _httpContextAccessor.HttpContext.Session;
}
The above code is receiving IHttpContextAccessor object through dependency injection and then, it is storing Sessions in a local variable.
The recommended approach is to register a dependency using the built-in dependency injection container. Inject IHttpContextAccessor into the corresponding service.
public class UserRepository : IUserRepository
{
private readonly IHttpContextAccessor _httpContextAccessor;
public UserRepository(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void LogCurrentUser()
{
var username = _httpContextAccessor.HttpContext.Session.GetString("UserName");
service.LogAccessRequest(username);
}
}
For more details, refer to this link
Did you test Microsoft doc, a sample is like below
public const string SessionKeyName = "_Name";
public const string SessionKeyAge = "_Age";
const string SessionKeyTime = "_Time";
// Requires: using Microsoft.AspNetCore.Http;
if (string.IsNullOrEmpty(HttpContext.Session.GetString(SessionKeyName)))
{
HttpContext.Session.SetString(SessionKeyName, "The Doctor");
HttpContext.Session.SetInt32(SessionKeyAge, 773);
}
var name = HttpContext.Session.GetString(SessionKeyName);
var age = HttpContext.Session.GetInt32(SessionKeyAge);

How to inject dependency into NServiceBus pipeline behavior?

I've been following the NServiceBus samples, specifically for how to use an entity framework (core) DbContext integrated with Sql Persistence so that I can save dbcontext state changes along with the outbox messages. This is the sample: https://docs.particular.net/samples/entity-framework-core/
I've modified the unit of work code a little to support creation of an aspnet core DI scoped DbContext. The relevant code follows:
public class UnitOfWork<TDbContext>
where TDbContext : DbContext
{
private Func<SynchronizedStorageSession, IServiceProvider, TDbContext> _contextFactory;
private TDbContext _context;
private IServiceProvider _serviceProvider;
public UnitOfWork(Func<SynchronizedStorageSession, IServiceProvider, TDbContext> contextFactory, IServiceProvider serviceProvider)
{
_contextFactory = contextFactory;
_serviceProvider = serviceProvider;
}
public TDbContext GetDataContext(SynchronizedStorageSession storageSession)
{
if (_context == null)
{
_context = _contextFactory(storageSession, _serviceProvider);
}
return _context;
}
}
public class UnitOfWorkSetupBehavior<TDbContext> : Behavior<IIncomingLogicalMessageContext>
where TDbContext : DbContext
{
private readonly Func<SynchronizedStorageSession, IServiceProvider, TDbContext> _contextFactory;
private readonly IServiceScopeFactory _serviceScopeFactory;
public UnitOfWorkSetupBehavior(Func<SynchronizedStorageSession, IServiceProvider, TDbContext> contextFactory, IServiceScopeFactory serviceScopeFactory)
{
_contextFactory = contextFactory;
_serviceScopeFactory = serviceScopeFactory;
}
public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var uow = new UnitOfWork<TDbContext>(_contextFactory, scope.ServiceProvider);
context.Extensions.Set(uow);
await next().ConfigureAwait(false);
context.Extensions.Remove<UnitOfWork<TDbContext>>();
}
}
}
public static class EndpointConfigurationExtensions
{
public static void RegisterUnitOfWork<TDbContext>(this EndpointConfiguration endpointConfiguration, IServiceScopeFactory serviceScopeFactory)
where TDbContext : DbContext
{
var pipeline = endpointConfiguration.Pipeline;
pipeline.Register(new UnitOfWorkSetupBehavior<TDbContext>((storageSession, serviceProvider) =>
{
var dbConnection = storageSession.SqlPersistenceSession().Connection;
var dbContextFactory = serviceProvider.GetService<IDbContextConnectionFactory<TDbContext>>();
var dbContext = dbContextFactory.GetDbContext(dbConnection);
//Use the same underlying ADO.NET transaction
dbContext.Database.UseTransaction(storageSession.SqlPersistenceSession().Transaction);
//Call SaveChanges before completing storage session
storageSession.SqlPersistenceSession().OnSaveChanges(x => dbContext.SaveChangesAsync());
return dbContext;
}, serviceScopeFactory), "Sets up unit of work for the message");
}
}
public static class UnitOfWorkContextExtensions
{
public static TDbContext DataContext<TDbContext>(this IMessageHandlerContext context)
where TDbContext : DbContext
{
var uow = context.Extensions.Get<UnitOfWork<TDbContext>>();
return uow.GetDataContext(context.SynchronizedStorageSession);
}
}
For this to work the behavior needs an injected IServiceScopeFactory.
Now all examples I've been able to find of behavior registration only show the type manually instantiated and passed in to the endpointconfiguration's pipeline.
Is there a way to either gain access to an IServiceScopeFactory via the behavior's Invoke method (maybe by the context via some extension perhaps?), or is it possible to register the behavior itself such that I can construct it with services created by the DI container?
FYI I took a look at this Q&A which gave me the idea of injecting the IServiceScopeFactory. Unfortunately, the answer doesn't show how to actually get an instance of the interface.
You would use context.builder.Build<T>(); within the Invoke method to resolve any objects like IServiceScopeFactory.
https://docs.particular.net/samples/multi-tenant/di/
Make sure that the IServiceScopeFactory is registered in the DI container. For example, during your endpoint initialization:
endpointConfiguration.RegisterComponents(registration: x =>
{
x.ConfigureComponent<IServiceScopeFactory>(yourServiceScopeFactory);
});
https://docs.particular.net/nservicebus/dependency-injection/
You can also do this by creating a Feature
https://docs.particular.net/nservicebus/pipeline/features

DbContext cannot find database

The connection string for our app is set in appsettings.json
"Data": {
"DefaultConnection": {
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=Customers;Trusted_Connection=True;MultipleActiveResultSets=true",
In ConfigureServices we have
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<CustomersContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
This seems to work in cases like this
var membershipUser = await _userManager.FindByEmailAsync(email);
and this
var result = await _userManager.CreateAsync(newUser);
but falls over when I try this
using (var customers = new CustomersContext())
{
var deviceList = customers.Devices.Where(d => d.UserId == membershipUser.Id);
The error is InvalidOperationException: No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services.
If I try this
public partial class CustomersContext : IdentityDbContext<ApplicationUser>
// note this inherits from IdentityDbContext<ApplicationUser> not DbContext
// refer http://stackoverflow.com/questions/19902756/asp-net-identity-dbcontext-confusion
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(#"Server=(localdb)\\mssqllocaldb;Database=Customers;Trusted_Connection=True;MultipleActiveResultSets=true");
}
I get this error
Local Database Runtime error occurred. Specified LocalDB instance name is invalid
Why is it my app can find the database in some cases but not others?
The problem is that although you've configured a CustomerContext with the DI services as shown here:
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<CustomersContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
You are not having the CustomerContext injected, instead you are newing it up like this:
using (var customers = new CustomersContext())
{
...
}
using a constructor that takes no parameters, so your CustomersContext is not configured like the one in startup and it has no connection string.
Since you mention you need it in the AccountController, then all you need to do is add CustomersContext to the constructor of AccountController, so that the one you configured in startup will get injected. Like this:
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private readonly ILogger _logger;
private CustomersContext _customerContext;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
CustomersContext customerContext)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_customerContext = customerContext;
}
That way you get a properly configured CusotmersContext and you don't have to new it up yourself. If for some reason you did want to new it up yourself you need to do so using a constructor that takes IServiceProvider and DbContextOptions. So you would receive those objects in the constructor of AccountController and you would pass them in as you new up the CustomersContext like this:
using (var customers = new CustomersContext(serviceProvider, dbContextOptions))
{
...
}

Get Injected Object in ASP.NET vNext filter

I'm trying to create my custom authorize attribute, but in asp.net vnext using the default dependency injection framework I don't how to get the injected object. I need to get the injected object in the default ctor.
public class CustomAttribute
{
private IDb _db;
public CustomAttribute()
{
_db = null; // get injected object
}
public CustomAttribute(IDb db)
{
_db = db;
}
// apply all authentication logic
}
You can use the ServiceFilterAttribute for this purpose. The service filter attribute lets the DI system take care of instantiating and maintaining the lifetime of the filter CustomAuthorizeFilter and its any required services.
Example:
// register with DI
services.AddScoped<ApplicationDbContext>();
services.AddTransient<CustomAuthorizeFilter>();
//------------------
public class CustomAuthorizeFilter : IAsyncAuthorizationFilter
{
private readonly ApplicationDbContext _db;
public CustomAuthorizeFilter(ApplicationDbContext db)
{
_db = db;
}
public Task OnAuthorizationAsync(AuthorizationContext context)
{
//do something here
}
}
//------------------
[ServiceFilter(typeof(CustomAuthorizeFilter))]
public class AdminController : Controller
{
// do something here
}