Umbraco CMS MVC-独自のコントローラーと美しいURL

CMS Umbraco私は数ヶ月間勉強しています。 私の研究活動の主な用途は、このシステムの最新バージョン7、および以前のバージョンのWebフォームに代わるものとしてのMVCエンジンでの作業のコンテキストを目的としたものでした。



ある時点で、ある会社のサイトを開発しているときに、この会社のニュースリポジトリをコンテンツツリーの別の最上位要素に移動したかったのです。 UmbracoのWebサイトに投稿されている例とビデオの説明では、このような組織の最も単純なバージョンが提案されています。ニュースはメニュー項目の子として保存されます(図1)。 例として、「Umbracoにアプローチする方法」のセクションでは、このアプローチは正当化されますが、数十、数百のニュースがあるライブサイトでは、かなり扱いにくいように見えます。 ニュースを扱うには、サイトエディターがコンテンツツリーのより深く行く必要があります-Home -News-Separate News 。 そして、このアプローチの概念そのものは私にはあまり適していません。マルチレベルメニュー項目のセクションに、ニュースのリストが突然表示されます...





画像



図2のように、別のオプションがより望ましいようです。ニュースを含むサイトは、コンテンツツリーの最上位の独立した要素です。



画像



さらに、参照によるニュースへのアクセスを整理するとき、私は彼らに美しい標準的な外観を持たせたいと思いました。





この問題を解決するMVCパラダイムは、コントローラーと表現の存在を前提としています(この場合、モデルは使用しません)。 すべてがUmbracoの「翼の下」で行われるため、News ControllerをControllerクラスから継承して実装することはできません。何も起こりません。 Umbracoのドキュメントでは、このCMSのインフラストラクチャに具体的に存在するSurfaceControllerクラスから継承することを提案しています。 すべて問題ありませんが、この場合、コントローラーアクションが呼び出されるリンクは、「 / umbraco / surface / _controllername _ / _ actionname_ 」の形式を取ります。 このようなurl構造はやや煩雑に見え、検索インデックスの観点からすると、同様のurlを持つページはサイト構造に深く隠されていると認識され、おそらく検索値が低下します。



この問題の研究により、次の解決策が導き出されました。SurfaceControllerクラスからではなく、 PluginControllerから継承する必要があります。 この場合、リンクは必要に応じてMVCの標準に従って生成されます。 ただし、いくつかの追加の状況を考慮する必要があります。 以下は、この問題の完全な解決策です。 だから:



ルート



ルートは、 App_Start / RouteConfig.csファイルに登録されていません。これは デフォルトGlobal.asaxで RouteConfig.RegisterRoutes(RouteTable.Routes)として呼び出さ ます 。 Umbraco MVCでは、 PluginControllerクラスの場合、 ルートはファイルApp_Code / Startup.csに登録されます。 このファイルでは、 IApplicationEventHandlerインターフェイスを実装するクラスを宣言します。 次のようになります。



public class MyStartupHandler : IApplicationEventHandler { public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { //Create a custom routes // News controller RouteTable.Routes.MapRoute( "", "News", new { controller = "News", action = "Index", page = 1 }); RouteTable.Routes.MapRoute( "", "News/Index", new { controller = "News", action = "Index", page = 1 }); RouteTable.Routes.MapRoute( "", "News/Page{page}", new { controller = "News", action = "Index", page = UrlParameter.Optional }); RouteTable.Routes.MapRoute( "", "News/{id}", new { controller = "News", action = "News", id = UrlParameter.Optional }); } public void OnApplicationInitialized( UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { } public void OnApplicationStarting( UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { } }
      
      







コントローラー



コントローラーは、通常の方法でControllersフォルダーにあるファイルに作成されます。 前述のように、コントローラークラスはPluginControllerクラスを継承します。 次のようになります。



 public class NewsController : PluginController { public NewsController() : this(UmbracoContext.Current) { } public NewsController(UmbracoContext umbracoContext) : base(umbracoContext) { } public ActionResult Index(string id) { /*   ,            -   ,     .. */ return View("News", CreateRenderModel(renderModel)); } private RenderModel CreateRenderModel(IPublishedContent content) { var model = new RenderModel(content, CultureInfo.CurrentUICulture); //add an umbraco data token so the umbraco view engine executes RouteData.DataTokens["umbraco"] = model; return model; } }
      
      





ここで説明が必要です。 ニュースノードの検索コードは、タイプIPublishedContentまたはIEnumerable <IPublishedContent>のオブジェクトを返します。 ただし、Umbracoでは、 PluginController 'aから呼び出されたビューを厳密に型指定し、タイプRenderModelのモデルを受け入れる必要があります。 これを行うには、プライベートメソッドCreateRenderModelがコントローラーで宣言され、 IPublishedContentから必要なタイプのオブジェクトが作成されます



提出



プレゼンテーションは標準スキームに従って作成されますが、この問題を解決する上でニュアンスはありません。



副作用



このアプローチを使用すると、1つのサードパーティの効果、つまり、この方法で呼び出されたページのコンテンツでマクロを使用できないことが明らかになりました。 「 PublishedContentRequest missing 」の定義でエラーが発生します。 私が理解しているように、このようなコントローラーを介して表示されるドキュメントは、Umbraco解析のすべての段階を経ず、その間に同じPublishedContentRequestが作成され、そこからマクロ生成コードが反発されるという事実に関連しています。 MVC部分ビューを使用する際にマクロを使用することは一般的ではなくなってきていると考えると安心です。 さらに、Umbracoの作成者自身は、リッチテキストコンテンツからのマクロ呼び出しを実装するコードはかなり紛らわしく、過去の激しい前感情の深刻な痕跡があると言っています...



参照資料



表面コントローラー

UmbracoのカスタムMVCルーティング



All Articles