扩展现有的ABP控制器 [英] Extending existing ABP controllers

查看:143
本文介绍了扩展现有的ABP控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ABP框架的3.3.2版本.如何向现有控制器添加新方法?我想扩展 IdentityUserController .在文档之后,我正在创建自己的实现,如下所示:

I am using version 3.3.2 of the ABP Framework. How can I add new methods to an existing controller? I want to extend the IdentityUserController. Following the docs I am creating my own implementation as following:

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IdentityUserController))]
    public class MyIdentityUserController : IdentityUserController
    {
        public MyIdentityUserController(IIdentityUserAppService userAppService) : base(userAppService)
        {
        }

        public override Task<PagedResultDto<IdentityUserDto>> GetListAsync(GetIdentityUsersInput input)
        {
            return base.GetListAsync(input);
        }

        [HttpGet]
        [Route("my-method")]
        public Task<string> MyMethod()
        {
            return Task.FromResult("Works");
        }
    }

覆盖实际上可以工作,但是我的自定义方法在Swagger中不可见,当我尝试使用Postman访问它时,也无法访问它.有什么想法可以扩展现有的控制器吗?我不想创建一个全新的控制器,因为我将重写和新方法结合在一起.我想把所有东西都放在一起.

The overrides actually work but my custom method is not visible in Swagger and when I try to access it with Postman it is not accessible either. Any ideas how I can extend existing controllers? I don't want to create a whole new controller since I have a combination with overrides and new methods. I would like to keep everything together.

推荐答案

首先,设置 IncludeSelf = true —我们将使用它来确定是否用扩展控制器和ASP替换现有控制器..NET Core将按类解析您的控制器.
(可选)从 IdentityUserController 添加 [ControllerName("User"))] ,因为它不是继承的:

First, set IncludeSelf = true — we will use this to determine whether to replace the existing controller with the extended controller, and ASP.NET Core will resolve your controller by class.
Optionally, add [ControllerName("User")] from IdentityUserController since it is not inherited:

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IdentityUserController), IncludeSelf = true)]
[ControllerName("User")]
public class MyIdentityUserController : IdentityUserController

选项1

子类 AbpServiceConvention 并覆盖 RemoveDuplicateControllers 以删除现有的控制器,而不是扩展的控制器:

Option 1

Subclass AbpServiceConvention and override RemoveDuplicateControllers to remove the existing controller(s) instead of your extended controller:

var exposeServicesAttr = ReflectionHelper.GetSingleAttributeOrDefault<ExposeServicesAttribute>(controllerModel.ControllerType);
if (exposeServicesAttr.IncludeSelf)
{
    var existingControllerModels = application.Controllers
        .Where(cm => exposeServicesAttr.ServiceTypes.Contains(cm.ControllerType))
        .ToArray();
    derivedControllerModels.AddRange(existingControllerModels);
    Logger.LogInformation($"Removing the controller{(existingControllerModels.Length > 1 ? "s" : "")} {exposeServicesAttr.ServiceTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")} from the application model since {(existingControllerModels.Length > 1 ? "they are" : "it is")} replaced by the controller: {controllerModel.ControllerType.AssemblyQualifiedName}");
    continue;
}

子类的完整代码:

public class MyAbpServiceConvention : AbpServiceConvention
{
    public MyAbpServiceConvention(
        IOptions<AbpAspNetCoreMvcOptions> options,
        IConventionalRouteBuilder conventionalRouteBuilder)
        : base(options, conventionalRouteBuilder)
    {
    }

    protected override void RemoveDuplicateControllers(ApplicationModel application)
    {
        var derivedControllerModels = new List<ControllerModel>();

        foreach (var controllerModel in application.Controllers)
        {
            if (!controllerModel.ControllerType.IsDefined(typeof(ExposeServicesAttribute), false))
            {
                continue;
            }

            if (Options.IgnoredControllersOnModelExclusion.Contains(controllerModel.ControllerType))
            {
                continue;
            }

            var exposeServicesAttr = ReflectionHelper.GetSingleAttributeOrDefault<ExposeServicesAttribute>(controllerModel.ControllerType);
            if (exposeServicesAttr.IncludeSelf)
            {
                var existingControllerModels = application.Controllers
                    .Where(cm => exposeServicesAttr.ServiceTypes.Contains(cm.ControllerType))
                    .ToArray();
                derivedControllerModels.AddRange(existingControllerModels);
                Logger.LogInformation($"Removing the controller{(existingControllerModels.Length > 1 ? "s" : "")} {exposeServicesAttr.ServiceTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")} from the application model since {(existingControllerModels.Length > 1 ? "they are" : "it is")} replaced by the controller: {controllerModel.ControllerType.AssemblyQualifiedName}");
                continue;
            }

            var baseControllerTypes = controllerModel.ControllerType
                .GetBaseClasses(typeof(Controller), includeObject: false)
                .Where(t => !t.IsAbstract)
                .ToArray();

            if (baseControllerTypes.Length > 0)
            {
                derivedControllerModels.Add(controllerModel);
                Logger.LogInformation($"Removing the controller {controllerModel.ControllerType.AssemblyQualifiedName} from the application model since it replaces the controller(s): {baseControllerTypes.Select(c => c.AssemblyQualifiedName).JoinAsString(", ")}");
            }
        }

        application.Controllers.RemoveAll(derivedControllerModels);
    }
}

选项2

实施 IApplicationModelConvention ,以将扩展控制器添加到 IgnoredControllersOnModelExclusion 并删除现有控制器:

Option 2

Implement IApplicationModelConvention to add your extended controller to IgnoredControllersOnModelExclusion and remove the existing controller:

public class ExtendedControllerApplicationModelConvention : IApplicationModelConvention
{
    private readonly Lazy<IOptions<AbpAspNetCoreMvcOptions>> _lazyOptions;

    public ExtendedControllerApplicationModelConvention (IServiceCollection services)
    {
        _lazyOptions = services.GetRequiredServiceLazy<IOptions<AbpAspNetCoreMvcOptions>>();
    }

    public void Apply(ApplicationModel application)
    {
        var controllerModelsToRemove = new List<ControllerModel>();
        var ignoredControllersOnModelExclusion = _lazyOptions.Value.Value.IgnoredControllersOnModelExclusion;

        foreach (var controllerModel in application.Controllers)
        {
            var exposeServicesAttr = ReflectionHelper.GetSingleAttributeOrDefault<ExposeServicesAttribute>(controllerModel.ControllerType);
            if (exposeServicesAttr != null && exposeServicesAttr.IncludeSelf)
            {
                ignoredControllersOnModelExclusion.AddIfNotContains(controllerModel.ControllerType);

                var existingControllerModels = application.Controllers
                    .Where(cm => exposeServicesAttr.ServiceTypes.Contains(cm.ControllerType));
                controllerModelsToRemove.AddIfNotContains(existingControllerModels);
            }
        }

        application.Controllers.RemoveAll(controllerModelsToRemove);
    }
}

在您的模块中,在 AbpServiceConventionWrapper 之前插入 ExtendedServiceApplicationModelConvention :

In your module, insert ExtendedServiceApplicationModelConvention before AbpServiceConventionWrapper:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    // ...
    Configure<MvcOptions>(options =>
    {
        var abpServiceConvention = options.Conventions.OfType<AbpServiceConventionWrapper>().First();
        options.Conventions.InsertBefore(abpServiceConvention, new ExtendedControllerApplicationModelConvention (context.Services));
    });
}

这篇关于扩展现有的ABP控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