我们可以在域驱动设计中使用ASP.NET标识吗?

时间:2022-12-02 10:13:51

Our team decided to use Domain Driven Design architecture for our project. Now the discussion is going on for, "can we use ASP.NET Identity in DDD?".

我们的团队决定为我们的项目使用域驱动设计架构。现在正在进行讨论,“我们可以在DDD中使用ASP.NET身份吗?”。

Is there any disadvantages on using ASP.NET identity in DDD design.

在DDD设计中使用ASP.NET标识是否有任何缺点。

I'm in a confusion to make a decision on it.

我对此做出决定感到困惑。

I have searched for it, but I didn't get any idea.

我已经搜索过了,但我没有想到。

Any help would be appreciable.

任何帮助都会很明显。

3 个解决方案

#1


15  

The questions reveals several misconceptions:

这些问题揭示了一些误解:

It appears that you perceive the domain model as some monolithic model where you put every piece of application in. Instead, concentrate on strategic patterns to distinguish Bounded Contexts. Consider the domain as a composition of several loosely interconnected components. Then identify what your core domain is and apply DDD tactical patterns there. Not every ccomponent needs DDD. Some of them even should not use DDD. Especially - generic domains, like Authentication.

您似乎将域模型视为一个单一的模型,您可以将每个应用程序放入其中。相反,请专注于战略模式以区分有界上下文。将域视为几个松散互连组件的组合。然后确定您的核心域名是什么,并在那里应用DDD战术模式。并非每个ccomponent都需要DDD。其中一些人甚至不应该使用DDD。特别是 - 通用域,如身份验证。

DDD is technology agnostic (to some point) so yes, you can use ASP.NET Identity or whatever library you like.

DDD是技术不可知的(在某些方面)所以是的,你可以使用ASP.NET Identity或任何你喜欢的库。

Authentication typically belongs to the Application layer, not Domain layer.

身份验证通常属于Application层,而不属于Domain层。

However - if in your domain there is a concept of a user/client/person, it might be required to use the identity provided by the identity component. But you have to understand that the meaning of User in your bounded context is different than meaning of User in Identity component. These are not the same concept. Although they both refer to the same physical person sitting somewhere and clicking on your app's GUI, they are 2 different models (or projections) of him that serve different purposes. So you shouldn't just reuse the ASP.NET User class in your bounded context.

但是 - 如果在您的域中存在用户/客户端/人的概念,则可能需要使用身份组件提供的身份。但是你必须明白,在有界上下文中User的含义与Identity in Identity中的含义不同。这些概念不一样。虽然他们都指的是坐在某个地方并点击你应用程序GUI的同一个身体的人,但他们是两个不同的模型(或投影),用于不同的目的。因此,您不应该仅仅在有界上下文中重用ASP.NET User类。

Instead - separate contexts should communicate via an anticorruption layer. Basically you have to make some service (interface only) in your bounded context that produces context-specific User objects. The implementation of that interface made in infrastructure layer will be a wrapper of ASP.NET Identity that gets ASP.NET Identity user and produce corresponding bounded context's user.

相反 - 单独的上下文应该通过反腐败层进行通信。基本上,您必须在有界上下文中创建一些服务(仅限接口),以生成特定于上下文的User对象。在基础结构层中实现的该接口的实现将是ASP.NET标识的包装,它获取ASP.NET标识用户并生成相应的有界上下文的用户。

#2


1  

You can use anything you like. But be aware of pollution particular solution is going to make. If your domain model gets messed up with hundreds of lines of asp.net technical kind of plumbing code that makes your domain logic hard to perceive and you are missing point of DDD.

你可以使用任何你喜欢的东西。但要注意污染特定的解决方案。如果您的域模型被数百行asp.net技术类型的管道代码搞砸了,这使得您的域逻辑难以察觉并且您缺少DDD点。

In ideal situation - your domain model should depend only on programming language.

在理想情况下 - 您的域模型应仅依赖于编程语言。

Also - you might find something useful from my long time ago implementation of user session related code.

此外 - 您可能会在我很久以前的用户会话相关代码实现中找到有用的东西。

#3


0  

I am new to DDD. But I achieved integration with Identity and DDD. Although I doubt it truly sticks to the priciples of DDD.

我是DDD的新手。但我实现了与Identity和DDD的集成。虽然我怀疑它真的坚持DDD的原则。

I started with the Entity:

我从实体开始:

public partial class User : IdentityUser {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager) {
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
        /// <summary>
        /// The Date the User Registered for general information purposes
        /// </summary>
        public DateTime DateRegistered { get; set; }
    }

Then the Interface:

接口:

