如何更改管道中的RenderingContext?

时间:2016-01-06 11:09:11

标签: c# sitecore sitecore-mvc

我需要一个管道来拦截sitecore RenderingContext的构建,特别是我需要动态更改RenderingContext.Current.Rendering.DataSource属性。

我需要这样做,因为我在sitecore的数据源中添加了一个变量。我在控制器中操作它,但当我打开体验编辑器时,它甚至在它击中我的控制器之前就会崩溃。我猜测需要更高的数据源才能生效。

1 个答案:

答案 0 :(得分:1)

经过一番挖掘后,我发现了这条管道:

namespace Sitecore.Mvc.Pipelines.Response.RenderRendering
{
    public class EnterRenderingContext : RenderRenderingProcessor
    {
        public override void Process(RenderRenderingArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            if (args.Rendered)
            {
                return;
            }
            this.EnterContext(args.Rendering, args);
        }

        protected virtual void EnterContext(Rendering rendering, RenderRenderingArgs args)
        {
            IDisposable item = RenderingContext.EnterContext(rendering);
            args.Disposables.Add(item);
        }
    }
}

反映出Sitecore.Mvc.dll

我现在可以用自己的管道替换这个管道,并在构建之前更改RenderingContext的值:

public class RedrowEnterRenderingContext : Sitecore.Mvc.Pipelines.Response.RenderRendering.EnterRenderingContext
{
    private const string _developmentKeyword = "$development";

    private IDevelopmentQueryServiceV2 _coUkDevelopmentQueryService = ServiceLocator.Current.GetInstance<IDevelopmentQueryServiceV2>();


    protected override void EnterContext(Rendering rendering, RenderRenderingArgs args)
    {

        //Make your changes to the items that are used to build the context here
        if (args.PageContext != null &&
            args.PageContext.Item != null &&
            args.Rendering.DataSource.Contains(_developmentKeyword) &&
            args.PageContext.Item.TemplateID.Guid == TemplateIdConst.V2Development)
        {

            args.Rendering.DataSource = args.Rendering.DataSource.Replace(_developmentKeyword, 
                args.PageContext.Item.Paths.Path);
        }
        //build the context using the existing functionality
        base.EnterContext(rendering, args);
    }
}

我正在操纵特定场景中的数据源,但是这段代码可以用来做很多工作。

你这样注册:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <mvc.renderRendering>
        <processor type="Namespace.MyEnterRenderingContext, DLLName"
                   patch:instead="*[@type='Sitecore.Mvc.Pipelines.Response.RenderRendering.EnterRenderingContext, Sitecore.Mvc']"/>
      </mvc.renderRendering>
    </pipelines>
   </sitecore>
</configuration>

这方面的一个问题是它出现在BrokenLinkValidator中。您可以覆盖它并创建自己的:

[Serializable]
public class MyBrokenLinksValidator : BrokenLinkValidator
{
    public RedrowBrokenLinksValidator() : base()
    {

    }

    public RedrowBrokenLinksValidator(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context)
    {
    }

    protected override ValidatorResult Evaluate()
    {
        ValidatorResult returnVal = base.Evaluate();
        if (returnVal != ValidatorResult.Valid)
        {
            Item obj = base.GetItem();
            ItemLink[] brokenLinks = obj.Links.GetBrokenLinks(false);
            //are all the broken links basically because they are contextual?
            if (brokenLinks.All(a => a.TargetPath.Contains("$development")))
            {
                foreach (ItemLink brokenLink in brokenLinks)
                {
                    Database database = Sitecore.Configuration.Factory.GetDatabase("master");
                    //try again but replacing the varible with a context
                    var secondTryPath = brokenLink.TargetPath.Replace(
                        "$development", obj.Paths.Path);

                    Item secondTryItem = database.GetItem(secondTryPath);
                    if (secondTryItem == null)
                        return returnVal;
                }

                //if we've got here then all the links are valid when adding the context
                return ValidatorResult.Valid;
            }
        }

        return returnVal;
    }
}