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。