rksoftware

Visual Studio とか C# とかが好きです

ASP.NET Core MVC にコントローラーを追加する

以前に ASP.NET MVC にコントローラーを追加する記事を書きました。

簡単に言うと、ASP.NET MVC のカレントのディレクトリに Controller クラスの含まれる DLL を置いてしまうと作りによってはそれだけで、実行されている ASP.NET MVC プロジェクト自身に手を加えることなく Controller を追加できてしまうというものでした。
手をあまりかけずに作った ASP.NET MVC アプリに発生する抜け穴の様なもので、本来はアプリでちゃんと設定をしてできないようにしておくのが良いものなのだろうとは思います。

■ ASP.NET Core MVC

ASP.NET Core MVC では基本状態で上で書いたような追加はできなくなっているようです。同じようなことを実現するには Startup.cs に手を入れて穴をあけておく必要があるようです。

テンプレートで生まれた状態

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

この ConfigureServices メソッドに手を加えます。
今回は、カレントのディレクトリではなく、拡張機能の体で Extensions というフォルダの中に DLL を置くという想定で書いてみました。

書き加えた状態

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        var builder = services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        var entryAssembly = System.Reflection.Assembly.GetEntryAssembly().Location;
        var entryDirectory = System.IO.Path.GetDirectoryName(entryAssembly);

        var extensionDirectory = System.IO.Path.Combine(entryDirectory, "Extensions");
        if (System.IO.Directory.Exists(extensionDirectory))
        {
            var extensionDlls = System.IO.Directory.GetFiles(extensionDirectory, "*.dll");
            var extensionAssemblys = extensionDlls.Select(dll => System.Reflection.Assembly.LoadFile(dll)).ToArray();

            foreach (var assembly in extensionAssemblys)
                builder.AddApplicationPart(assembly);
        }
    }

追加する Controller を含んだ DLL

.NET Core のクラスライブラリプロジェクトを作成します。

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;

namespace ExtensionDll
{
    [Route("api/[controller]")]
    [ApiController]
    public class ExtensionController : ControllerBase
    {
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "saitama", "gunma" };
        }
    }
}

このクラスを含んだ DLL を Extensions ディレクトリに置いて ASP.NET Core MVC プロジェクトを実行。ブラウザで localhost:5000/api/Extensionlocalhost:5001/api/Extension にアクセスすると

f:id:rksoftware:20190529033657j:plain

とブラウザに表示され、Controller の追加が確認できました。