相关模块
  1. AbpAspNetCoreModule
  2. AbpAspNetCoreMvcModule
  3. AbpAspNetCoreMvcContractsModule

abp通过这三个模块加载并配置了 asp.net core。,最主要的就是AbpAspNetCoreMvcModule模块类,abp如何基于aspnet core构建自己的控制器和AppServices,就是在这个类中。

  • AbpAspNetCoreMvcModule

    将AbpAspNetCoreMvcConventionalRegister类添加到ConventionalRegistrarList列表中,该类主要是用来注入依赖及获取服务生命周期的。

      public override void PreConfigureServices(ServiceConfigurationContext context)
    {
    context.Services.AddConventionalRegistrar(new AbpAspNetCoreMvcConventionalRegistrar());
    }

    接下来就是重点,在ConfigureServices方法中配置视图和控制器,当然是基于 asp.net core mvc。首先配置Razor:

      context.Services.Insert(0,
    ServiceDescriptor.Singleton<IConfigureOptions<RazorViewEngineOptions>>(
    new ConfigureOptions<RazorViewEngineOptions>(options =>
    {
    options.FileProviders.Add(
    new RazorViewEngineVirtualFileProvider(
    context.Services.GetSingletonInstance<IObjectAccessor<IServiceProvider>>()
    )
    );
    }
    )
    )
    );

    配置Api描述符:

      Configure<ApiDescriptionModelOptions>(options =>
    {
    options.IgnoredInterfaces.AddIfNotContains(typeof(IAsyncActionFilter));
    options.IgnoredInterfaces.AddIfNotContains(typeof(IFilterMetadata));
    options.IgnoredInterfaces.AddIfNotContains(typeof(IActionFilter));
    });

    可以看到 aspnetcore mvc中的过滤器接口,我们将其添加到了Api描述模型选项类中。下面就是注入MVC:

      var mvcCoreBuilder = context.Services.AddMvcCore();
    var mvcBuilder = context.Services.AddMvc()
    .AddDataAnnotationsLocalization(options =>
    {
    options.DataAnnotationLocalizerProvider = (type, factory) =>
    {
    var resourceType = abpMvcDataAnnotationsLocalizationOptions.AssemblyResources.GetOrDefault(type.Assembly);
    return factory.Create(resourceType ?? type);
    };
    })
    .AddViewLocalization();

    使用DI创建控制器,使用的是aspnet core默认的控制器激活器ServiceBasedControllerActivator类:

      //Use DI to create controllers
    context.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

    abp提供了一个基于约定的控制器特性提供器类,这个类是基于 aspnetcore mvc的ControllerFeatureProvider构建自己的控制器,并检索判断控制器。

      //Add feature providers
    var partManager = context.Services.GetSingletonInstance<ApplicationPartManager>();
    var application = context.Services.GetSingletonInstance<IAbpApplication>(); partManager.FeatureProviders.Add(new AbpConventionalControllerFeatureProvider(application));

    该类源码:

      public class AbpConventionalControllerFeatureProvider : ControllerFeatureProvider
    {
    private readonly IAbpApplication _application; public AbpConventionalControllerFeatureProvider(IAbpApplication application)
    {
    _application = application;
    } protected override bool IsController(TypeInfo typeInfo)
    {
    //TODO: Move this to a lazy loaded field for efficiency.
    if (_application.ServiceProvider == null)
    {
    return false;
    } var configuration = _application.ServiceProvider
    .GetRequiredService<IOptions<AbpAspNetCoreMvcOptions>>().Value
    .ConventionalControllers
    .ConventionalControllerSettings
    .GetSettingOrNull(typeInfo.AsType()); return configuration != null;
    }
    }

    由上,abp会基于aspnetcore mvc配置abp的mvc模块,特别是Controller的创建。从代码里面可以看出获取到AbpAspNetCoreMvcOptions的服务再去检索规约的控制器。由此返回是否是控制器。AbpAspNetCoreMvcOptions类是Abp对aspnet core mvc的一个封装,源码如下:

      public class AbpAspNetCoreMvcOptions
    {
    public ConventionalControllerOptions ConventionalControllers { get; } public AbpAspNetCoreMvcOptions()
    {
    ConventionalControllers = new ConventionalControllerOptions();
    }
    } //规约控制器集合
    public class ConventionalControllerOptions
    {
    public ConventionalControllerSettingList ConventionalControllerSettings { get; } public List<Type> FormBodyBindingIgnoredTypes { get; } public ConventionalControllerOptions()
    {
    ConventionalControllerSettings = new ConventionalControllerSettingList(); FormBodyBindingIgnoredTypes = new List<Type>
    {
    typeof(IFormFile)
    };
    } public ConventionalControllerOptions Create(Assembly assembly, [CanBeNull] Action<ConventionalControllerSetting> optionsAction = null)
    {
    var setting = new ConventionalControllerSetting(assembly, ModuleApiDescriptionModel.DefaultRootPath); // DefaultRootPath = app,abp路由就是以这个app开头的。
    optionsAction?.Invoke(setting);
    setting.Initialize();
    ConventionalControllerSettings.Add(setting);
    return this;
    }
    }

    AbpAspNetCoreMvcOptions实际上是通过ConventionalControllerOptions来完成规约的配置,来实现自定义的路由以及动态API。

  • AspNetCoreDescriptionModelProvider

    abp是如何aspnet core创建自己的API的呢?有这么一个类AspNetCoreDescriptionModelProvider,这个类就是提供了aspnet core的描述模型,源码如下:

      public class AspNetCoreApiDescriptionModelProvider : IApiDescriptionModelProvider, ITransientDependency
    {
    public ILogger<AspNetCoreApiDescriptionModelProvider> Logger { get; set; } private readonly IApiDescriptionGroupCollectionProvider _descriptionProvider;
    private readonly AbpAspNetCoreMvcOptions _options;
    private readonly ApiDescriptionModelOptions _modelOptions; public AspNetCoreApiDescriptionModelProvider(
    IApiDescriptionGroupCollectionProvider descriptionProvider,
    IOptions<AbpAspNetCoreMvcOptions> options,
    IOptions<ApiDescriptionModelOptions> modelOptions)
    {
    _descriptionProvider = descriptionProvider;
    _options = options.Value;
    _modelOptions = modelOptions.Value; Logger = NullLogger<AspNetCoreApiDescriptionModelProvider>.Instance;
    } public ApplicationApiDescriptionModel CreateApiModel()
    {
    //TODO: Can cache the model? var model = ApplicationApiDescriptionModel.Create(); foreach (var descriptionGroupItem in _descriptionProvider.ApiDescriptionGroups.Items)
    {
    foreach (var apiDescription in descriptionGroupItem.Items)
    {
    if (!apiDescription.ActionDescriptor.IsControllerAction())
    {
    continue;
    } AddApiDescriptionToModel(apiDescription, model);
    }
    } return model;
    } private void AddApiDescriptionToModel(ApiDescription apiDescription, ApplicationApiDescriptionModel model)
    {
    var controllerType = apiDescription.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType();
    var setting = FindSetting(controllerType); var moduleModel = model.GetOrAddModule(GetRootPath(controllerType, setting)); var controllerModel = moduleModel.GetOrAddController(controllerType.FullName, CalculateControllerName(controllerType, setting), controllerType, _modelOptions.IgnoredInterfaces); var method = apiDescription.ActionDescriptor.GetMethodInfo(); var uniqueMethodName = GetUniqueActionName(method);
    if (controllerModel.Actions.ContainsKey(uniqueMethodName))
    {
    Logger.LogWarning($"Controller '{controllerModel.ControllerName}' contains more than one action with name '{uniqueMethodName}' for module '{moduleModel.RootPath}'. Ignored: " + method);
    return;
    } Logger.LogDebug($"ActionApiDescriptionModel.Create: {controllerModel.ControllerName}.{uniqueMethodName}");
    var actionModel = controllerModel.AddAction(uniqueMethodName, ActionApiDescriptionModel.Create(
    uniqueMethodName,
    method,
    apiDescription.RelativePath,
    apiDescription.HttpMethod,
    GetSupportedVersions(controllerType, method, setting)
    )); AddParameterDescriptionsToModel(actionModel, method, apiDescription);
    } private static string CalculateControllerName(Type controllerType, ConventionalControllerSetting setting)
    {
    var controllerName = controllerType.Name.RemovePostFix("Controller").RemovePostFix(ApplicationService.CommonPostfixes); if (setting?.UrlControllerNameNormalizer != null)
    {
    controllerName = setting.UrlControllerNameNormalizer(new UrlControllerNameNormalizerContext(setting.RootPath, controllerName));
    } return controllerName;
    }
    }

    这个类为我们提供了从Action到Controller的描述,构建了abp自己的api。它的调用有两个地方,一个是AbpApiDefinitionController,一个是ProxyScriptManager,前者是定义Abp的api控制器定义的地方,后者则是生成代理脚本的地方,abp的示例项目BookStore中会调用接口Abp/ServiceProxyScript生成一个js文件,这个js文件里面就是api的url地址,前端通过访问这个api地址来访问appservice等后端方法。源码如下:

      [Area("Abp")]
    [Route("Abp/ServiceProxyScript")]
    [DisableAuditing]
    public class AbpServiceProxyScriptController : AbpController
    {
    private readonly IProxyScriptManager _proxyScriptManager; public AbpServiceProxyScriptController(IProxyScriptManager proxyScriptManager)
    {
    _proxyScriptManager = proxyScriptManager;
    } [HttpGet]
    [Produces("text/javascript", "text/plain")]
    public string GetAll(ServiceProxyGenerationModel model)
    {
    model.Normalize();
    return _proxyScriptManager.GetScript(model.CreateOptions());
    }
    }
  • AbpHttpModule模块

    Abp创建jquery代理脚本生成器,主要用来生产api提供给前端访问

      public override void ConfigureServices(ServiceConfigurationContext context)
    {
    Configure<AbpApiProxyScriptingOptions>(options =>
    {
    options.Generators[JQueryProxyScriptGenerator.Name] = typeof(JQueryProxyScriptGenerator);
    });
    }

