Successfully implementing custom UserManager<IUser> in Identity 2.0 - c#

I'm trying to navigate the black hole that is the custom implementation of Identity Membership. My goal right now is simply to get this line from my ApiController to correctly retrieve my UserManager:
public IHttpActionResult Index()
{
var manager = HttpContext.Current.GetOwinContext().GetUserManager<UserManager<MyUser,int>>();
//manager is null
}
Here's my setup. In my Startup's Configuration I set up the WebApi and add my OwinContext:
app.CreatePerOwinContext<UserManager<MyUser,int>>(Create);
My Create method:
public static UserManager<User,int> Create(IdentityFactoryOptions<UserManager<MyUser,int>> options, IOwinContext context)
{
return new UserManager<MyUser,int>(new UserStore(new DbContext()));
}
the rest is the most basic implementation I can make.
MyUser:
public class MyUser : IUser<int>
{
public int Id { get; set; }
public string UserName { get; set; }
}
MyUserStore:
public class MyUserStore : IUserStore<MyUser,int>
{
private IdentityDbContext context;
public MyUserStore(IdentityDbContext c)
{
context = c;
}
//Create,Delete, etc implementations
}
MyDbContext:
public class MyDbContext : IdentityDbContext
{
public MyDbContext() : base("Conn")
{
}
}
This is all for the sake of learning how Identity works, which I'm pretty convinced no one actually knows. I want to be able to fully customize my Users and Roles eventually, avoiding Microsoft's IdentityUser.
Again, my issue right now is that in my controller, I am getting null when trying to retrieve my UserManager.
Any and all help is greatly appreciated.

I had several errors, but the main one was that my Startup class looked like :
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseWebApi(new WebApiConfig());
app.CreatePerOwinContext(MyDbContext.Create);
app.CreatePerOwinContext<MyUserManager>(MyUserManager.Create);
}
}
Of course, the OWIN pipeline will plug my dependencies after firing off the WebAPI calls. Switching those around was my main problem.
In addition, I finally found this great guide way down in my Google search. It answers pretty much everything I was getting at. I needed to implement a concrete class that was a UserManager<MyUser,int>
I hope this is able to help someone later on.

Are you using MyIdentity.User or MyIdentity.MyUser? You have two different objects passed into the TUser parameter in your examples.
I tested your implementation and did not have issues retrieving the registered instance of the UserManager.
To fully customize your Users and Roles, you will need to end up writing a new implementation of the UserManager in order to get your Authentication, Claims, Roles, method calls, etc to work.
If you are trying to learn how Identity works, I would suggest working with the default implementation of UserManager and IdentityUser. Get that to work first.
Here is a good tutorial
Eventually, create your own users implementing IdentityUser. All of the UserManager functions will work and you will have access to your new properties. The additional properties will automatically be built into the AspnetUser table generated by the IdentityDbContext.
public MyIdentityUser : IdentityUser
{
public int Id {get; set;}
public string CustomUserId {get; set;}
public string UserId { get; set; }
}
Or you can start building your custom MyIdentityUser with foreign key references to other objects.
public MyIdentityUser : IdentityUser
{
public virtual UserProperties Properties { get; set; }
}
Does this help any?

Related

MVC .net core: Validator.TryValidateObject is not validating attributes, defined in a buddy class

We used DB-first approach to generate models in a .NET core application. DataAnnotations were put in a "buddy" metadata class so as to avoid writing in an autogenerated file. When controller calls TryValidateModel, all works well, Name property is required.
public partial class User
{
public string Name { get; set; }
}
[ModelMetadataType(typeof(UserMetaData))]
public partial class User : IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { }
}
public class UserMetaData
{
[Required]
public string Name { get; set; }
}
On a service layer of the app, we want to implement additional validation, that also checks if objects are valid in regards to data annotations. This is done via
Validator.TryValidateObject()
which successfully calls Validate method, but disregards data annotations - user is valid, even with an empty name.
TL;DR:
MVC (web project) knows how to consider data annotations put in a "buddy" class via ModelMetadataType attribute, service layer project does not.
I thought i have found the answer here, but it seems that
TypeDescriptor.AddProviderTransparent
does not work for .net core apps.
Any ideas would be greatly appreciated.
I really hoped for a one line solution :)
I abused ashrafs answer to his own question like so:
var metadataAttr = typeof(T).GetCustomAttributes(typeof(ModelMetadataTypeAttribute), true).OfType<ModelMetadataTypeAttribute>().FirstOrDefault();
if (metadataAttr != null)
{
var metadataClassProperties = TypeDescriptor.GetProperties(metadataAttr.MetadataType).Cast<PropertyDescriptor>();
var modelClassProperties = TypeDescriptor.GetProperties(typeof(T)).Cast<PropertyDescriptor>();
var errs =
from metaProp in metadataClassProperties
join modelProp in modelClassProperties
on metaProp.Name equals modelProp.Name
from attribute in metaProp.Attributes.OfType<ValidationAttribute>()
where !attribute.IsValid(modelProp.GetValue(model))
select new ValidationResult(attribute.FormatErrorMessage(Reflector.GetPropertyDisplayName<T>(metaProp.Name)), new[] { metaProp.Name });
validationResults.AddRange(errs);
}