public interface IUserRepository:IBaseRepository<User> {
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns>Identity Result</returns>
        Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe);
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser);
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code);
        void ForgotPassword();
        void ForgotPasswordConfirmation();
        void ResetPassword();
        void ResetPasswordConfirmation();
        void ExternalLogin();
        void SendCode();
        void ExternalLoginCallback();
        void ExternalLoginConfirmation();
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        void Logoff(IAuthenticationManager AuthenticationManager);
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        User GetUser(string Email);
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        User GetUserById(string ID);
    }

Then the Repository:

然后是存储库:

public class UserRepository : BaseRepository<User>, IUserRepository {
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        public async Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code) =>
            await userManager.ConfirmEmailAsync(userId, code);

        public void ExternalLogin() {
            throw new NotImplementedException();
        }

        public void ExternalLoginCallback() {
            throw new NotImplementedException();
        }

        public void ExternalLoginConfirmation() {
            throw new NotImplementedException();
        }

        public void ForgotPassword() {
            throw new NotImplementedException();
        }

        public void ForgotPasswordConfirmation() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        public User GetUser(string Email) =>
            _context.Users.Where(p => p.Email == Email).FirstOrDefault();
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        public User GetUserById(string ID) => 
            _context.Users.Find(ID);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        public async Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe) =>
            await signinManager.PasswordSignInAsync(email, password, rememberMe, shouldLockout: false);
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        public void Logoff(IAuthenticationManager AuthenticationManager) {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
        }
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns>Identity Result</returns>
        public async Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password) =>
            await userManager.CreateAsync(user, password);

        public void ResetPassword() {
            throw new NotImplementedException();
        }

        public void ResetPasswordConfirmation() {
            throw new NotImplementedException();
        }

        public void SendCode() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        public async Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser) =>
            await signinManager.TwoFactorSignInAsync(provider, code, isPersistent: rememberMe, rememberBrowser: rememberBrowser);
    }

IService:

IService:

public interface IUserService {
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns></returns>
        Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns></returns>
        Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe);
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns></returns>
        Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser);
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns></returns>
        Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code);
        void ForgotPassword();
        void ForgotPasswordConfirmation();
        void ResetPassword();
        void ResetPasswordConfirmation();
        void ExternalLogin();
        void SendCode();
        void ExternalLoginCallback();
        void ExternalLoginConfirmation();
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        void Logoff(IAuthenticationManager AuthenticationManager);
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        User GetUser(string Email);
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        User GetUserById(string ID);
    }

Service:

服务:

public class UserService : ServiceBase, IUserService {

        #region Private Field

        private IUserRepository _userRepository;

        #endregion

        #region Constructor
        /// <summary>
        /// Constructor to initialise User Repository
        /// </summary>
        /// <param name="userRepository"></param>
        public UserService(IUserRepository userRepository) {
            _userRepository = userRepository;
        }

        #endregion

        #region Methods
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        public Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code) =>
            _userRepository.ConfirmEmail(userManager, userId, code);

        public void ExternalLogin() {
            throw new NotImplementedException();
        }

        public void ExternalLoginCallback() {
            throw new NotImplementedException();
        }

        public void ExternalLoginConfirmation() {
            throw new NotImplementedException();
        }

        public void ForgotPassword() {
            throw new NotImplementedException();
        }

        public void ForgotPasswordConfirmation() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        public User GetUser(string Email) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        public User GetUserById(string ID) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        public Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe) =>
            _userRepository.Login(signinManager, email, password, rememberMe);
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        public void Logoff(IAuthenticationManager AuthenticationManager) {
            _userRepository.Logoff(AuthenticationManager);
        }
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        public Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password) =>
            _userRepository.Register(userManager, user, password);

        public void ResetPassword() {
            throw new NotImplementedException();
        }

        public void ResetPasswordConfirmation() {
            throw new NotImplementedException();
        }

        public void SendCode() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        public Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser) =>
            _userRepository.VerifyCode(signinManager, provider, code, rememberMe, rememberBrowser);

        #endregion

    }

#1


15  

The questions reveals several misconceptions:

这些问题揭示了一些误解:

It appears that you perceive the domain model as some monolithic model where you put every piece of application in. Instead, concentrate on strategic patterns to distinguish Bounded Contexts. Consider the domain as a composition of several loosely interconnected components. Then identify what your core domain is and apply DDD tactical patterns there. Not every ccomponent needs DDD. Some of them even should not use DDD. Especially - generic domains, like Authentication.

