I am trying to override the SendPasswordResetCodeAsync and ResetPasswordAsync methods of the AccountController but I am having issues. They both are virtual methods.
I followed the Overriding Services guide and created the controller as follows:
namespace MyProject.Controllers
{
[Dependency(ReplaceServices = true)]
[Area("account")]
[RemoteService(IsEnabled = false, IsMetadataEnabled = false, Name = AccountRemoteServiceConsts.RemoteServiceName)]
[Route("api/account")]
public class AccountController : Volo.Abp.Account.AccountController, IAccountAppService
{
public AccountController(IAccountAppService accountAppService)
: base(accountAppService) { }
[HttpPost]
[Route("send-password-reset-code")]
public override Task SendPasswordResetCodeAsync(SendPasswordResetCodeDto input)
{
// my logic...
return AccountAppService.SendPasswordResetCodeAsync(input);
}
[HttpPost]
[Route("reset-password")]
public override Task ResetPasswordAsync(ResetPasswordDto input)
{
// my logic...
return AccountAppService.ResetPasswordAsync(input);
}
}
}
But I get the following exception when using the endpoints:
Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints. Matches:
Volo.Abp.Account.AccountController.SendPasswordResetCodeAsync (Volo.Abp.Account.HttpApi)
MyProject.Controllers.AccountController.SendPasswordResetCodeAsync (MyProject.HttpApi.Host)
So I scour the existing abp issues and come across this from a long time ago: https://github.com/abpframework/abp/issues/2428#issuecomment-567778737 so add a custom routing convention i.e.
context.Services.Configure<MvcOptions>(options =>
{
options.Conventions.Add(new MyRoutingConvention());
});
But I am not happy with this approach because it removes all the original /account routes so then I have to use: [RemoteService(true)], when I only want to override a few methods of the existing controller.
Is there a better approach now in ABP 3.1.0 and could you add a section to the 'Overriding Services' guide to explain how to override API Controllers specifically?
@realLiangshiwei May it be updated in the the 'Overriding Services' guide ?
I will work on this in the next milestone.
See my comment:
https://support.abp.io/QA/Questions/438#answer-0ee7923f-f88b-b6cc-6f63-39f7f9779443
With the v3.3, you will be able to do it like;
````csharp
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Account;
using Volo.Abp.DependencyInjection;
namespace MyCompanyName.MyProjectName.Controllers
{
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(AccountController))]
public class MyAccountController : AccountController
{
public MyAccountController(IAccountAppService accountAppService)
: base(accountAppService)
{
}
public override async Task SendPasswordResetCodeAsync(SendPasswordResetCodeDto input)
{
Logger.LogInformation("Your custom logic...");
await base.SendPasswordResetCodeAsync(input);
}
}
}
````
No need to repeat all the route and other attributes. It is that simple and documented: https://github.com/abpframework/abp/blob/dev/docs/en/Customizing-Application-Modules-Overriding-Services.md#example-overriding-a-controller
666
Most helpful comment
With the v3.3, you will be able to do it like;
````csharp
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Account;
using Volo.Abp.DependencyInjection;
namespace MyCompanyName.MyProjectName.Controllers
{
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(AccountController))]
public class MyAccountController : AccountController
{
public MyAccountController(IAccountAppService accountAppService)
: base(accountAppService)
{
}
````
No need to repeat all the route and other attributes. It is that simple and documented: https://github.com/abpframework/abp/blob/dev/docs/en/Customizing-Application-Modules-Overriding-Services.md#example-overriding-a-controller