DataAccessLayer and organize solution

I have a MVC solution :
In my different file :
Library.DataAccessLayer.LibraryContext.cs :
namespace Library.DataAccessLayer
{
public class LibraryContext : DbContext
{
public LibraryContext() : base("DefaultConnection")
{
}
public DbSet<Book> Books { get; set; }
public DbSet<Author> Authors { get; set; }
}
}
Library.DataAccessLayer.Models.Author.cs :
namespace Library.DataAccessLayer.Models
{
public class Author
{
[Key]
public int AuthorID { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
.........
}
}
Library.DataAccessLayer.Repositories.AuthorRepository.cs :
namespace Library.DataAccessLayer.Repositories
{
public class AuthorRepository : IDisposable, IAuthorRepository
{
private LibraryContext context;
public AuthorRepository(LibraryContext context)
{
this.context = context;
}
public IEnumerable<Author> GetAuthors()
{
return context.Authors.ToList();
}
public Author GetAuthorById(int id)
{
return .........
}
............
}
}
And in Library.Controllers.AuthorController :
namespace Library.Controllers
{
public class AuthorController : Controller
{
private IAuthorRepository authorRepository;
public AuthorController()
{
this.authorRepository = new AuthorRepository(new LibraryContext());
}
public ActionResult Index()
{
var authors = authorRepository.GetAuthors();
return View(authors);
}
}
}
1/ This architecture is coherent ?
2/ Is it really useful to declare interfaces for my repositories which are implemented in my repository classes ?
3/ In my AuthorRepository, the declaration and call of the LibraryContext is correct?
4/ In my AuthorController, my declaration and call of AuthorRepository is correct ?
5/ In which folder can we put the file LibraryContext ? (If necessary and useful)
6/ Is it good to group repositories interfaces and repositories class in the same folder? If not, how to separate and name the various folders ?
7/ How to improve that?
I need your advices.
Thanks
I find the architecture simple, which is good, maybe as your application grows you'll need more layers
Yeah, is really good, specially if you are going to use dependency injection, which leads to the next questions.
Your implementation is right, as for dependencies you should use some design patterns as, again, dependency injection or factory. All your dependencies should be instantiated outside.
This one should be the same as the previous one, the repository should be instantiated outside.
The structure is supposed to accommodate your needs, but I find the example in here pretty useful
Many developers do it that way, some also, and some others, like me, keep them in separate files, personally I create a 'contracts' folder alongside my repositories and keep the interfaces there.
The best way to find a convention that accommodates you is reading code from other developers, there you will find many styles, structures, architecture and pattern implementations.
I hope you find this useful, May the force be with you
This question is more fit to Codereview website, but I think it deserves an answer here:
Repositories are fine, but you should also consider defining a service layer. Services are responsible for aggregating information using repositories and providing this information using service models. Sending back data models (e.g. Authors) might lead to trouble because:
serialization can fail if navigation properties create cycles
you want to provide more information that is not related to data layer (e.g. some computed stuff)
Example:
class AuthorServiceModel
{
int AuthorId { get; set; }
string FirstName { get; set; }
// ...
}
class LibraryService : ILibraryService // if DI is used
{
public AuthorServiceModel GetAuthorById(int id)
{
// error handling/logging may be put here, if an invalid id is provided
var author = context.Authors.Get(id);
// auto mapping can be used to avoid the typing - check http://automapper.org/
var sm = new AuthorServiceModel { AuthorId = author.AuthorId, FirstName = author.FirstName };
return sm;
}
//
}
The controller will never have to know about your data access layer
2) Repositories unification - if most of your repositories are doing just the standard operations (get all, get by identifier, update entity, remove entity etc.), you may define a generic typed repository that helps you to avoid the repetition:
class Repository<T> : IRepository<T>
{
private LibraryContext context;
public IQueryable<T> All => context.Set<T>().AsQueryable();
public IQueryable<T> AllNoTracking => context.Set<T>().AsNoTracking();
public T Get(int id)
{
return context.Set<T>().Find(id);
}
// other methods
}
3) Implementing interfaces can be useful when using Dependency Injection - DI (e.g. Ninject). This removes some coupling between your classes and also allows automatic testing (bindings can be changed to mock objects). E.g.:
public class LibraryContext : DbContext, ILibraryContext
{
public LibraryContext() : base("DefaultConnection")
{
}
// other methods here
}
public class AuthorRepository : IDisposable, IAuthorRepository
{
private ILibraryContext context;
// the context will be injected and should not be provided by the caller, if DI is used
public AuthorRepository(ILibraryContext context)
{
this.context = context;
}
// other methods come here
}
public class AuthorController : Controller
{
// this allows for automatic injection based on defined bindings
[Inject]
public IAuthorRepository authorRepository { get; set; }
public AuthorController()
{
// no need for this, as DI takes care of the initialization
// also, controller does not have to know about your data access classes
// this.authorRepository = new AuthorRepository(new LibraryContext());
}
public ActionResult Index()
{
var authors = authorRepository.GetAuthors();
return View(authors);
}
}
4) Grouping of files is a matter of taste, but I usually recommend groping them semantically (all classes and interfaces that do similar jobs in a folder). Also, data context and repositories are quite coupled and they can reside in the same project/assembly.
Also, services can be separated in their own project/assembly.
NOTE: For a more thorough analysis, consider providing all the code related to your patterns and post your question on Codereview (they deal with complete and working code, not just fragments). It is a great chance that someone will cover all the topics from naming to the patterns).

