Ignia.Topics.Web.Mvc
Ignia.Topics.Web.Mvc
組件提供了與 ASP.NET MVC 5.x Framework 一起使用的 OnTopic 實作。
MVC 實作的核心包含三個關鍵元件。
MvcTopicRoutingService
:這是ITopicRoutingService
的具體實現,它接受有關給定請求的上下文資訊(在本例中為 URL 和路由資料),然後使用它從ITopicRepository
檢索當前Topic
。TopicController
:這是一個預設控制器實例,可用於任何主題路徑。它將自動驗證Topic
是否存在,是否未停用( IsDisabled
),並且將尊重任何重定向(例如,如果填寫了Url
屬性)。否則,它將根據視圖模型、視圖名稱和內容類型傳回TopicViewResult
。TopicViewEngine
:每次請求視圖時都會呼叫TopicViewEngine
。它與TopicViewResult
結合使用,根據預定位置和約定識別匹配的 MVC 視圖。這些將在下面討論。 MVC 實作附帶了六個主要控制器。除了核心TopicController
之外,還包括以下輔助控制器:
ErrorControllerBase<T>
:提供Error
、 NotFound
和InternalServer
操作的支援。可以接受任何IPageTopicViewModel
作為通用參數;將用作視圖模型。FallbackController
:在控制器工廠中用作後備,以防其他控制器無法接受要求。只需傳回一個帶有預先定義訊息的NotFoundResult
。LayoutControllerBase<T>
:透過自動對應目前命名空間的前三層(例如, Web
、其子級和孫級)來提供導航選單的支援。可以接受任何INavigationTopicViewModel
作為通用參數;將用作每個映射實例的視圖模型。RedirectController
:提供單一Redirect
操作,可以綁定到路由,例如/Topic/{ID}/
;這為獨立於GetWebPath()
的永久 URL 提供支援。SitemapController
:提供單一Sitemap
操作,該操作傳回對ITopicRepository
的引用,從而允許網站地圖視圖在整個主題圖(包括所有屬性)上遞歸。注意: MVC 沒有一種實用的方法來為通用控制器提供路由。因此,每個實作都必須對它們進行子類化。除了提供對通用基底類別的特定類型參考之外,派生控制器不需要執行任何操作。
預設情況下,OnTopic 根據目前主題的ContentType
和View
(如果可用)來匹配視圖。
設定視圖的方法有多種。 TopicViewResult
將根據下列位置自動評估視圖。選擇第一個與有效視圖名稱相符的視圖。
?View=
查詢字串參數(例如?View=Accordion
)Accept
標頭(例如Accept=application/json
);將把/
之後的段落視為可能的視圖名稱View
屬性(即topic.View
)ContentType
屬性(即topic.ContentType
)對於上述每個視圖匹配規則, TopicViewEngine
將在以下位置搜尋匹配視圖:
~/Views/{ContentType}/{View}.cshtml
~/Views/ContentTypes/{ContentType}.{View}.cshtml
~/Views/ContentTypes/{ContentType}.cshtml
~/Views/Shared/{View}.cshtml
注意:在每個位置搜尋每個視圖匹配規則後,控制權將移交給
RazorViewEngine
,它將搜尋 ASP.NET MVC 的現成預設位置。
如果topic.ContentType
是ContentList
並且Accept
header 是application/json
那麼TopicViewResult
和TopicViewEngine
將協調搜尋以下路徑:
~/Views/ContentList/JSON.cshtml
~/Views/ContentTypes/ContentList.JSON.cshtml
~/Views/ContentTypes/JSON.cshtml
~/Views/Shared/JSON.cshtml
如果未找到匹配項,則將搜尋下一個Accept
標頭。最終,如果在各種視圖匹配規則上找不到匹配項,則將搜尋以下內容:
~/Views/ContentList/ContentList.cshtml
~/Views/ContentTypes/ContentList.ContentList.cshtml
~/Views/ContentTypes/ContentList.cshtml
~/Views/Shared/ContentList.cshtml
在global.asax.cs
中,應在Application_Start
事件處理程序下註冊以下元件:
ControllerBuilder.Current.SetControllerFactory(new OrganizationNameControllerFactory());
ViewEngines.Engines.Insert(0, new TopicViewEngine());
注意:控制器工廠名稱是任意的,並且應遵循適合站點的約定。 Ignia 通常使用
{OrganizationName}ControllerFactory
(例如IgniaControllerFactory
),但 OnTopic 不需要知道或在乎名稱是什麼;它位於您的應用程式和 ASP.NET MVC 框架之間。
透過RouteConfig.RegisterRoutes()
(通常透過RouteConfig
類別)註冊路由時,為任何 OnTopic 路由註冊一個路由:
routes.MapRoute(
name: "WebTopics",
url: "Web/{*path}",
defaults: new { controller = "Topic", action = "Index", id = UrlParameter.Optional, rootTopic = "Web" }
);
注意:由於 OnTopic 依賴通配符路徑名,因此應為每個根命名空間(例如
/Web
)配置新路由。雖然可以配置 OnTopic 來評估所有路徑,但這使得在必要時將控制權委託給其他控制器和處理程序變得困難。
由於 OnTopic 依賴建構函式註入,因此必須在組合根中配置應用程式 — 對於 ASP.NET MVC,這意味著自訂控制器工廠。其基本結構可能如下所示:
var connectionString = ConfigurationManager.ConnectionStrings["OnTopic"].ConnectionString;
var sqlTopicRepository = new SqlTopicRepository(connectionString);
var cachedTopicRepository = new CachedTopicRepository(sqlTopicRepository);
var topicViewModelLookupService = new TopicViewModelLookupService();
var topicMappingService = new TopicMappingService(cachedTopicRepository, topicViewModelLookupService);
var mvcTopicRoutingService = new MvcTopicRoutingService(
cachedTopicRepository,
requestContext.HttpContext.Request.Url,
requestContext.RouteData
);
switch (controllerType.Name) {
case nameof(TopicController):
return new TopicController(sqlTopicRepository, mvcTopicRoutingService, topicMappingService);
case default:
return base.GetControllerInstance(requestContext, controllerType);
}
有關完整的參考模板(包括輔助控制器),請參閱OrganizationNameControllerFactory.cs
Gist。
注意:預設的
TopicController
會自動辨識目前主題(例如基於URL),將目前主題對應到對應的視圖模型(基於TopicMappingService
約定),然後傳回對應的視圖(基於視圖約定)。對於大多數應用程式來說,這已經足夠了。但是,如果需要自訂映射規則或附加表示邏輯,實作者可以子類化TopicController
。