Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9337

ASP.NET Core MVC Areaを利用する

$
0
0

何でエリアを利用するかについては省きます。

バージョン

.net 5.0
Microsoft Visual Studio Community 2019 Version 16.8.6

フォルダー構成

例えアプリにPersonnelとTreasurerという二つの論理グループがあるとします、エリアを利用するとフォルダー構造は次のようになります。
*プロジェクト名
 |-Areas
  |-Personnel
   |-Controllers
    |-HomeController.cs
   |-Models
    |-HomeModel.cs
   |-Views
    |-Home
     |-Index.cshtml
     |-About.cshtml
  |-Treasurer
   |-Controllers
    |-HomeController.cs
   |-Models
    |-HomeModel.cs
   |-Views
    |-Home
     |-Index.cshtml
     |-About.cshtml
 |-Controllers
 |-Models
 |-Views
 |-wwwroot

エリアを利用する時の構造は一般的にこうなっているですが、MVCの規約ではViewファイルのみこの構造に従う必要がある、ModelとControllerは従わなくても問題がない、外だしは可能ということです。

エリアを作成

プロジェクトで右クリック⇒追加⇒新規スキャフォールディングアイテム
image.png

MVCエリアを選んで追加、その後エリア名を入力して作成する
image.png

エリアを作成した後の実際の構造は次のようになります
image.png

エリアルートを追加

Startup.cs
publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){if(env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Home/Error");// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints=>{//ルーティングのルールによって、エリアを持つルートはエリアを持たないルート具体的なので、前に配置する必要があるendpoints.MapControllerRoute(name:"areas",pattern:"{area:exists}/{controller=Home}/{action=Index}/{id?}");endpoints.MapControllerRoute(name:"default",pattern:"{controller=Home}/{action=Index}/{id?}");});}

詳細なエリアルーティングはここから参照

上記コードの「{area:exists}」ではルートが必ず一つのエリアと一致しなければならないという制約を掛けている
詳細なルーティング制約はここから参照

エリアのコントローラー作成

HomeController.cs
namespaceWebAppForDotNetCore5.Areas.Personnel.Controllers{//エリア属性によって、該当コントローラーを指定のエリアと関連付ける[Area("Personnel")]publicclassHomeController:Controller{publicIActionResultIndex(){returnView();}}}

_ViewStart.cshtml と _ViewImports.cshtml

この二ファイルの影響先はファイルを配置しているフォルダー及びその下級フォルダーのみ、なのでエリアじゃなく普通のViewsフォルダーにあるこの二ファイルはAreasに対しては影響を与えることはできない。
ViewsとAreasの両方に対して影響を与えたい場合はアプリケーションのルートフォルダ(Startup.csを含むフォルダ)にそのファイルを配置もしくはコピーすること。

_ViewStart.cshtmlの詳細はここから参照
_ViewImports.cshtmlの詳細はここから参照

Areasのフォルダー名変更

既定のエリアフォルダー「Areas」を変更することはできます

Startup.cs
publicvoidConfigureServices(IServiceCollectionservices){services.Configure<RazorViewEngineOptions>(options=>{//既存のエリアビューの検出ルールをクリアoptions.AreaViewLocationFormats.Clear();//新しいエリアビューの検出ルールを登録するoptions.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/{1}/{0}.cshtml");options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/Shared/{0}.cshtml");options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");});services.AddControllersWithViews();}

Area属性の応用

前述のようにエリアとコントローラーを関連付けるため、ントローラーにArea属性を定義する必要が有ります、もしそのエリアに沢山のコントローラーがあったらそれ全部を定義する必要が有ります。そうなると問題が発生し易くなります。

Microsoft.AspNetCore.Mvc.Core.dll
[System.AttributeUsage(System.AttributeTargets.Class|System.AttributeTargets.Method,AllowMultiple=false,Inherited=true)]publicclassAreaAttribute:Microsoft.AspNetCore.Mvc.Routing.RouteValueAttribute

AreaAttributeクラスの定義から見るとArea属性が継承を許されていることがわかる、つまり親にArea属性を設定するとそのクラスを継承した子にもArea属性が適用されます。よってエリアコントローラーは次のように変更可能

PersonnelBaseController.cs
namespaceWebAppForDotNetCore5.Areas.Personnel.Controllers{//親コントローラーにArea属性を設定//Controllerが抽象クラスなので、PersonnelBaseControllerは抽象にしてもしなくても良いです[Area("Personnel")]publicabstractclassPersonnelBaseController:Controller{}}
HomeController.cs
namespaceWebAppForDotNetCore5.Areas.Personnel.Controllers{//親コントローラーにエリア属性を設定しているので、該当子コントローラーには設定しなくてもPersonnelエリアと関連付けているpublicclassHomeController:PersonnelBaseController{publicIActionResultIndex(){returnView();}}}

まとめ

エリアのビューの検出順序
  • /Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
  • /Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
  • /Views/Shared/<Action-Name>.cshtml
  • /Pages/Shared/<Action-Name>.cshtml
長くなるので、エリア毎に認証スキーム設定に関しては別の記事でまとめる

Viewing all articles
Browse latest Browse all 9337

Latest Images

Trending Articles