4. abp中的asp.net core模块剖析的更多相关文章

  1. 中小研发团队架构实践之生产环境诊断工具WinDbg 三分钟学会.NET微服务之Polly 使用.Net Core+IView+Vue集成上传图片功能 Fiddler原理~知多少? ABP框架(asp.net core 2.X+Vue)模板项目学习之路(一) C#程序中设置全局代理(Global Proxy) WCF 4.0 使用说明 如何在IIS上发布,并能正常访问

    中小研发团队架构实践之生产环境诊断工具WinDbg 生产环境偶尔会出现一些异常问题,WinDbg或GDB是解决此类问题的利器.调试工具WinDbg如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具 ...

  2. ASP.NET Core模块概述

    原文地址:ASP.NET Core Module overview By Tom Dykstra, Rick Strahl, and Chris Ross ASP.NET Core模块(ANCM)让你 ...

  3. 丙申年把真假美猴王囚禁在容器中跑 ASP.NET Core 1.0

    var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...

  4. 在Visual Studio 2017中使用Asp.Net Core构建Angular4应用程序

    前言 Visual Studio 2017已经发布了很久了.做为集成了Asp.Net Core 1.1的地表最强IDE工具,越来越受.NET系的开发人员追捧. 随着Google Angular4的发布 ...

  5. [Asp.Net Core] 1. IIS中的 Asp.Net Core 和 dotnet watch

    在基于传统的.NET Framework的Asp.Net Mvc的时候,本地开发环境中可以在IIS中建立一个站点,可以直接把站点的目录指向asp.net mvc的项目的根目录.然后build一下就可以 ...

  6. 【Asp.Net Core】在Visual Studio 2017中使用Asp.Net Core构建Angular4应用程序

    前言 Visual Studio 2017已经发布了很久了.做为集成了Asp.Net Core 1.1的地表最强IDE工具,越来越受.NET系的开发人员追捧. 随着Google Angular4的发布 ...

  7. ASP.NET Core 2.2 基础知识(十一) ASP.NET Core 模块

    ASP.NET Core 应用与进程内的 HTTP 服务器实现一起运行.该服务器实现侦听 HTTP 请求,并在一系列请求功能被写到 HttpContext 时,将这些请求展现到应用中. ASP.NET ...

  8. IIS中的 Asp.Net Core 和 dotnet watch

    在基于传统的.NET Framework的Asp.Net Mvc的时候,本地开发环境中可以在IIS中建立一个站点,可以直接把站点的目录指向asp.net mvc的项目的根目录.然后build一下就可以 ...

  9. .NET 7 预览版2 中的 ASP.NET Core 更新

    .NET 7 预览版2 现已推出,其中包括对ASP.NET Core 的许多重大改进. 以下是此预览版中新增内容的摘要: 推断来自服务的API 控制器操作参数 SignalR 集线器方法的依赖注入 为 ...