Extend the ClaimsPrincipal and ClaimsIdentity classes in MVC-6

I've been trying to figure this thing out for a few days now, but have to turn to you guys (again).
As the title says, I would like to implement my custom ClaimsPrincipal and ClaimsIdentity, so that I can attach a few more properties to my Identity-instance.
I have done this earlier in MVC-5, using Global.asax.cs and an inherited BaseController. In MVC-6 it seems like startup.cs would be the entry point for this, but I can't figure it out.
These are my two classes:
public class BaseIdentity : ClaimsIdentity
{
public Guid UserId { get; set; }
public Guid OrgId { get; set; }
public string OrgName { get; set; }
public BaseIdentity()
{
}
}
And..
public class BasePrincipal : ClaimsPrincipal
{
private readonly BaseIdentity _identity;
public BasePrincipal(BaseIdentity identity)
{
_identity = identity;
}
public new BaseIdentity Identity
{
get { return _identity; }
}
}
How can I use these classes, instead of the default, when creating / retrieving Auth cookie?
There is a method called IApplicationBuilder.UseClaimsTransformation() , but can't find any documentation on how to use it - if it's even for this scenario?
Help much appreciated at this point! :)
BTW: I would like to point out that I've asked a similar question a week ago, when I first encountered this challenge. I got an answer, but this is something that I really have to fix, to make my website usable on MVC-6.
I've done this using extension methods instead of inheritance.
public static class PrincipalExtensions
{
public static string GetEmployeeNumber(this ClaimsPrincipal claimsPrincipal)
{
return claimsPrincipal.FindFirstValue("EmployeeNumber");
}
}

Adding a class which uses DbContext to ASP.NET Identity 2 project

