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
。