使用应用程序部件共享控制器、视图、Razor Pages 等

作者:Rick Anderson

查看或下载示例代码如何下载

应用程序部件是对应用资源的抽象化。 借助应用程序部件,ASP.NET Core 可以发现控制器、视图组件、标记帮助程序、Razor Pages、Razor 编译源等。 AssemblyPart 是应用程序部件。 AssemblyPart 用于封装程序集引用,并公开类型和编译引用。

功能提供程序使用应用程序部件填充 ASP.NET Core 应用的功能。 应用程序部件的主要用例是将应用配置为从程序集中发现(或避免加载)ASP.NET Core 功能。 例如,可能需要在多个应用之间共享通用功能。 借助应用程序部件,你可以与多个应用共享包含控制器、视图、Razor Pages、Razor 编译源、标记帮助程序等的程序集 (DLL)。 相对于在多个项目中复制代码,首选共享程序集。

ASP.NET Core 应用从 ApplicationPart 加载功能。 AssemblyPart 类表示受程序集支持的应用程序部件。

加载 ASP.NET Core 功能

使用 Microsoft.AspNetCore.Mvc.ApplicationPartsAssemblyPart 类发现并加载 ASP.NET Core 功能(控制器、视图组件等)。 ApplicationPartManager 跟踪可用的应用程序部件和功能提供程序。 在 Startup.ConfigureServices 中配置 ApplicationPartManager

// Requires using System.Reflection;
public void ConfigureServices(IServiceCollection services)
{
    var assembly = typeof(MySharedController).Assembly;
    services.AddControllersWithViews()
        .AddApplicationPart(assembly)
        .AddRazorRuntimeCompilation();

    services.Configure<MvcRazorRuntimeCompilationOptions>(options => 
    { options.FileProviders.Add(new EmbeddedFileProvider(assembly)); });
}

以下代码提供使用 AssemblyPart 配置 ApplicationPartManager 的可选方法:

// Requires using System.Reflection;
// Requires using Microsoft.AspNetCore.Mvc.ApplicationParts;
public void ConfigureServices(IServiceCollection services)
{
    var assembly = typeof(MySharedController).Assembly;
    // This creates an AssemblyPart, but does not create any related parts for items such as views.
    var part = new AssemblyPart(assembly);
    services.AddControllersWithViews()
        .ConfigureApplicationPartManager(apm => apm.ApplicationParts.Add(part));
}

前面的两个代码示例从程序集加载 SharedControllerSharedController 未在该应用的项目中。 请参阅 WebAppParts 解决方案示例下载。

包含视图

使用 Razor Razor 类库将视图包含在程序集中。

阻止加载资源

可以使用应用程序部件来避免加载特定程序集或位置中的资源。 添加或删除 Microsoft.AspNetCore.Mvc.ApplicationParts 集合的成员,将隐藏或提供资源。 ApplicationParts 集合中条目的顺序并不重要。 在使用 ApplicationPartManager 配置容器中的服务之前,对该类进行配置。 例如,在调用 AddControllersAsServices 之前配置 ApplicationPartManager。 在 ApplicationParts 集合上调用 Remove,将删除资源。

ApplicationPartManager 包括以下内容的部件:

  • 应用的程序集和依赖程序集。
  • Microsoft.AspNetCore.Mvc.ApplicationParts.CompiledRazorAssemblyPart
  • Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
  • Microsoft.AspNetCore.Mvc.TagHelpers
  • Microsoft.AspNetCore.Mvc.Razor

功能提供程序

应用程序功能提供程序用于检查应用程序部件,并为这些部件提供功能。 以下 ASP.NET Core 功能有内置功能提供程序:

功能提供程序从 IApplicationFeatureProvider<TFeature> 继承,其中 T 是功能的类型。 可以为上面列出的任意功能类型实现功能提供程序。 ApplicationPartManager.FeatureProviders 中的功能提供程序的顺序可能影响运行时行为。 较晚添加的提供程序可能会影响较早添加的提供程序执行的操作。

显示可用功能

通过依存关系注入请求 ApplicationPartManager 即可以枚举应用的可用功能:

using AppPartsSample.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewComponents;

