I am trying to implement a custom UserStore for my MVC 5 application so that I can delegate the database commands to my existing database project.
The tables in my database use integer keys, so I created a custom UserManager that inherits UserManager<User, int> instead of just UserManager<User>. For that reason, I also created a custom UserStore that implements IUserPasswordStore<User, int> instead of just IUserPasswordStore<User>.
Briefly:
public class CustomUserManager : UserManager<User, int>
{
public CustomUserManager(CustomUserStore store) : base(store)
{
}
}
public class CustomUserStore : IUserPasswordStore<User, int>
{
private readonly DbContext _db;
public CustomUserStore(DbContext db)
{
_db = db;
}
public Task<User> FindByIdAsync(int userId)
{
return _db.users.SingleOrDefaultAsync(u => u.Id == userId);
}
public Task UpdateAsync(User user)
{
_db.Entry(user).State = System.Data.Entity.EntityState.Modified;
return _db.SaveChangesAsync();
}
}
Now, it seems that when I call UpdateAsync on CustomUserManager, it does not go through my custom CustomUserStore, but rather through some default implementation or something. The problem is evident because CustomUserManager.UpdateAsync() returns Task<IdentityResult>, while my implementation in CustomUserStore returns just Task. Hence there are no errors or anything, but the method is not being called. I think IUserPasswordStore<User, int> should have some method UpdateAsync that returns Task<IdentityResult> but it doesn't...
On the other hand, the FindByIdAsync method does work fine and calls the method in my CustomUserStore.
I am quite sure the problem is due to inheriting the classes with the custom key type (int in my case). Any example of a custom UserStore I can find online just uses the string keys and does not inherit IUserStore<User, int> but just IUserStore<User>.
However I can't figure out my problem. Perhaps I can just override all the methods in my CustomUserManager but that seems like a work-around rather than a solution. Is this a bug in the framework perhaps, I think the custom key types is still relatively new or even in alpha?
I know that this is an old question but I struggled yesterday with the same issue and after some time spent on it, I decided to take a look in the Identity source code and what I've found, almost made me smashed my head against the wall...
Simple, if you call UserManager.UpdateAsync, in the base class you will see that before the UserStore.UpdateAsync there is a validation that takes place, which, in my case, failed (doesn't matter the reason). So, please, be so kind and check in your class (controller class) the result of UpdateAsync which is an IdentityResult and more then sure the Succes result is false.
Evdin
Related
I'm building REST API on the top of Spring Data Rest. Initially all repositories where extending JpaRepository. Lately decision has been made to take a more flexible approach and use QueryDslPredicateExecutor<T> along with QuerydslBinderCustomizer<Q>.
Pretty much all findAll methods exposed in repositories should address two scenarios
principal has a role ROLE_ADMIN then no filtering should be applied a part from Pageable,Sort
principal does not have a role ROLE_ADMIN I would return only those entities which belong to the current user
Getting that done was as simple as annotating findAll method as below.
#Query("select e from Entity e where e.field = ?#{principal} or 1=?#{hasRole('ROLE_ADMIN') ? 1 : 0}")
Page<Entity> findAll(Pageable pageable);
Now I want our findAll to be something similar to below
Page<Entity> findAll(Predicate predicate, Pageable pageable)
Predicate is being build from request parameters(courtesy of #QuerydslPredicate) and is being passed in to RepositoryEntityController which is all being managed by spring-data-rest which is great.
#ResponseBody
#RequestMapping(value = BASE_MAPPING, method = RequestMethod.GET)
public Resources<?> getCollectionResource(#QuerydslPredicate RootResourceInformation resourceInformation,
DefaultedPageable pageable, Sort sort, PersistentEntityResourceAssembler assembler)
throws ResourceNotFoundException, HttpRequestMethodNotSupportedException {
I want to tweak that predicate(2 scenarios as above that I want to address).
It would be something simialr to below.
BooleanBuilder builder = new BooleanBuilder(predicateBuildFromHttpRequest);
builder.and(predicateAddressingOurRequirements);
builder.getValue();
#PostFilter won't be an option as return type for all repos is Page<Entity>.
Use case that I want to address seems to be quite common to me. Having said that I had a look at spring-data and spring-data-rest documentation and could not find anything related to my question.
Question is : Am I missing something obvious here and there is a quick win for it? or I would need to implement custom solution myself? Any comments very much appreciated!
The Querydsl predicates are constructed by QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver which is sadly package private and can't be directly extended.
However, you can make a copy of that, add your security predicate logic and then drop in your implementation instead of the former resolver.
public class MyQueryDslRootResourceArgumentResolver extends RootResourceInformationHandlerMethodArgumentResolver {
// the most of the code is ommitted, the content is identical with
// QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver,
// the important part is postProcessMethod where you can modify the predicate
#Override
#SuppressWarnings({"unchecked"})
protected RepositoryInvoker postProcess(MethodParameter parameter, RepositoryInvoker invoker,
Class<?> domainType, Map<String, String[]> parameters) {
Object repository = repositories.getRepositoryFor(domainType);
if (!QueryDslPredicateExecutor.class.isInstance(repository)
|| !parameter.hasParameterAnnotation(QuerydslPredicate.class)) {
return invoker;
}
ClassTypeInformation<?> type = ClassTypeInformation.from(domainType);
QuerydslBindings bindings = factory.createBindingsFor(null, type);
// modify your predicate here
Predicate predicate = predicateBuilder.getPredicate(type, toMultiValueMap(parameters), bindings);
return new QuerydslRepositoryInvokerAdapter(invoker, (QueryDslPredicateExecutor<Object>) repository, predicate);
}
}
Then add you own configuration class with the custom resolver implementation.
public class CustomRepositoryRestMvcConfiguration extends RepositoryRestMvcConfiguration {
#Autowired
ApplicationContext applicationContext;
#Override
public RootResourceInformationHandlerMethodArgumentResolver repoRequestArgumentResolver() {
QuerydslBindingsFactory factory = applicationContext.getBean(QuerydslBindingsFactory.class);
QuerydslPredicateBuilder predicateBuilder = new QuerydslPredicateBuilder(defaultConversionService(),
factory.getEntityPathResolver());
return new MyQueryDslRootResourceArgumentResolver(repositories(),
repositoryInvokerFactory(defaultConversionService()), resourceMetadataHandlerMethodArgumentResolver(),
predicateBuilder, factory);
}
}
Here is an example project that modifies the Predicate (that is produced by the parameters from url) before passing it to the repository.
The demonstration of what David Siro explained above
https://github.com/yeldarxman/QueryDslPredicateModifier
I'm trying to add Dagger to an existing web application and am running into a design problem.
Currently our Handlers are created in a dispatcher with something like
registerHandler('/login', new LoginHandler(), HttpMethod.POST)
Inside the login handler we might call a function like
Services.loginService.login('username', 'password');
I want to be able to inject the loginService into the handler, but am having trouble figuring out the best approach. There is a really long list of handlers in the dispatcher, and injecting them all as instance variables seems like a large addition of code.
Is there a solution to this type of problem?
Based on your comment about having different services to inject. I would propose next solution.
ServicesProvider:
#Module(injects = {LoginHandler.class, LogoutHandler.class})
public class ServicesProvider {
#Provides #Singleton public LoginService getLoginService() {
return new LoginService();
}
}
LoginHandler.java:
public class LoginHandler extends Handler {
#Inject LoginService loginService;
}
HttpNetwork.java
public class HttpNetwork extends Network {
private ObjectGraph objectGraph = ObjectGraph.create(new ServicesProvider());
public registerHandler(String path, Handler handler, String methodType) {
getObjectGraph().inject(handler);
}
}
There is one week point in this solution - you can't easily change ServiceProvider for test purpose (or any other kind of purpose). But if you inject it also (for example with another object graph or just through constructor) you can fix this situation.
In my asp.net mvc controller`s constructor I have multiple (5) interfaces which communicate with my database in this way:
[HttpGet]
public ActionResult Create()
{
var releases = _releaseDataProvider.GetReleases();
var templates = _templateDataProvider.GetTemplates();
var createTestplanViewModel = new CreateTestplanViewModel(templates, releases);
return PartialView(createTestplanViewModel);
}
Above I use 2 different interfaces to get data from the database.
business case: To create a testplan I need to show the user the available releases + templates he can choose from.
How can I decrease the dependency/over-injection of these 2 interfaces
In the MVC project:
public class MyController : Controller
{
private readonly IQueryProcessor _queryProcessor;
public MyController(IQueryProcessor queryProcessor)
{
_queryProcessor = queryProcessor;
}
[HttpGet]
public ActionResult Create()
{
var releases = _queryProcessor.Execute(new ProvideReleaseData());
var templates = _queryProcessor.Execute(new ProvideTemplateData());
var createTestplanViewModel = AutoMapper.Mapper
.Map<CreateTestplanViewModel>(releases);
AutoMapper.Mapper.Map(templates, createTestplanViewModel);
return PartialView(createTestplanViewModel);
}
}
You can then constructor inject your current provider implementations into IQueryHandler implementations. The IQueryProcessor is just infrastructure. See this for more info: https://cuttingedge.it/blogs/steven/pivot/entry.php?id=92
Reply to comments:
It's at the site I linked to. Here's mine:
using System.Diagnostics;
using SimpleInjector;
namespace MyApp.Infrastructure
{
sealed class SimpleQueryProcessor : IQueryProcessor
{
private readonly Container _container;
public SimpleQueryProcessor(Container container)
{
_container = container;
}
[DebuggerStepThrough]
public TResult Execute<TResult>(IDefineQuery<TResult> query)
{
var handlerType = typeof(IHandleQueries<,>)
.MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = _container.GetInstance(handlerType);
return handler.Handle((dynamic)query);
}
}
}
A good general way to decouple your database would be using a unit of work. Here's a great article on from asp.net, as well as another article on MSDN.
In summary, you create a single unit where all of your database/service calls reside and it can handle the database logic. This would reduce the dependancy of your multiple interfaces into a single point, so you would only need to inject 1 class into your controller.
A quote from the MSDN article:
According to Martin Fowler, the Unit of Work pattern "maintains a list
of objects affected by a business transaction and coordinates the
writing out of changes and the resolution of concurrency problems."
EDIT
It seems to me you basically have these options to reduce constructor dependency count here:
Split the controller
Add layer in front of the two interfaces
Switch to property injection
Service locator
#3 and #4 are included for good measure, but they obviously don't actually decrease the dependency count, they only hide them from the constructor. They also have several disadvantages, and I consider service locator especially evil most of the time.
For #1, if you feel your constructor is actually doing two+ jobs, and there is a clean separation where you could split, I would do so. I assume from your responses that you have already considered this, however, and don't want to do this.
That leaves #2 - adding another layer. In this case that would be introducing a factory interface for that particular view model. Naively, I'll name this ICreateTestplanViewModelFactory, but you can name it something more sensical for your app if you wish. A single method on it would construct a CreateTestplanViewModel.
This makes the fact that the data for this view is coming from 2 sources merely an implementation detail. You would wire up an implementation which takes IReleaseDataProvider and ITemplateDataProvider as constructor dependencies.
This is along the lines of what I was suggesting:
public interface IProvideTestPlanSetupModel
{
CreateTestplanViewModel GetModel();
}
public class TestPlanSetupProvider : IProvideTestPlanSetupModel
{
private readonly IReleaseDataProvider _releaseDataProvider;
private readonly ITemplateDataProvider _templateDataProvider;
public TestPlanSetupProvider(IReleaseDataProvider releaseDataProvider, ITemplateDataProvider templateDataProvider)
{
_releaseDataProvider = releaseDataProvider;
_templateDataProvider = templateDataProvider;
}
public CreateTestplanViewModel GetModel()
{
var releases = _releaseDataProvider.GetReleases();
var templates = _templateDataProvider.GetTemplates();
return new CreateTestplanViewModel(releases, templates);
}
}
public class TestPlanController : Controller
{
private readonly IProvideTestPlanSetupModel _testPlanSetupProvider;
public TestPlanController(IProvideTestPlanSetupModel testPlanSetupProvider)
{
_testPlanSetupProvider = testPlanSetupProvider;
}
[HttpGet]
public ActionResult Create()
{
var createTestplanViewModel = _testPlanSetupProvider.GetModel();
return PartialView(createTestplanViewModel);
}
}
If you don't like constructing a view model anywhere outside the controller, the interface could provide an intermediate object with the same properties that you would copy to the view model. But that is silly, as this combination of data is only relevant for that particular view, which is precisely what the view model is supposed to represent.
On a side note, it seems you are running into pretty common annoyances doing read/write through the same model. Since these issues bother you so, you might investigate CQRS, which perhaps would make you feel less dirty about talking to the database directly for these types of queries and would help you get around the layering labyrinth we all enjoy so much. It seems promising, though I have not yet had the pleasure of test driving it in a production application.
Psssst...!
Read on, by all means. But I can tell you here that the problem had nothing to do with the DataContext, but with Dependency Injection. I have left the question up, as it documents one possible issue with the "row not found or changed error" that has nothing to do with real world concurrency conflicts.
It seems the problems have been caused by badly written dependency injection. Or rather, I am beginning to believe, by default lifecycle management by the DI container I used.
The problem was that I used a DataContext as a constructor argument that was supplied by Ninject. It seems that the default behaviour was to cache this DataContext, leading to all manner of unexpected behaviour. I will ask a separate question about this.
Anyway, what follows is my original question, which as you will see, misses the real cause of the issue by a mile...
The Problem
I am getting a number of errors that imply that the DataContext, or rather, the way I am using the DataContext is getting out of synch.
The error occurs on db.SubmitChanges() where db is my DataContext instance. The error is:
Row not found or changed.
The problem only occurs intermitently, for example, adding a row then deleting it. If I stop the dev server and restart, the added row is there and I can delete it no problem.
Ie, it seems that the problem is related to the DataContext losing track of the rows that have been added.
IMPORTANT:
Before anyone votes to close this thread, on the basis of it being a duplicate, I have checked the sql server profiler and there is no "Where 0 = 1" in the SQL.
I have also recreated the dbml file, so am satisfied that the database schema is in synch with the schema represented by the dbml file.
Ie, no cases of mismatched nullable/not nullable columns, etc.
My Diagnosis (for what it is worth):
The problem seems (to me) related to how I am using the DataContext. I am new to MVC, Repositories and Services patterns, so suspect that I have wired things up wrong.
The Setup
Simple eLearning app in its early stages. Pupils need to be able to add and delete courses (Courses table) to their UserCourses.
To do this, I have a service that gets a specific DataContext instance Dependency Injected into its constructor.
Service Class Constructor:
public class SqlPupilBlockService : IPupilBlockService
{
DataContext db;
public SqlPupilBlockService(DataContext db)
{
this.db = db;
CoursesRepository = new SqlRepository<Course>(db);
UserCoursesRepository = new SqlRepository<UserCourse>(db);
}
// Etc, etc
}
The CoursesRepository and UserCoursesRepository are both private properties of the service class that are of type IRepository (just a simple generic repository interface).
SqlRepository Code:
public class SqlRepository<T> : IRepository<T> where T : class
{
DataContext db;
public SqlRepository(DataContext db)
{
this.db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
db.SubmitChanges();
}
#endregion
}
The two methods for adding and deleting UserCourses are:
Service Methods for Adding and Deleting UserCourses:
public void AddUserCourse(int courseId)
{
UserCourse uc = new UserCourse();
uc.IdCourse = courseId;
uc.IdUser = UserId;
uc.DateCreated = DateTime.Now;
uc.DateAmended = DateTime.Now;
uc.Role = "Pupil";
uc.CourseNotes = string.Empty;
uc.ActiveStepIndex = 0;
UserCoursesRepository.Add(uc);
UserCoursesRepository.Save();
}
public void DeleteUserCourse(int courseId)
{
var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single();
UserCoursesRepository.Delete(uc);
UserCoursesRepository.Save();
}
Ajax
I am using Ajax via Ajax.BeginForm
I don't think that is relevant.
ASP.NET MVC 3
I am using mvc3, but don't think that is relevant: the errors are related to model code.
The problem only occurs intermitently,
for example, adding a row then
deleting it. If I stop the dev server
and restart, the added row is there
and I can delete it no problem.
Your code does not show what the link is between the Added Row and the Delete/Update. Your Add() doesn't return an object reference.
I'm thinking you are missing a Refresh (ie reload the object after Insert). Is your IdCourse also the PK in the Table?
Edit:
Further research has revealed that the problem is with the dependency injection.
The problem was related to how Dependency Injection manages the items it creates. Google for 'lifecycle management' in IoC or DI. Essentially, DI cached a DataContext constructor argument that I injected.
For a way to solve this using the Factory Pattern, see this thread:
Ninject caching an injected DataContext? Lifecycle Management?
The accepted answer solved it all.
Recently I've switched to Ninject 2.0 release and started getting the following error:
Error occured: Error activating SomeController
More than one matching bindings are available.
Activation path:
1) Request for SomeController
Suggestions:
1) Ensure that you have defined a binding for SomeController only once.
However, I'm unable to find certain reproduction path. Sometimes it occurs, sometimes it does not.
I'm using NinjectHttpApplication for automatic controllers injection. Controllers are defined in separate assembly:
public class App : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
INinjectModule[] modules = new INinjectModule[] {
new MiscModule(),
new ProvidersModule(),
new RepositoryModule(),
new ServiceModule()
};
return new StandardKernel(modules);
}
protected override void OnApplicationStarted()
{
RegisterRoutes(RouteTable.Routes);
RegisterAllControllersIn("Sample.Mvc");
base.OnApplicationStarted();
}
/* ............. */
}
Maybe someone is familiar with this error.
Any advice?
I finally figured this issue out recently. Apparently, the NinjectHttpApplication.RegisterAllControllersIn() function doesn't do all of the proper bindings needed. It binds your concrete controller implementations to IController requests. For example, if you have a controller class called SampleMvcController, which inherits from System.Web.Mvc.Controller. It would do the following named binding during application start:
kernel.Bind<IController>().To(SampleMvcController).InTransientScope().Named("SampleMvc");
But when debugging the NinjectControllerFactory, I find that request are being made for the Ninject Kernel to return an object for the class "SampleMvcController", not for a concrete implementation of IController, using the named binding of "SampleMvc".
Because of this, when the first web request that involves the SampleMvcController is made, it creates a binding of SampleMvcController to itself. This is not thread safe though. So if you have several web requests being made at once, the bindings can potentially happen more than once, and now you are left with this error for having multiple bindings for the SampleMvcController.
You can verify this by quickly refreshing an MVC URL, right after causing your web application to restart.
The fix:
The simplest way to fix this issue is to create a new NinjectModule for your controller bindings, and to load this module during application start. Within this module, you self bind each of your defined controllers, like so:
class ControllerModule : StandardModule {
public override Load() {
Bind<SampleMvcController>().ToSelf();
Bind<AnotherMvcController>().ToSelf();
}
}
But if you don't mind changing the Ninject source code, you can modify the RegisterAllControllersIn() function to self bind each controller it comes across.
I have been dealing with this problem for months. I tried so many options but was unable to come to a solution. I knew that it was a threading problem because it would only occur when there was a heavy load on my site. Just recently a bug was reported and fixed in the ninject source code that solves this problem.
Here is a reference to the issue. It was fixed in build 2.1.0.70 of the Ninject source. The key change was in KernelBase.cs by removing the line
context.Plan = planner.GetPlan(service);
and replacing it with
lock (planner)
{
context.Plan = planner.GetPlan(service);
}
To use this new build with MVC you will need to get the latest build of Ninject then get the latest build of ninject.web.mvc. Build ninject.web.mvc with the new Ninject build.
I have been using this new build for about a week with a heavy load and no problems. That is the longest it has gone without a problem so I would consider this to be a solution.
Are you sure you really are creating a single completely new Kernel from scratch in your OnApplicationStarted every time it's invoked ? If you're not and you're actually creating it once but potentially running the registration bit twice. Remember that you're not guaranteed to only ever have one App class instantiated ever within a given AppDomain.
My answer was a bit more obvious.
I had declared the binding for one of my controllers more than once during refactor of my code.
I added this to my global.ascx.cs file:
public void RegisterAllControllersInFix(Assembly assembly)
{
RegisterAllControllersInFix(assembly, GetControllerName);
}
public void RegisterAllControllersInFix(Assembly assembly, Func<Type, string> namingConvention)
{
foreach (Type type in assembly.GetExportedTypes().Where(IsController))
Kernel.Bind(type).ToSelf();
}
private static bool IsController(Type type)
{
return typeof(IController).IsAssignableFrom(type) && type.IsPublic && !type.IsAbstract && !type.IsInterface;
}
private static string GetControllerName(Type type)
{
string name = type.Name.ToLowerInvariant();
if (name.EndsWith("controller"))
name = name.Substring(0, name.IndexOf("controller"));
return name;
}
Then called it from my OnApplicationStarted() method as follows:
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
RegisterAllControllersInFix(Assembly.GetExecutingAssembly());
Difficult to know whether this fixed it though because it's so intermittent.