@ -191,4 +191,167 @@ public class MyDistributedIdentityUserCreatedEventHandler :
}
````
* This handler is executed only when a new user has been created.
* This handler is executed only when a new user has been created.
> The only pre-defined specialized event class is the `UserEto`. For example, you can subscribe to the `EntityCreatedEto<UserEto>` to get notified when a user has created. This event also works for the Identity module.
### Overriding Services
You may need to **change behavior (business logic)** of a depended module for your application. You can use the power of the [dependency injection system](Dependency-Injection.md) to replace a service, controller or even a page model of the depended module by your own implementation.
Replacing a service is possible for any type of class registered to the dependency injection, including services of the ABP Framework.
You have different options can be used based on your requirement those will be explained in the next sections.
#### Replacing an Interface
If given service defines an interface, like the `IdentityUserAppService` class implements the `IIdentityAppService`, you can re-implement the same interface and replace the current implementation by your class. Example:
````csharp
public class MyIdentityUserAppService : IIdentityUserAppService, ITransientDependency
{
//...
}
````
`MyIdentityUserAppService` replaces the `IIdentityUserAppService` by naming convention (since both ends with `IdentityUserAppService`). If your class name doesn't match, you need to manually expose the service interface:
````csharp
[ExposeServices(typeof(IIdentityUserAppService))]
public class TestAppService : IIdentityUserAppService, ITransientDependency
{
//...
}
````
The dependency injection system allows to register multiple services for the same interface. The last registered one is used when the interface is injected. It is a good practice to explicitly replace the service.
Example:
````csharp
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IIdentityUserAppService))]
public class TestAppService : IIdentityUserAppService, ITransientDependency
{
//...
}
````
In this way, there will be a single implementation of the `IIdentityUserAppService` interface, while it doesn't change the result for this case. Replacing a service is also possible by code:
You can write this inside the `ConfigureServices` method of your [module](Module-Development-Basics.md).
#### Overriding a Service Class
In most cases, you will want to change one or a few methods of the current implementation for a service. Re-implementing the complete interface would not be efficient in this case. As a better approach, inherit from the original class and override the desired method.
##### Example: Overriding an Application Service
````csharp
[Dependency(ReplaceServices = true)]
public class MyIdentityUserAppService : IdentityUserAppService
{
//...
public MyIdentityUserAppService(
IdentityUserManager userManager,
IIdentityUserRepository userRepository,
IGuidGenerator guidGenerator
) : base(
userManager,
userRepository,
guidGenerator)
{
}
public override async Task<IdentityUserDto> CreateAsync(IdentityUserCreateDto input)
{
if (input.PhoneNumber.IsNullOrWhiteSpace())
{
throw new AbpValidationException(
"Phone number is required for new users!",
new List<ValidationResult>
{
new ValidationResult(
"Phone number can not be empty!",
new []{"PhoneNumber"}
)
}
); }
return await base.CreateAsync(input);
}
}
````
This class **overrides** the `CreateAsync` method of the `IdentityUserAppService` to check the phone number. Then calls the base method to continue to the **underlying business logic**. In this way, you can perform additional business logic **before** and **after** the base logic.
You could completely **re-write** the entire business logic for a user creation without calling the base method.
##### Example: Overriding a Domain Service
````csharp
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IdentityUserManager))]
public class MyIdentityUserManager : IdentityUserManager
public override async Task<IdentityResult> CreateAsync(IdentityUser user)
{
if (user.PhoneNumber.IsNullOrWhiteSpace())
{
throw new AbpValidationException(
"Phone number is required for new users!",
new List<ValidationResult>
{
new ValidationResult(
"Phone number can not be empty!",
new []{"PhoneNumber"}
)
}
);
}
return await base.CreateAsync(user);
}
}
````
This example class inherits from the `IdentityUserManager` and overrides the `CreateAsync` method to perform the same phone number check implemented above. The result is same, but this time we've implemented it inside the domain service assuming that this is a **core domain logic** for our system.
> `[ExposeServices(typeof(IdentityUserManager))]` attribute is **required** here since `IdentityUserManager` does not define an interface (like `IIdentityUserManager`) and dependency injection system doesn't expose services for inherited classes (like it does for the implemented interfaces) by convention.
Check the [localization system](Localization.md) to learn how to localize the error messages.