I'm working with ASP.NET MVC application which is based on Identity sample available via NuGet. Because of this I already have some classes to work with the database e.g. ApplicationDbContext.
Say, I decided to let users leave requests for the administrator. I've added the Request class to the models:
public class Request
{
public int Id { get; set; }
public string Message { get; set; }
public ApplicationUser User { get; set; }
}
Since the sample uses different managers to work with users, roles, etc, I've decided to create another one called ApplicationRequestManager inside the Identity.config file (though I'm not sure it's a good practice).
public class ApplicationRequestManager : IRequestManager
{
private ApplicationDbContext db = new ApplicationDbContext();
public void Add(Request request)
{
db.Requests.Add(request);
db.SaveChanges();
}
...
}
This class uses the ApplicationDbContext to work with the database and has some methods to create a request, find it and so on.
I've created a method responsible for sending request inside the Manage controller:
public ActionResult SendRequest(IndexViewModel model)
{
Request request = new Request { Message = model.Message, User = UserManager.FindById(User.Identity.GetUserId()) };
requestManager.Add(request);
return View();
}
When this method is invoked, I get the following exception:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
If I understood correctly, the reason of exception is that I use one ApplicationDbContext to get User - via UserManager and I use another ApplicationDbContext to add the request - via RequestManager, so my request is attached to two contexts. As far as I know, such mistake can be avoided by passing the same context to both UserManager and RequestManager. However, UserManager gets its context via the OwinContext together with other managers:
// Configure the db context, user manager and role manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
How can I make my own manager follow that pattern as well? I've tried to use the CreatePerOwinContext method like
app.CreatePerOwinContext<ApplicationRequestManager>(ApplicationRequestManager.Create);
And I've also tried to implement the Create method following the RoleManager example
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(new RoleStore<ApplicationRole>(context.Get<ApplicationDbContext>()));
}
But I don't have any Store for my requests so I don't know what I should do with the 'new RoleStore' part. How could I solve that problem?
Updated:
I've tried Gert's solution and it worked:
public class Request
{
public int Id { get; set; }
public string Message { get; set; }
[ForeignKey("User")]
public int ApplicationUserId { get; set; }
public ApplicationUser User { get; set; }
}
var userId = User.Identity.GetUserId();
Request request = new Request
{
Message = model.Message,
ApplicationUserId = userId
};
I've also tired another way using HttpConext.Current.GetOwinContext().Get method. I've added the following line to my ApplicationRequestMananger:
public ApplicationRequestManager()
{
this.db = HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>();
}
And it worked fine with the original Request class.
The question is, what advantages and disadvantages does each way have? I've read about foreign keys and I understand the general idea quite well; but I don't really understand what problems can 'HttpContext.Current.GetOwinContext().Get()' cause. Should I use it since it's simpler than adding foreign keys?
The trouble with your design is that each manager has its own context. Seeing this example, I think each manager should call...
db = context.Get<ApplicationDbContext>();
...or receive the request-bounded context in their constructor.
Apart from that, you could make this much simpler by exposing the foreign field to ApplicationUser (ApplicationUserId?) as a primitive property in Request:
public class Request
{
public int Id { get; set; }
public string Message { get; set; }
[ForeignKey("User")]
public int ApplicationUserId { get; set; }
public ApplicationUser User { get; set; }
}
And then create Request like so:
var userId = User.Identity.GetUserId();
Request request = new Request
{
Message = model.Message,
ApplicationUserId = userId
};
This is refered to as foreign key associations, as opposed to independent associations that only have a reference navigation property.

How to initialize on MVC module?

I am new to MVC programming. In normal OOP, where I have my class, I would just initiliaze and load data from database. In MVC, we have modules, how do I load up records from it?
Here is my current code for type UserAcount:
[Table("UserAccount")]
public class UserAccount {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string userName { get; set; }
public string email { get; set; }
public int companyID { get; set; }
}
Say that I have an user with name "testUser", how do I initialize on this record and get it's information? How do I do this:
UserAccount user = new UserAccount("tesetUser");
How and where shoulud I use this?
user = user.SingleOrDefault(u => u.userName.ToLower() == User.Identity.Name.ToLower());
You need to read up on Entity Framework. This is the default ORM that MVC uses. Simply:
If you don't have a project context, yet, create one:
public class MyProjectContext : DbContext
{
public MyProjectContext()
: base("name=ConnectionStringNameHere")
{
}
}
Add your models to your project context:
public class MyProjectContext : DbContext
{
...
public DbSet<SomeModel> SomeModels { get; set; }
public DbSet<SomeOtherModel> SomeOtherModels { get; set; }
# etc.
}
Update your database using Package Manager Console (TOOLS > Library Package Manager > Package Manager Console):
> update-database
(hit ENTER after typing that)
Now, to use your context in your controllers:
public class MyAwesomeController : Controller
{
private MyProjectContext db = new MyProjectContext();
public ActionResult Index()
{
var someModels = db.SomeModels;
return View(someModels);
}
public ActionResult GetSomeModel(int id)
{
var someModel = db.SomeModels.Find(id);
return View(someModel);
}
# other actions
}
In the simplest case, you should do this logic in your controller, which will pass the data to the view. However, MVC is meant for UI separation of concerns, so theoretically you should be doing this in your domain layer, which is called from your controller.
Here is a decent article from Jeff Atwood, however I disagree that the controller is the brains of the application. It is more of the brains of the UI...but that depends on how complex your code is. Dont create a domain layer if it is stupidly simple
In the MVC model, Controllers are responsible for processing HTTP requests.
Typically you would load your entity (e.g. UserAccount) in a controller action.
If you want to edit / update an entity, typically you would map the relevant fields to a model that reflects the UserAccount. A separate model is suggested because the needs of the UI are often somewhat different than the needs of the entity model. Having separate classes for each concern avoids polluting the entity model to satisfy the needs of the view.

Categories