我在Sitecore的网站定义中定义了一个网站。它的路径是/localhost/mysite/home
。它有效。
我需要创建一个自定义控制器来使用绕过Sitecore的API提交表单。所以我有FormsController
(继承自MVC控制器),其动作名为" Test"没有参数。
我在初始化管道中定义了这样的路由:
public class Initialize
{
public void Process(PipelineArgs args)
{
MapRoutes();
GlassMapperSc.Start();
}
private void MapRoutes()
{
RouteTable.Routes.MapRoute(
"Forms.Test",
"forms/test",
new
{
controller = "FormsController",
action = "Test"
},
new[] { "Forms.Controller.Namespace" });
}
}
路由正确地添加到路由表中,当我调试它时它就在那里。 现在,当我尝试调用方法" test"时,找不到路由,调试器也没有点击操作中的断点。
我尝试了不同的路线:
/localhost/mysite/home/forms/test
/localhost/forms/test
(默认网站)但到目前为止没有运气。
----更新---
深入研究,我注意到Sitecore的行为有问题。 TransferRoutedRequest
处理器应该中止httpRequestBegin
管道,在上下文项为空(简化)的情况下将控制权交还给MVC。它发生在一些检查之后,其中一个是RoutTable数据。但是对RouteTable.Routes.GetRouteData
的调用总是返回null,这使得处理器返回而不中止管道。我重写它以使其正确地中止管道,但是,即使我调用方法args.AbortPipeline()
,管道也不会中止并且路由未被解析。
这就是原始TransferRoutedRequest
的样子:
public class TransferRoutedRequest : HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
Assert.ArgumentNotNull((object) args, "args");
RouteData routeData = RouteTable.Routes.GetRouteData((HttpContextBase) new HttpContextWrapper(HttpContext.Current));
if (routeData == null)
return;
RouteValueDictionary routeValueDictionary = ObjectExtensions.ValueOrDefault<Route, RouteValueDictionary>(routeData.Route as Route, (Func<Route, RouteValueDictionary>) (r => r.Defaults));
if (routeValueDictionary != null && routeValueDictionary.ContainsKey("scIsFallThrough"))
return;
args.AbortPipeline();
}
}
这就是我如何覆盖它:
public class TransferRoutedRequest : global::Sitecore.Mvc.Pipelines.HttpRequest.TransferRoutedRequest
{
public override void Process(HttpRequestArgs args)
{
if (Context.Item == null || Context.Item.Visualization.Layout == null)
args.AbortPipeline();
else
base.Process(args);
}
}
答案 0 :(得分:5)
以下是我的一个项目的工作示例。
自定义路线注册:
namespace Test.Project.Pipelines.Initialize
{
public class InitRoutes : Sitecore.Mvc.Pipelines.Loader.InitializeRoutes
{
public override void Process(PipelineArgs args)
{
RegisterRoutes(RouteTable.Routes);
}
protected virtual void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
"Test", // Route name
"api/test/{controller}/{action}/{id}", // URL with parameters
new { id = UrlParameter.Optional }
);
}
}
}
初始化管道配置:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<initialize>
<processor type="Test.Project.Pipelines.Initialize.InitRoutes, Test.Project"
patch:after="processor[@type='Sitecore.Mvc.Pipelines.Loader.InitializeRoutes, Sitecore.Mvc']" />
</initialize>
</pipelines>
</sitecore>
</configuration>
答案 1 :(得分:0)
以下是为您创建路线的代码。在global.asax.cs中,您将从App_Start事件处理程序中调用RegisterRoutes:
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
然后您将路线指定为:
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute(
name: "test",
url: "mvc/Forms/{action}/{id}",
defaults: new { controller = "Forms", action = "Test", id = UrlParameter.Optional }
);
}
在这种情况下,您将使用/ mvc /前缀来处理指定控制器的路由,因此您将其称为:
/mvc/Forms/Test/{you_may_pass_some_optional_GUID_here}
这将路由到FormsController类操作方法Test(字符串id),但您可以省略id参数
答案 2 :(得分:0)
最后我的工作正常。正如我写的TransferRoutedRequest
没有按预期工作,所以我不得不覆盖它。尽管如此,即使它按预期工作,路线也没有得到解决。问题出在管道配置中。感谢一位同事,我打开了SitecoreRocks管道工具,它显示管道注册的位置离它应该的位置太远,所以它从未被击中(我在ItemResolver
之后注册了它,因为它在原配置)。我在LayoutResolver
之前修补了它,这就是诀窍。路线得到了解决。
尽管如此,Sitecore还是无法创建该类型的实例,就像在另一个程序集中一样。即使指定控制器的命名空间也无法解决问题。所以我不得不进行一些修改并覆盖ControllerFactory类的CreateController方法并覆盖InitializeControllerFactory处理器(我已经修改过它以便能够使用DI容器),编写一个新的ControllerFactory
和一个新的{{1} }。
最终代码如下:
SitecoreControllerFactory
如果我正在处理Sitecore项目,我使用public override IController CreateController(RequestContext requestContext, string controllerName)
{
var controller = SC.Context.Item == null || SC.Context.Item.Visualization.Layout == null
? base.GetControllerType(requestContext, controllerName)
: TypeHelper.GetType(controllerName);
return GetControllerInstance(requestContext, controller);
}
从控制器呈现或布局返回当前控制器类型。否则,我使用TypeHelper
来解析自定义路由。
唯一需要注意的是:如果2个或更多名称空间的控制器具有相同的名称和操作,则必须添加名称空间以识别它们。