相关模块
  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. ubuntu windows mutual remote control

    Win10 remote control Ubuntu18 Part1.ubuntu settings 1.安装所需组件 sudo apt-get update //若没有desktop sharin ...

  2. java基础总结(1)--深入理解基本数据类型

    深入理解java数据类型 java是一种强类型语言,这就意味着必须为每一个声明变量声明一种类型.在java中,一共有8种数据类型,其中4种整型,2种浮点类型,1种字符类型和一种表示真值的boolean ...

  3. [ASP.NET Core 3框架揭秘] 配置[1]:读取配置数据[上篇]

    提到"配置"二字,我想绝大部分.NET开发人员脑海中会立即浮现出两个特殊文件的身影,那就是我们再熟悉不过的app.config和web.config,多年以来我们已经习惯了将结构化 ...

  4. Mybatis工作流程源码分析

    1.简介 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单 ...

  5. php之自动加载(懒加载)

    有A类和B类,如果在A类实例化B类,最简单直接的方法就是在B中使用include require_once A的文件,但是这种方法显然是不友好的,在框架中叶不是这么做的,在框架中使用的是自动加载的机制 ...

  6. 【数据结构】之链表(C语言描述)

    链表是线性表的一种,是一种物理存储单元上非连续的存储结构,链表中的数据元素之间是通过指针链接实现的. 链表由一系列节点组成,节点可以在运行时动态的生成. 链表中国的每个节点分为两部分:一部分是存储数据 ...

  7. Erlang/Elixir精选-第2期(20191209)

    Spot The Discrepancies with Dialyzer for Erlang. 如何在大型Erlang项目中从零开始一步步践行Dialyzer. Which companies ar ...

  8. 带着canvas去流浪系列之一:绘制柱状图

    [摘要] 学习使用canvasAPI来实现数据可视化. 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI绘制柱 ...

  9. NB-IoT将成为未来5G物联网主流技术

    日前,我国完成了IMT-2020(5G)候选技术方案的完整提交.据悉,在提交的方案中,NB-IoT技术被正式纳入5G候选技术集合,预计2020年6月ITU将正式宣布5G技术方案的诞生.而NB-IoT也 ...

  10. [TimLinux] JavaScript 模态框可拖动功能实现——节流版

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...