您似乎将域模型视为一个单一的模型,您可以将每个应用程序放入其中。相反,请专注于战略模式以区分有界上下文。将域视为几个松散互连组件的组合。然后确定您的核心域名是什么,并在那里应用DDD战术模式。并非每个ccomponent都需要DDD。其中一些人甚至不应该使用DDD。特别是 - 通用域,如身份验证。

DDD is technology agnostic (to some point) so yes, you can use ASP.NET Identity or whatever library you like.

DDD是技术不可知的(在某些方面)所以是的,你可以使用ASP.NET Identity或任何你喜欢的库。

Authentication typically belongs to the Application layer, not Domain layer.

身份验证通常属于Application层,而不属于Domain层。

However - if in your domain there is a concept of a user/client/person, it might be required to use the identity provided by the identity component. But you have to understand that the meaning of User in your bounded context is different than meaning of User in Identity component. These are not the same concept. Although they both refer to the same physical person sitting somewhere and clicking on your app's GUI, they are 2 different models (or projections) of him that serve different purposes. So you shouldn't just reuse the ASP.NET User class in your bounded context.

但是 - 如果在您的域中存在用户/客户端/人的概念,则可能需要使用身份组件提供的身份。但是你必须明白,在有界上下文中User的含义与Identity in Identity中的含义不同。这些概念不一样。虽然他们都指的是坐在某个地方并点击你应用程序GUI的同一个身体的人,但他们是两个不同的模型(或投影),用于不同的目的。因此,您不应该仅仅在有界上下文中重用ASP.NET User类。

Instead - separate contexts should communicate via an anticorruption layer. Basically you have to make some service (interface only) in your bounded context that produces context-specific User objects. The implementation of that interface made in infrastructure layer will be a wrapper of ASP.NET Identity that gets ASP.NET Identity user and produce corresponding bounded context's user.

相反 - 单独的上下文应该通过反腐败层进行通信。基本上,您必须在有界上下文中创建一些服务(仅限接口),以生成特定于上下文的User对象。在基础结构层中实现的该接口的实现将是ASP.NET标识的包装,它获取ASP.NET标识用户并生成相应的有界上下文的用户。

#2


1  

You can use anything you like. But be aware of pollution particular solution is going to make. If your domain model gets messed up with hundreds of lines of asp.net technical kind of plumbing code that makes your domain logic hard to perceive and you are missing point of DDD.

你可以使用任何你喜欢的东西。但要注意污染特定的解决方案。如果您的域模型被数百行asp.net技术类型的管道代码搞砸了,这使得您的域逻辑难以察觉并且您缺少DDD点。

In ideal situation - your domain model should depend only on programming language.

在理想情况下 - 您的域模型应仅依赖于编程语言。

Also - you might find something useful from my long time ago implementation of user session related code.

此外 - 您可能会在我很久以前的用户会话相关代码实现中找到有用的东西。

#3


0  

I am new to DDD. But I achieved integration with Identity and DDD. Although I doubt it truly sticks to the priciples of DDD.

我是DDD的新手。但我实现了与Identity和DDD的集成。虽然我怀疑它真的坚持DDD的原则。

I started with the Entity:

我从实体开始:

public partial class User : IdentityUser {
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager) {
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
        /// <summary>
        /// The Date the User Registered for general information purposes
        /// </summary>
        public DateTime DateRegistered { get; set; }
    }

Then the Interface:

接口:

public interface IUserRepository:IBaseRepository<User> {
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns>Identity Result</returns>
        Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe);
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser);
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code);
        void ForgotPassword();
        void ForgotPasswordConfirmation();
        void ResetPassword();
        void ResetPasswordConfirmation();
        void ExternalLogin();
        void SendCode();
        void ExternalLoginCallback();
        void ExternalLoginConfirmation();
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        void Logoff(IAuthenticationManager AuthenticationManager);
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        User GetUser(string Email);
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        User GetUserById(string ID);
    }

Then the Repository:

然后是存储库:

public class UserRepository : BaseRepository<User>, IUserRepository {
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        public async Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code) =>
            await userManager.ConfirmEmailAsync(userId, code);

        public void ExternalLogin() {
            throw new NotImplementedException();
        }

        public void ExternalLoginCallback() {
            throw new NotImplementedException();
        }

        public void ExternalLoginConfirmation() {
            throw new NotImplementedException();
        }

        public void ForgotPassword() {
            throw new NotImplementedException();
        }

        public void ForgotPasswordConfirmation() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        public User GetUser(string Email) =>
            _context.Users.Where(p => p.Email == Email).FirstOrDefault();
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        public User GetUserById(string ID) => 
            _context.Users.Find(ID);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        public async Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe) =>
            await signinManager.PasswordSignInAsync(email, password, rememberMe, shouldLockout: false);
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        public void Logoff(IAuthenticationManager AuthenticationManager) {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
        }
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns>Identity Result</returns>
        public async Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password) =>
            await userManager.CreateAsync(user, password);

        public void ResetPassword() {
            throw new NotImplementedException();
        }

        public void ResetPasswordConfirmation() {
            throw new NotImplementedException();
        }

        public void SendCode() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        public async Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser) =>
            await signinManager.TwoFactorSignInAsync(provider, code, isPersistent: rememberMe, rememberBrowser: rememberBrowser);
    }

