ASP.NET Core Identity - UserManager and UserStore woes - asp.net

I'm trying to implement the Identity system in an ASP.NET Core app (RC2 libraries) and there is a particular hangup that is driving me crazy.
First of all, I am not using EntityFramework. I'm not even using SQL. I'm backing up to RavenDB, so I need the implementation to be very specific to that; Which isn't a problem.
So I designed a RavenUserStore class, and it looks like this;
public class RavenUserStore<TUser> :
IUserStore<TUser>,
IUserLoginStore<TUser>,
IUserPasswordStore<TUser>,
IUserRoleStore<TUser>,
IUserSecurityStampStore<TUser>,
IUserClaimStore<TUser>,
IUserLockoutStore<TUser>,
IUserTwoFactorStore<TUser>,
IUserEmailStore<TUser> {
// ...
}
Works great on its own. I've implemented all the methods, etc. It's wonderful. Very clean and efficient.
Now, I go over to my web application and wire things up;
services.AddTransient<ILookupNormalizer>(s => new LowerInvariantLookupNormalizer());
services.AddTransient<IPasswordHasher<Member>>(s => new PasswordHasher<Member>());
services.AddTransient<IUserStore<Member>, RavenUserStore<Member>>();
services.AddIdentity<Member, Role>(o => {
o.Password.RequiredLength = 6;
o.Password.RequireDigit = true;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
})
.AddUserStore<RavenUserStore<Member>>()
.AddRoleStore<RavenRoleStore<Role>>();
So I go make a controller to use this, per all the samples I've seen, and the very core sample from the Identity Framework Github Repository
//... [PROPERTIES]...//
public AccountController(UserManager<Member> userManager, SignInManager<Member> signInManager) {
// ... [attach constructor parameters to properties] ...//
}
Alright, so I inspect the classes carefully.
UserManager<T> has a property Store,which is a type of IUserStore<T>.
So theoretically.. if the dependency injection resolves types of IUserStore<T> to RavenUserStore<T> when they are injected through a constructor.. shouldn't that mean that the UserManager<T> gets a RavenUserStore<T> as its Store property?
I thought it would too; But when I call methods on the UserManager, it DOES NOT call the ones on my RavenUserStore. Why is this? What can I do?
Do I really have to ALSO make a custom UserManager class and do all of those methods AGAIN?

You need to add your own custom providers before calling services.AddIdentity(). Internally, AddIdentity uses TryAddScoped() which only adds the default items if they don't already exist in the services container.
So just putting the call to AddIdentity() after you registered all your custom implementations should mean that they will take precedence as you expect.

Related

Autofac Multiple Regsistrations to Single service. Simple Injector -> Autofac translation

