Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Sitecore、自定义MVC控制器和路由_C#_Routing_Asp.net Mvc 5_Sitecore_Sitecore7 - Fatal编程技术网

C# Sitecore、自定义MVC控制器和路由

C# Sitecore、自定义MVC控制器和路由,c#,routing,asp.net-mvc-5,sitecore,sitecore7,C#,Routing,Asp.net Mvc 5,Sitecore,Sitecore7,我在Sitecore的网站定义中定义了一个网站。它的路径是/localhost/mysite/home。它是有效的 我需要创建一个自定义控制器,通过绕过Sitecore的API提交表单。因此,我有FormsController(继承自MVC控制器),其中一个名为“Test”的操作不带任何参数 我在初始化管道中定义了如下路由: public class Initialize { public void Process(PipelineArgs args) { Map

我在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" });
     }
}
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);
    }
路由被正确地添加到路由表中,并且在调试它时它就在那里。 现在,当我尝试调用方法“test”时,找不到路由,并且调试器在操作中没有命中断点

我正在尝试不同的路线:

  • /localhost/mysite/home/forms/test
  • /localhost/forms/test
    (默认网站)
但到目前为止运气不好

----更新---

深入研究之后,我注意到Sitecore的行为有问题。
TransferRoutedRequest
处理器应该中止
httpRequestBegin
管道,在上下文项为空的情况下将控制权交还给MVC(简化)。它是在一些检查之后发生的,其中一个检查是关于路由表数据的。但是对
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();
   }
}

下面是将为您创建路由的代码。在global.asax.cs中,您将从应用程序启动事件处理程序调用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类操作方法测试(字符串id),但您可以省略id参数

,这里是从我的一个项目中提取的一个工作示例

自定义路线注册:

namespace Test.Project.Pipelines.Initialize
{
公共类InitRoutes:Sitecore.Mvc.Pipelines.Loader.InitializeRoutes
{
公共覆盖无效进程(PipelineArgs args)
{
注册地址(RouteTable.Routes);
}
受保护的虚拟空注册表端口(RouteCollection路由)
{
routes.MapRoute(
“Test”,//路由名称
“api/test/{controller}/{action}/{id}”,//带参数的URL
新建{id=urlparmeter.Optional}
);
}
}
}
初始化管道配置:


我终于让它正常工作了。我写的
TransferRoutedRequest
没有按预期工作,所以我不得不重写它。尽管如此,即使它按预期运行,路线也没有得到解决。问题出在管道配置中。多亏了一位同事,我打开了SitecoreRocks管道工具,它显示管道注册的位置离它应该在的位置太远,因此它从未被击中(我在
itemsolver
之后注册了它,因为它是在原始配置上注册的)。我在
LayoutResolver
之前打了补丁,结果成功了。路线已确定。 不过,Sitecore无法创建该类型的实例,因为它位于另一个程序集中。即使指定控制器的名称空间也不能解决问题。因此,我必须做一些修改,重写ControllerFactory类的CreateController方法,重写InitializeControllerFactory处理器(我已经对其进行了修改,以便能够使用DI容器),编写一个新的
ControllerFactory
和一个新的
SitecoreControllerFactory

最后的代码如下所示:

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" });
     }
}
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);
    }
在处理Sitecore项目时,我使用
TypeHelper
从控制器呈现或布局返回当前控制器类型。否则,我将使用
DefaultControllerFactory.GetControllerType
解析自定义路由


唯一需要注意的是:如果2个或多个名称空间具有相同名称和操作的控制器,则必须添加名称空间以识别它们。

您正在复制我的(不工作)示例,但添加了错误的做法:修改
应用程序\u Start
方法。我无法使用全球asax,即使我有,我也不会碰它。正确的方法是通过初始化管道,将配置添加到App_Config/include文件夹。或者,作为第二种选择,通过使用
assembly:PreApplicationStartMethod
装饰您自己的init类,我当然意识到至少出于维护目的,最好避免修改global.asax.cs——我只是为了理解而简化了它。一个代码片段的例子是一个工作代码,因为我已经提前对它进行了测试。你读过我写的吗?这是你写的同一个例子,但对我不起作用。所以关键是:我知道通常的技术是如何工作的,但在我的情况下它不起作用。那么,用通常的方法回答问题有什么意义呢?此外:您是否在sitecore中创建了新的网站配置?如果是,您是否在新创建的网站中测试了您的方法?我不这么认为……亲爱的地狱骑士,@MartinMiles试图帮助你,而你却不友善。如果我是你,我就不会指望其他人会帮助亲爱的马瑞克和马丁。我很抱歉。我不是故意粗鲁的。但只有当我有真正的问题时,我才会在这里发布消息。正如我已经说明的,我完全知道这应该如何工作。但是,不知什么原因,它没有。此外,StackOverflow的目标不仅应该是解决问题,还应该教会人们如何正确地解决问题。我注意到马丁