相关模块
  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. (四十二)golang--管道

    假设我们现在有这么一个需求: 计算1-200之间各个数的阶乘,并将每个结果保存在mao中,最终显示出来,要求使用goroutime. 分析: (1)使用goroutime完成,效率高,但是会出现并发/ ...

  2. Git及Github

    目录 Git及Github的使用 Git的基本介绍 Git命令行操作 1.设置签名 2.创建本地库 3.仓库初始化 4.状态查看 5.添加文件 6.提交文件 7.历史记录 8.前进后退 9.删除文件 ...

  3. Pycharm报错连接linux服务器报错:Could not verify `ssh-rsa` host key with fingerprint

    忘记了截图,后来解决了就懒得再去重新制造错误了.大概记得是通过ssh连接linux时,报错 Could not verify `ssh-rsa` host key with fingerprint . ...

  4. “达观杯”文本分类--baseline

    结合tfidf权重,对“达观杯”提供的文本,进行文本分类,作为baseline,后续改进均基于此. 1.比赛地址及数据来源 "达观杯"文本智能挑战赛 2.代码及解析 # -*- c ...

  5. .Net Core 3.0 使用 Serilog 把日志记录到 SqlServer

    Serilog简介 Serilog是.net中的诊断日志库,可以在所有的.net平台上面运行.Serilog支持结构化日志记录,对复杂.分布式.异步应用程序的支持非常出色.Serilog可以通过插件的 ...

  6. 使用python2连接操作db2

    在python2.6下连接db2,步骤: 1.安装python2.6. (注:目前db2的驱动还不支持2.7) 2.安装setuptools,下载地址http://pypi.python.org/py ...

  7. Sql like模糊查询 区分大小写

    Sql模糊查询,Like默认是不区分大小写的 使用Like时,怎么支持大小写呢? upper.lower,只能模糊所有的内容,不能区分内容中的大小写. sqlite数据库对text字段默认是大小写敏感 ...

  8. CSRF的原理与防御 | 你想不想来一次CSRF攻击?

    CSRF是Cross Site Request Forgery的缩写,中文翻译过来是跨站请求伪造.这个漏洞往往能给用户带来巨大的损失,CSRF在等保安全检测中,也是一个非常重要的检测项.但是在我们的网 ...

  9. Anticancer Effect of Deuterium Depleted Water - Redox Disbalance Leads to Oxidative Stress(低氘水的抗癌作用-氧化还原失衡导致了氧化应激)-解读人:范徉

    期刊名:Molecular & Cellular Proteomics 发表时间:(2019年12月) IF:4.828 单位:瑞典卡罗林斯卡学院 物种:人 技术:标记定量蛋白质组学,氧化还原 ...

  10. JQuery之选择集过滤

    JQuery选择集过滤应用如下: 代码实现: <script src="JS/jquery-3.4.1.js"></script> <script&g ...