Sitecore,自定义MVC控制器和路由 [英] Sitecore, custom MVC controllers and routes

查看:179
本文介绍了Sitecore,自定义MVC控制器和路由的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在Sitecore的网站定义中定义的网站。路径为 / localhost / mysite / home

I have a website defined in Sitecore's site definitions. The path to it is /localhost/mysite/home. And it works.

我需要创建一个自定义控制器,以使用绕过Sitecore的API提交表单。因此,我有 FormsController (继承自MVC控制器),它的操作名为 Test,不带任何参数。

I need to create a custom controller to submit forms with an API bypassing Sitecore. So I have FormsController (inheriting from MVC controller) with an action named "Test" taking no parameters.

I在初始化管道中这样定义路由:

I defined the route in the initialize pipeline like this:

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时,找不到路由,并且调试器未在操作中达到断点。

The route is added to the route table correctly, and it's there when I debug it. Now, when I try to call method "test", the route is not found and the debugger doesn't hit the breakpoint in the action.

I我正在尝试不同的路线:

I'm trying different routes:


  • / localhost / mysite / home / forms / test

  • / localhost / forms / test (默认网站)

  • /localhost/mysite/home/forms/test
  • /localhost/forms/test (default website)

但到目前为止还没有运气。

But no luck so far.

----更新---

深入研究它,我注意到Sitecore的行为有问题。 TransferRoutedRequest 处理器应该中止 httpRequestBegin 管道,如果上下文项为null,则将控制权交还给MVC。 (简化)。经过一些检查后,它会发生,其中一项是对RoutTable数据的检查。但是对 RouteTable.Routes.GetRouteData 的调用始终返回null,这使处理器返回而不会中断管道。我对其进行了覆盖以使其能够正确地中止管道,但是,即使我调用了方法 args.AbortPipeline(),管道也不会中止并且路由也无法解析。

Going deeper into it, I noticed that there's something wrong with Sitecore's behavior. The TransferRoutedRequest processor is supposed to abort the httpRequestBegin pipeline, giving control back to MVC, in case the context item is null (simplifying). It happens after some checks, among which is one on RoutTable data. But the call to RouteTable.Routes.GetRouteData returns always null, which makes the processor return without aborting the pipeline. I overrode it to make it abort the pipeline correctly, but still, even if I it calls method args.AbortPipeline(), pipeline is not aborted and route not resolved.

这是原始 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);
    }
}


推荐答案

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

Finally I've got it working correctly. As I wrote TransferRoutedRequest wasn't working as expected, so I had to override it. Still, even if it worked as it's supposed to, the route wasn't being resolved. The problem was in the pipeline configuration. Thanks to a colleague I opened SitecoreRocks pipeline tool and it showed the pipeline was registered in a position too far away from where it should have been, so it was never hit (I had registered it after ItemResolver, as it was on the original configuration). I patched it before LayoutResolver and that did the trick. The route was resolved. Still, Sitecore wasn't able to create an instance of the type, as it was in another assembly. Even specifying the controller's namespace didn't solve the problem. So I had to make some modifications and override CreateController method of ControllerFactory class and override InitializeControllerFactory processor (which I already had modified to be able to work with a DI container), writing a new ControllerFactory and a new SitecoreControllerFactory.

最终代码如下:

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 来解析自定义路由。

In case I'm dealing with a Sitecore item, I use TypeHelper to return current controller type from a controller rendering or layout. Otherwise I use DefaultControllerFactory.GetControllerType to resolve the custom route.

唯一需要注意的是:第2种情况或更多名称空间的控制器具有相同的名称和操作,必须添加名称空间才能标识它们。

The only thing to be careful: in case 2 or more namespaces have a controller with the same name and action, it's mandatory to add a namespace in order to identify them.

这篇关于Sitecore,自定义MVC控制器和路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