随机推荐

  1. 【python测试开发栈】—python内存管理机制(二)—垃圾回收

    在上一篇文章中(python 内存管理机制-引用计数)中,我们介绍了python内存管理机制中的引用计数,python正是通过它来有效的管理内存.今天来介绍python的垃圾回收,其主要策略是引用计数 ...

  2. 甲小蛙战记:PHP2Java 排雷指南

    (马蜂窝技术原创内容,申请转载请在公众后后台留言,ID:mfwtech ) 大家好,我是来自马蜂窝电商旅游平台的甲小蛙,从前是一名 PHP 工程师,现在可能是一名 PHJ 工程师,以后...... 前 ...

  3. WebGPU学习(一): 开篇

    介绍 大家好,本系列从0开始学习WebGPU API,并给出相关的demo. WebGPU介绍 WebGPU相当于DX12/Vulkan,能让程序员更灵活地操作GPU,从而大幅提升性能. 为什么要学习 ...

  4. Dictionary的遍历

    Dictionary<string, int> list = new Dictionary<string, int>(); list.Add("d", 1) ...

  5. EF分页查询

    /// <summary> /// 分页查询 + 条件查询 + 排序 /// </summary> /// <typeparam name="Tkey" ...

  6. springboot打印SQL及多环境配置

    1-在控制台打印sql语句 在springBoot+Mybatis中,要想在控制台日志显示SQL的执行情况,简单设置即可:在properties新增: logging.level.com.anson. ...

  7. 八分音符(频率)卷积算子 Octave Convolution

    为什么读此系列文章? 优化数学和计算理论帮助机器学习完成问题分类: 1)按照领域划分,比如计算机视觉,自然语言处理,统计分析预测形: 2)按照算法复杂划分,比如是否是NP-Hard问题,是否需要精确解 ...

  8. luogu P1509 找啊找啊找GF

    题目背景 sqybi现在看中了n个MM,我们不妨把她们编号1到n.请MM吃饭是要花钱的,我们假设请i号MM吃饭要花rmb[i]块大洋.而希望骗MM当自己GF是要费人品的,我们假设请第i号MM吃饭试图让 ...

  9. iOS 日志获取和实时浏览器显示日志

    https://juejin.im/entry/576252855bbb500063e51c7d iOS 日志获取和实时浏览器显示日志

  10. ios 10 更新 新体验

    1.使用手机登录开发者网站https://developer.apple.com/download/ 2.下载描述文件 3.安装描述文件,按照提示步骤操作 4.更新ios系统 下面的方法是连接电脑直接 ...