ASP.NET MVC でアプリケーションを複数のプロジェクトに分けてみたかった

# 環境
- Windows10 Pro (2004) 64bit
- Visual Studio 2019
- .NET Frame Work 4.5  
//会社の環境に合わせてフレームワークバージョン低くしがち

# 要約すると
複数のWebシステムと、それを統括する1つのWebシステム…みたいな構成にしたいとき、
ただAreasで分けるだけだと、結局1プロジェクトに複数のWebシステムが全部入ってくることになってしまう。
別システムは別プロジェクトで開発したいと思ったのでちょっと調べた。
結果[AreaRegistration]なるクラスを使えば**ある程度**出来るらしいのでまとめておく。

# アプローチ
## メインとなるサイトのプロジェクトを立てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/69ed58a6-c68c-8886-98b1-1a4f5efe543e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/fcbe5c82-97cd-1e6c-3cff-e481f4b14c59.png)
メインのサイトはテンプレート[MVC]で作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/c8225e6b-95d4-df4d-25e6-878792a38d1f.png)
出来上がりはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/5f025c9e-3559-3aba-1b12-06906d3a4118.png)
実行するとこう。親の顔より見たデフォルトページ。

## 別システムのプロジェクトを立てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/ee83a96b-8849-3dc4-17e9-fd86daf64f50.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/40512105-c558-1bea-b406-beba33108702.png)
こちらのテンプレートは**空**、コア参照の**MVC**にチェックを入れる。
//こちらのテンプレートをMVCで作成したら起動に失敗したのでとりあえず空。詳しい人何でか教えてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/a7be2953-a01d-d6e2-08b8-82d0036f2917.png)
出来上がりはこう。
ControllerもViewもないからまだ動かない。

## 別システムにとりあえず表示機能を付ける
Controllerを作成する。
Controllersフォルダを右クリックして[追加]→[コントローラー]→[MVC5コントローラー -空]

```c#:SubSystemHomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace SubSystemWeb.Controllers
{
    public class SubSystemHomeController : Controller
    {
        // GET: SubSystemHome
        public ActionResult Index()
        {
            return View();
        }
    }
}
```
とりあえず自動作成されたコードをそのまま使う。

Viewを作成する。
Controllerを作成するとViewsフォルダ内にSubSystemHomeフォルダ(Controller名から自動作成)が作成される。
SubSystemHomeフォルダを右クリックして[追加]→[ビュー]→ビュー名を「Index」に指定。

```Razor:Index.cshtml
@{
    ViewBag.Title = "Index";
}

<h2>SubSystemIndex</h2> <!--デフォルトだと[Index]なので、[SubSystemIndex]に変更した-->
```
//Qiitaでcshtml(Razor?)のコード入れるときの設定も誰か教えて…

デフォルトで実行するコントローラーが[SubSystemHome]なので、ルーティングを変更。
App_Startフォルダ内、RouteConfig.csを変更する

```c#:RouteConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace SubSystemWeb
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            //defaultsに指定しているクラスのcontrollerプロパティを[Home]→[SubSystemHome]に変更
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "SubSystemHome", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}
```

ここまでやると別システム側も単独で動く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/dec267f1-c1c0-e6f4-b6a4-960657e7ea95.png)

## 別システム側にAreaRegistrationを継承したクラスを追加
**今回の肝**。
別システム側にAreaRegistrationクラスを継承したクラスを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/32e24f24-740c-5de7-7eb2-107d8cb31dc3.png)

```c#:SubSystemAreaRegistration.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace SubSystemWeb
{
    public class SubSystemAreaRegistration : AreaRegistration
    {
        public override string AreaName => "SubSystem";

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                name: "SubSystemDefault",
                url: "SubSystem/{controller}/{action}/{id}",
                defaults: new { controller = "SubSystemHome", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}
```

## メイン側から参照設定する
メイン側のプロジェクトから別システムをプロジェクト参照する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/09345de7-1e56-2f0e-97d5-a76caee85656.png)

## いざ実行　からのエラー…
メイン側をデバッグ実行して、URLを[localhost:(PortNumber)/SubSystem]にアクセスする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/5797d0ab-efe6-3db5-537d-571dd6240402.png)
無事エラーになりました。
エラーになる理由は、ビューが見つからないから。
**実行しているのはMainSiteであり、SubSystem側のビューを見に行くことができないからです。**
**ASP.NET MVCはビュー(cshtml)がdllに含まれないので、ファイルとして存在する必要があります。**

## 仕方ないのでビュー追加
表示されたエラーを見ると[Areas]フォルダを参照していることがわかります。
Areasフォルダは普通にArea分けするときに作るフォルダです。
エラーに表示された通り、\Areas\SubSystemを作成し、
その中にSubSystemWebのViewsフォルダをコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/8d67d514-b193-ecc3-8b5b-0f80e75670a3.png)
これがあるから冒頭で「**ある程度**」と書きました。
「参照設定を変えるだけで機能を追加したり削除したりできる」というお手軽さには微妙に届かない残念な結果です……

## 再度実行したらちゃんと表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470282/ddea8be1-3eb1-bede-c808-ca16f623564d.png)

# まとめ
- サーバーサイドだけ見ればうまくいっている。デバッグを別システム単体で実行する形であれば今回のやり方で問題なさそう。
- サイト発行した場合もAreasフォルダにViewsを放り込んでいけば動く。
- メイン側からのデバッグでサブ側のビューをデバッグする場合はひと手間必要。

以上です。
もっといいやり方がある気がするので、詳しい方教えてください。