namespace AppPartsSample.Controllers
{
    public class FeaturesController : Controller
    {
        private readonly ApplicationPartManager _partManager;

        public FeaturesController(ApplicationPartManager partManager)
        {
            _partManager = partManager;
        }

        public IActionResult Index()
        {
            var viewModel = new FeaturesViewModel();

            var controllerFeature = new ControllerFeature();
            _partManager.PopulateFeature(controllerFeature);
            viewModel.Controllers = controllerFeature.Controllers.ToList();

            var tagHelperFeature = new TagHelperFeature();
            _partManager.PopulateFeature(tagHelperFeature);
            viewModel.TagHelpers = tagHelperFeature.TagHelpers.ToList();

            var viewComponentFeature = new ViewComponentFeature();
            _partManager.PopulateFeature(viewComponentFeature);
            viewModel.ViewComponents = viewComponentFeature.ViewComponents.ToList();

            return View(viewModel);
        }
    }
}

下载示例使用前面的代码显示应用功能:

Controllers:
    - FeaturesController
    - HomeController
    - HelloController
    - GenericController`1
    - GenericController`1
Tag Helpers:
    - PrerenderTagHelper
    - AnchorTagHelper
    - CacheTagHelper
    - DistributedCacheTagHelper
    - EnvironmentTagHelper
    - Additional Tag Helpers omitted for brevity.
View Components:
    - SampleViewComponent

应用程序部件中的发现

使用应用程序部件进行开发时,会遇到 HTTP 404 错误且并不鲜见。 发生这些错误的原因通常是由于未满足某项针对应用程序部件发现方式的基本要求。 如果应用返回 HTTP 404 错误,请验证是否满足以下要求:

  • 需要将 applicationName 设置设置为用于发现的根程序集。 用于发现的根程序集通常是入口点程序集。
  • 根程序集需要引用用于发现的部件。 引用可以是直接的,也可以是可传递的。
  • 根程序集需要引用 Web SDK。 该框架的逻辑会将属性标记到用于发现的根程序集中。

作者:Rick Anderson

查看或下载示例代码如何下载

应用程序部件是对应用资源的抽象化。 借助应用程序部件,ASP.NET Core 可以发现控制器、视图组件、标记帮助程序、Razor Pages、Razor 编译源等。 AssemblyPart 是应用程序部件。 AssemblyPart 用于封装程序集引用,并公开类型和编译引用。

功能提供程序使用应用程序部件填充 ASP.NET Core 应用的功能。 应用程序部件的主要用例是将应用配置为从程序集中发现(或避免加载)ASP.NET Core 功能。 例如,可能需要在多个应用之间共享通用功能。 借助应用程序部件,你可以与多个应用共享包含控制器、视图、Razor Pages、Razor 编译源、标记帮助程序等的程序集 (DLL)。 相对于在多个项目中复制代码,首选共享程序集。

ASP.NET Core 应用从 ApplicationPart 加载功能。 AssemblyPart 类表示受程序集支持的应用程序部件。

加载 ASP.NET Core 功能

使用 ApplicationPartAssemblyPart 类发现并加载 ASP.NET Core 功能(控制器、视图组件等)。 ApplicationPartManager 跟踪可用的应用程序部件和功能提供程序。 在 Startup.ConfigureServices 中配置 ApplicationPartManager