I've developed a CQRS style database access framework based on Tripod and other inspirations but targeting .NET Standard and simplifying for easier use. I want to split the IoC into separate integration packages so consumers can get the type registration I'm currently doing internally easily without being locked into a specific IoC container. My issue is I've only really worked closely with SimpleInjector so not familiar with other systems and their nuances around how they handle specific scenarios. I have an iminent need to support Autofac so thought I'd try here to see if anyone can translate.
I have the following Simple Injector CompositionRoot static class:
public static void RegisterDatabase(this Container container, DbContextOptions<EntityDbContext> dbContextOptions, params Assembly[] assemblies)
{
var scopedLifeStyle = container.Options.DefaultScopedLifestyle;
//container.Register<ICreateDbModel, DefaultDbModelCreator>(scopedLifeStyle); // lifestyle c
container.RegisterInitializer<EntityDbContext>( //(container.InjectProperties);
handlerToInitialise => handlerToInitialise.ModelCreator = new DefaultDbModelCreator()
);
// Setup DbContext
var ctxReg = scopedLifeStyle.CreateRegistration(
() => new EntityDbContext(dbContextOptions),
container);
container.AddRegistration<IUnitOfWork>(ctxReg);
container.AddRegistration<IReadEntities>(ctxReg);
container.AddRegistration<IWriteEntities>(ctxReg);
}
In ASP.NET Core solutions I invoke the above from Startup.Configure(...) with:
var optionsBuilder = new DbContextOptionsBuilder<EntityDbContext>()
//.UseInMemoryDatabase("Snoogans");
.UseSqlServer(_config.GetConnectionString("DefaultConnection"));
container.RegisterDatabase(optionsBuilder.Options);
which allows me to switch out to an in memory database for unit testing if needed. EntityDbContext contains all my unit of work methods for calling onto the context without having to specify explicit DbSet for each table. The IUnitOfWork, IReadEntities and IWriteEntities interfaces all define methods on the EntityDbContext.
So I'm not sure how I'd go about making an Autofac module that allows scoped registration of the dbcontext with passed in DbContextOptions followed by multiple registrations of interfaces to this registration.
Does anyone know how this can be achieved?
I worked out the process and now have an AutoFac module. I was able to registermodule by instance of the class and also pass in the options when I instantiate. Because EntityDbContext implements the three interfaces I was registering separately in the Simple Injector scenario, AutoFac has the convenience of being able to just infer them and register with AsImplementedInterfaces()
public class EntityFrameworkModule : Module
{
private readonly DbContextOptions<EntityDbContext> _dbContextOptions;
public EntityFrameworkModule(DbContextOptions<EntityDbContext> dbContextOptions)
{
_dbContextOptions = dbContextOptions;
}
protected override void Load(ContainerBuilder builder)
{
// If the calling code hasn't already registered a custom
// ICreateDbModel then register the internal DefaultDbModelCreator
builder.RegisterType<DefaultDbModelCreator>()
.IfNotRegistered(typeof(ICreateDbModel))
.As<ICreateDbModel>();
// Expecting IUnitOfWork, IReadEntities and IWriteEntities to be registered with this call
builder.Register(c => new EntityDbContext(_dbContextOptions)
{
ModelCreator = c.Resolve<ICreateDbModel>()
})
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
}

Upgrading Unity container breaks interception mechanism

We recently upgraded Microsoft's Unity in our project from version 3.5.1404 to 5.8.6. With only a few minor adjustments in our code this upgrade seemed to go pretty easy. It resolves all our registered instances without a problem. However, we also use Unity's Interception-mechanism to cache some results that a method returns in AOP-style. This cache mechanism is broken since the upgrade and we can't figure out why. Apparently, our attributes are no longer called when a decorated method is called.
It currently works as follows. We register the interception like this:
var container = new UnityContainer();
container.RegisterType<IService, Service>(some_lifetime);
container.AddNewExtension<Interception>();
container.Configure<Interception>()
.SetInterceptorFor(typeof(IService), new InterfaceInterceptor());
In the Service class, which implements IService we have a method that is decorated with a custom Cache attribute, like this:
public class Service : IService {
[Cache(..)]
public Result SomeMethod() {
// Some code
}
}
And lastly, our custom Cache attribute which inherits from Unity's HandlerAttribute:
public class CacheAttribute : HandlerAttribute
{
// ctor
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new CacheCallHandler(container, and, some, more);
}
}
When method SomeMethod used to be called with version 3.5.1404 the attribute was called first, but since 5.8.6 it no longer calls this attribute. The code however, does compile. The changes we had to make to make it compile are mostly changes in usings. Like Microsoft.Practices.Unity.InterceptionExtension which changed to Unity.Interception.PolicyInjection.Policies.
We can't figure out why this mechanism is no longer working. And even after extensive research on the internet, we can't find a way to get this to work. Any suggesties would therefore be greatly appreciated!
I got in your exact same situation while trying to refresh some legacy code. I got it working with:
Changing:
config.SetInterceptorFor(myType, new InterfaceInterceptor()); for
config.SetInterceptorFor(myType, new TransparentProxyInterceptor());
Registering the class that inherits from HandlerAttribute
Container.RegisterType<MyHandlerAttribute>(new PerRequestLifeTimeManager());
Register each type to intercept with special InjectionMembers:
Container.RegisterType<MyClassToBeIntercepted>(
new Interceptor<TransparentProxyInterceptor>(),
new InterceptionBehavior<PolicyInjectionBehavior>()
);

IContainerRegistryExtensions how to register an instance as singleton

I am trying to migrate an old Prism Xamarin Form project to latest Prism and XF version.
I'd like to register a factory for creating connections like this Func<SQLiteConnection>:
public class AndroidInitializer : IPlatformInitializer
{
string DbFilePath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "test.db3");
public void RegisterTypes(IContainerRegistry container)
{
container.RegisterSingleton<Func<SQLiteConnection>>(() => new SQLiteConnection(DbFilePath));
}
}
Howeve this doesn't work, there's no overload which takes an instance like I was used to do in old Prism Unity version.
The ContainerRegistry is intentionally basic to handle the 90+% of registrations that you need in a consistent manner regardless of which container you're using. You can continue to use the underlying container for more advanced registrations.
For both DryIoc and Unity it would be:
containerRegistry.GetContainer().SomeContainerSpecificMethod();
where SomeContainerSpecificMethod would match what you had in Prism 6.3
Another possibility is to use RegisterInstance to register a single instance of a class. Not sure if this has implications for object lifetime though.
var connection = new SQLiteConnection(DbFilePath)
container.RegisterInstance(connection);

Using Sessions in my Project