IService:

IService:

public interface IUserService {
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        /// <returns></returns>
        Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password);
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns></returns>
        Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe);
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns></returns>
        Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser);
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns></returns>
        Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code);
        void ForgotPassword();
        void ForgotPasswordConfirmation();
        void ResetPassword();
        void ResetPasswordConfirmation();
        void ExternalLogin();
        void SendCode();
        void ExternalLoginCallback();
        void ExternalLoginConfirmation();
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        void Logoff(IAuthenticationManager AuthenticationManager);
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        User GetUser(string Email);
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        User GetUserById(string ID);
    }

Service:

服务:

public class UserService : ServiceBase, IUserService {

        #region Private Field

        private IUserRepository _userRepository;

        #endregion

        #region Constructor
        /// <summary>
        /// Constructor to initialise User Repository
        /// </summary>
        /// <param name="userRepository"></param>
        public UserService(IUserRepository userRepository) {
            _userRepository = userRepository;
        }

        #endregion

        #region Methods
        /// <summary>
        /// Confirm email of User
        /// </summary>
        /// <param name="userManager">User Manager to handle confirmation</param>
        /// <param name="userId">String user Id of the User</param>
        /// <param name="code">User code sent in Email</param>
        /// <returns>Identity Result</returns>
        public Task<IdentityResult> ConfirmEmail(UserManager<User, string> userManager, string userId, string code) =>
            _userRepository.ConfirmEmail(userManager, userId, code);

        public void ExternalLogin() {
            throw new NotImplementedException();
        }

        public void ExternalLoginCallback() {
            throw new NotImplementedException();
        }

        public void ExternalLoginConfirmation() {
            throw new NotImplementedException();
        }

        public void ForgotPassword() {
            throw new NotImplementedException();
        }

        public void ForgotPasswordConfirmation() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get user based on their Email
        /// </summary>
        /// <param name="Email">Email of user</param>
        /// <returns>User</returns>
        public User GetUser(string Email) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Get User by their GUID
        /// </summary>
        /// <param name="ID">GUID</param>
        /// <returns>User</returns>
        public User GetUserById(string ID) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Login User
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle login</param>
        /// <param name="email">Email of user</param>
        /// <param name="password">Password of user</param>
        /// <param name="rememberMe">Boolean if the user wants to be remembered</param>
        /// <returns>SignIn Status</returns>
        public Task<SignInStatus> Login(SignInManager<User, string> signinManager, string email, string password, bool rememberMe) =>
            _userRepository.Login(signinManager, email, password, rememberMe);
        /// <summary>
        /// Log off user from the Application
        /// </summary>
        /// <param name="AuthenticationManager">Application Manager to handle Sign out</param>
        public void Logoff(IAuthenticationManager AuthenticationManager) {
            _userRepository.Logoff(AuthenticationManager);
        }
        /// <summary>
        /// Register User to Identity Database
        /// </summary>
        /// <param name="userManager">User Manager to Handle Registration</param>
        /// <param name="user">User to add to database</param>
        /// <param name="password">User's password</param>
        public Task<IdentityResult> Register(UserManager<User, string> userManager, User user, string password) =>
            _userRepository.Register(userManager, user, password);

        public void ResetPassword() {
            throw new NotImplementedException();
        }

        public void ResetPasswordConfirmation() {
            throw new NotImplementedException();
        }

        public void SendCode() {
            throw new NotImplementedException();
        }
        /// <summary>
        /// Verify that code sent to User is valid
        /// </summary>
        /// <param name="signinManager">Signin Manager to handle verification</param>
        /// <param name="provider">Provider of the code</param>
        /// <param name="code">The code</param>
        /// <param name="rememberMe">Boolean if user wants to be remembered</param>
        /// <param name="rememberBrowser">Boolean if browser should be remembered</param>
        /// <returns>SignIn Status</returns>
        public Task<SignInStatus> VerifyCode(SignInManager<User, string> signinManager, string provider, string code, bool rememberMe, bool rememberBrowser) =>
            _userRepository.VerifyCode(signinManager, provider, code, rememberMe, rememberBrowser);

        #endregion

    }