public void ConfigureServices(IServiceCollection services)
{
    // Requires using System.Reflection;
    var assembly = typeof(MySharedController).GetTypeInfo().Assembly;
    services.AddMvc()
        .AddApplicationPart(assembly)
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

以下代码提供使用 AssemblyPart 配置 ApplicationPartManager 的可选方法:

public void ConfigureServices(IServiceCollection services)
{
    // Requires using System.Reflection;
    // Requires using Microsoft.AspNetCore.Mvc.ApplicationParts;
    var assembly = typeof(MySharedController).GetTypeInfo().Assembly;
    var part = new AssemblyPart(assembly);
    services.AddMvc()
        .ConfigureApplicationPartManager(apm => apm.ApplicationParts.Add(part))
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

前面的两个代码示例从程序集加载 SharedControllerSharedController 未在应用程序的项目中。 请参阅 WebAppParts 解决方案示例下载。

包含视图

使用 Razor Razor 类库将视图包含在程序集中。

阻止加载资源

可以使用应用程序部件来避免加载特定程序集或位置中的资源。 添加或删除 Microsoft.AspNetCore.Mvc.ApplicationParts 集合的成员,将隐藏或提供资源。 ApplicationParts 集合中条目的顺序并不重要。 在使用 ApplicationPartManager 配置容器中的服务之前,对该类进行配置。 例如,在调用 AddControllersAsServices 之前配置 ApplicationPartManager。 在 ApplicationParts 集合上调用 Remove,将删除资源。

以下代码使用 Microsoft.AspNetCore.Mvc.ApplicationParts 删除应用中的 MyDependentLibrary

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
            .ConfigureApplicationPartManager(apm =>
            {
                var dependentLibrary = apm.ApplicationParts
                    .FirstOrDefault(part => part.Name == "MyDependentLibrary");

                if (dependentLibrary != null)
                {
                    apm.ApplicationParts.Remove(dependentLibrary);
                }
            });
}

ApplicationPartManager 包括以下内容的部件:

  • 应用的程序集和依赖程序集。
  • Microsoft.AspNetCore.Mvc.TagHelpers
  • Microsoft.AspNetCore.Mvc.Razor

应用程序功能提供程序

应用程序功能提供程序用于检查应用程序部件,并为这些部件提供功能。 以下 ASP.NET Core 功能有内置功能提供程序:

功能提供程序从 IApplicationFeatureProvider<TFeature> 继承,其中 T 是功能的类型。 可以为上面列出的任意功能类型实现功能提供程序。 ApplicationPartManager.FeatureProviders 中的功能提供程序的顺序可能影响运行时行为。 较晚添加的提供程序可能会影响较早添加的提供程序执行的操作。

显示可用功能

通过依存关系注入请求 ApplicationPartManager 即可以枚举应用的可用功能:

using AppPartsSample.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Controllers;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewComponents;

namespace AppPartsSample.Controllers
{
    public class FeaturesController : Controller
    {
        private readonly ApplicationPartManager _partManager;

        public FeaturesController(ApplicationPartManager partManager)
        {
            _partManager = partManager;
        }

        public IActionResult Index()
        {
            var viewModel = new FeaturesViewModel();

            var controllerFeature = new ControllerFeature();
            _partManager.PopulateFeature(controllerFeature);
            viewModel.Controllers = controllerFeature.Controllers.ToList();

            var tagHelperFeature = new TagHelperFeature();
            _partManager.PopulateFeature(tagHelperFeature);
            viewModel.TagHelpers = tagHelperFeature.TagHelpers.ToList();

            var viewComponentFeature = new ViewComponentFeature();
            _partManager.PopulateFeature(viewComponentFeature);
            viewModel.ViewComponents = viewComponentFeature.ViewComponents.ToList();

            return View(viewModel);
        }
    }
}

下载示例使用前面的代码显示应用功能:

Controllers:
    - FeaturesController
    - HomeController
    - HelloController
    - GenericController`1
    - GenericController`1
Tag Helpers:
    - PrerenderTagHelper
    - AnchorTagHelper
    - CacheTagHelper
    - DistributedCacheTagHelper
    - EnvironmentTagHelper
    - Additional Tag Helpers omitted for brevity.
View Components:
    - SampleViewComponent

应用程序部件中的发现

使用应用程序部件进行开发时,会遇到 HTTP 404 错误且并不鲜见。 发生这些错误的原因通常是由于未满足某项针对应用程序部件发现方式的基本要求。 如果应用返回 HTTP 404 错误,请验证是否满足以下要求:

  • 需要将 applicationName 设置设置为用于发现的根程序集。 用于发现的根程序集通常是入口点程序集。
  • 根程序集需要引用用于发现的部件。 引用可以是直接的,也可以是可传递的。
  • 根程序集需要引用 Web SDK。
    • ASP.NET Core 框架具有自定义生成逻辑,会将属性标记到用于发现的根程序集中。