I am new to .NET programming and I am trying to implement sessions in my already screwed sample. So here are the details of my sample i had done till now.
I have types of solutions in my project. A Class library, web application and console application.
I created a static class which has a bunch of get/properties and using these properties as global variables to use in my Class library. These get/set properties have a mixed set of data structures like list and dictionaries.
My Web app has only one page with a bunch of list boxes and button. I am using all the get set properties from my class library in to my Web application for some data storing and retrieving purposes. Now when the web page is opened in two different browsers then the data is over written from one user to the other as I am using all static variables and storing data in those static variables.
My best solution to this is using sessions but I am a little confused of using them in my project. Can any one please help me in this regard.
Here is a small sample of my explanation:
a XMLData Class in Class Library has a bunch of these get/set properties.
public Dictionary<string, List<string>> Content
{
get { return _testContent; }
set { _testContent = value;}
}
Now how do I use HttpContext Sessions to use in my Class Library to move these static properties to sessions so that every user who uses my site have their set of data. FYI. The web project is basically used for call in methods to the class library and do a little selection on the list box of the UI which are kind of inputs to my test.
Thanks In Advance.
The simple way is that you can access the current context in a class in your class library using
HttpContext.Current
this has Session available on it.
There are more complex ways that your application could be architected, but we'll start with the simplest :)
To elaborate, your class library may declare an interface for a component that is able to access session
public interface ISessionStore
{
object Get(string key);
void Save(string key, object value);
}
now, define a concrete implementation of ISessionStore
public class HttpContextSessionStore : ISessionStore
{
public object Get(string key)
{
var context = HttpContext.Current;
if (context == null)
throw new InvalidOperationException("this class is intended to work only within web applications");
return context.Session(key);
}
public void Save(string key, object value)
{
var context = HttpContext.Current;
if (context == null)
throw new InvalidOperationException("this class is intended to work only within web applications");
// note that this will overwrite anything already set
// against this key in session
context.Session[key] = value;
}
}
Now you can program against the interface ISessionStore and use the HttpContextSessionStore in your application.
I'd recommend looking at the MVP pattern if you're working with web forms or alternatively, take a look at the MVC framework.
In addition to Russ Cam's comments above, you should also check that HttpContext.Current != null in methods in your class library. It's guaranteed to bite you in the ass if you start writing unit tests, or for any code which isn't being executed within ASP.Net

Get instance of type inheriting from base class, implementing interface, using StructureMap

Continuing on my quest for a good plugin implementation I have been testing the StructureMap assembly scanning features.
All plugins will inherit from abstract class PluginBase. This will provide access to common application services such as logging. Depending on it's function, each plugin may then implement additional interfaces, for example, IStartUpTask.
I am initializing my plugins like so:
Scan(x => {
x.AssembliesFromPath(HttpContext.Current.Server.MapPath("~/Plugins"),
assembly => assembly.GetName().Name.Contains("Extension"));
x.AddAllTypesOf<PluginBase>();
});
The difficulty I am then having is how to work against the interface (not the PluginBase) in code. It's easy enough to work with PluginBase:
var plugins = ObjectFactory.GetAllInstances<PluginBase>();
foreach (var plugin in plugins)
{
}
But specific functionality (e.g. IStartUpTask.RunTask) is tied to the interface, not the base class.
I appreciate this may not be specific to structuremap (perhaps more a question of reflection).
Thanks,
Ben
Do you know all of the specific interfaces at registration time? If so, you can make a custom registration convention that registers each type with the plugin "family" of the interface it implements. An IRegistrationConvention gets each type, one at a time. You could do a simple check to see if the current type implements the desired interface, and if so, add it.
if (typeof(IStartUpTask).IsAssignableFrom(currentType)){
For<IStartUpTask>().Add(currentType);
}
Then later in the code, you can retrieve plugins for each specific interface individually:
var startupTasks = ObjectFactory.GetAllInstances<IStartUpTask>();
This approach has the benefit of allowing you to inject an enumerable of your custom interface plugins into a class that needs them, instead of making the service location call.
Alternatively, if you don't want to make a registration convention, you can just do the filtering at runtime using the handy OfType linq extension method:
var startupTasks = ObjectFactory.GetAllInstances<PluginBase>().OfType<IStartupTask>();
In case it helps others, I followed Joshua's advice and added my own registration convention:
public class PluginConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry) {
if (type.BaseType == null) return;
if (type.BaseType.Equals(typeof(PSAdmin.Core.Domain.PluginBase))) {
if (typeof(IStartUpTask).IsAssignableFrom(type)) {
registry.For<IStartUpTask>()
.TheDefault.Is.OfConcreteType(type);
}
}
}
}
I couldn't get the .Add method to work, no matter what I tried, so had to use TheDefault.Is.OfConcreteType(type).
Then in my bootstrapper I am scanning like so:
Scan(x => {
x.AssembliesFromPath(HttpContext.Current.Server.MapPath("~/Plugins"),
assembly => assembly.GetName().Name.Contains("Extension"));
x.Convention<PluginConvention>();
});
I can then grab my IStartUp task types like so:
var plugins = ObjectFactory.GetAllInstances<IStartUpTask>();
foreach (var plugin in plugins)
{
plugin.Configure();
}
That said, after reading up on some of the new features of StructureMap, I'm not sure I need to do any of the above. For example I could just change my Scan delegate function to:
Scan(x => {
x.AssembliesFromPath(HttpContext.Current.Server.MapPath("~/Plugins"),
assembly => assembly.GetName().Name.Contains("Extension"));
x.AddAllTypesOf<PluginBase>();
});
And to use my interface concrete types (that inherit from PluginBase):
var tasks = ObjectFactory.Model.GetAllPossible<IStartUpTask>();
foreach (var task in tasks)
{
task.Configure();
}
Both methods seem to achieve the same thing.

Resources