1

I am trying to create a "User Service" class where I Expose only the methods that would need to go through this. One of this methods is FindById. Here is my code:

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security.DataProtection;

public interface IUserService : IDisposable
{
    Task<CustomUser> FindByIdAsync(string userId);
    ICustomUser FindById(string userId);
}

public class UserService : UserManager<CustomUser>, IUserService
{
    public UserService(IUserStore<CustomUser> store, IDataProtectionProvider dataProvider)
        : base(store)
    {
        UserValidator = new UserValidator<CustomUser>(this)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        PasswordValidator = new PasswordValidator
        {
            RequiredLength = 8,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };

        UserLockoutEnabledByDefault = true;
        DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(1);
        MaxFailedAccessAttemptsBeforeLockout = 5;

        var dataProtectionProvider = dataProvider;
        if (dataProtectionProvider != null)
        {
            UserTokenProvider =
                new DataProtectorTokenProvider<CustomUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }

    public new async Task<ICustomUser> FindByIdAsync(string userId)
    {
        return await base.FindByIdAsync(userId);
    }

    public ICustomUser FindById(string userId)
    {
        return base.FindById(userId);
    }
}

The FindByIdAsync method works fine, however the FindById method won't even compile. My autocomplete suggests that the method is there, but when I type it out, it becomes red and says:

Microsoft.AspNet.Identity.UserManager does not contain a definition for FindById

What am I doing wrong?

EDIT:

FindById comes from UserManagerExtensions (see https://msdn.microsoft.com/en-us/library/dn497471(v=vs.108).aspx). Does this mean that I have to extend the extensions class somehow? All I am really trying to do is allow the use of this method via my interface which is IUserService, but adding a reference there it forces me to implement a method, which I tried to do with little success as you can see above

Bagzli
  • 6,254
  • 17
  • 80
  • 163
  • As always - errors are most helpful if you pay attention to them: This error is telling you that there is no findbyid for that. And there isn't. Please see the MSDN: https://msdn.microsoft.com/en-us/library/dn613290(v=vs.108).aspx – Shannon Holsinger Sep 26 '16 at 14:35
  • @trailmax FindByIdAsync method works fine, I am trying to get FindById method to work – Bagzli Sep 26 '16 at 14:36
  • @ShannonHolsinger I read the error message, however according to multiple sources, here is one http://stackoverflow.com/questions/20925822/asp-mvc5-identity-how-to-get-current-applicationuser I should be able to call that method via UserManager, and this class is that UserManager. The IntelliSense also shows me that the method exists. This is why i am so confused about it. – Bagzli Sep 26 '16 at 14:38
  • @ShannonHolsinger Hey man, I appreciate the help, even if it comes in a form of unnecessary rudeness, I really do, but according to documentation: https://msdn.microsoft.com/en-us/library/dn497471(v=vs.108).aspx It should come from the extension. So seeing how i have it referenced, why does it not allow me to use it? IntelliSense can see it. – Bagzli Sep 26 '16 at 14:43
  • **UserManagerExtensions**.FindById sorry man - bad morning. Don't mean to take it out on you. I didn't dv by the way. – Shannon Holsinger Sep 26 '16 at 14:47
  • @ShannonHolsinger no worries, how would I implement that with my class? I can't type `UserManagerExtension.FindById` because I don't have such a class and mine Extends the original Manager class. I'm not sure how to tap into the extension from the main class, is that possible? – Bagzli Sep 26 '16 at 14:50
  • Since it's inheriting from UserManager, it gets the extention as well. since your code is just calling `base.FindById` just remove the function, and it will work like you intend. – gilmishal Sep 26 '16 at 14:54
  • @gilmishal if I do that, my interface complains that it requires the method. – Bagzli Sep 26 '16 at 14:55
  • then you shouldn't inherit from UserManager, just hold a UserManager field. – gilmishal Sep 26 '16 at 14:56
  • The reason you can call the async version is because you hide the method in the UserManager class by adding the `new` keyword in method definition. – Glubus Sep 26 '16 at 14:56
  • @Glubus yeah, I understand that part. I'm more confused how do I tap into the extension. – Bagzli Sep 26 '16 at 14:59
  • @gilmishal would that be the only way? It then means I need to have 1 class that extends the user manager, and another that instantiates it and uses it (this would be the service). – Bagzli Sep 26 '16 at 15:01
  • Check the answer given here: http://stackoverflow.com/questions/2059425/in-c-can-a-class-inherit-from-another-class-and-an-interface. If your interface has different signatures for these methods you need to aggregate the `UserManager` class, otherwise you can just leave the implementation of these methods to the baseclass. – Glubus Sep 26 '16 at 15:06
  • Come to think of it this is odd, this should actually work for you, are you sure you aren't missing a reference? base is of type UserManager isn't it? That being said, there is nothing wrong with having a different class for UserService, and extending UserManager – gilmishal Sep 26 '16 at 15:14
  • @gilmishal The problem is with Naming of the method. If I try to call the method lets say Test and I return `this.FindById(userId);`then it works. However, the moment I call my method FindById it will complain about the recursive call. So I suppose the way to go about it is to call my method something else. – Bagzli Sep 26 '16 at 15:24

1 Answers1

0

You can't call an extension method for base

The reason for that seems to be that you can't pass base as a parameter, and that what an extension method is.

You can call the method in a static context like this, instead of as an extension.

public ICustomUser FindById(string userId)
{
    return UserManagerExtentions.FindById(this, userId);
}
Community
  • 1
  • 1
gilmishal
  • 1,884
  • 1
  • 22
  • 37
  • While you are correct in saying that we can't call an extension method from the base, in my example I'm not calling it from a base, but from a class that extends that base. As such I should (and I do) have access to the method. However, the real problem lies in that I cannot use the same method name in my child class name because of the extension, if I do it will hide the extension and the child class itself won't be able to call it. It enters an infinite loop of calling itself. The way around this is to call the method something else. At least that is the solution I went with. – Bagzli Sep 26 '16 at 16:02