Orchard Tokens - >

时间:2013-04-23 09:27:46

标签: orchardcms

我对Orchard Token Providers感到头疼,任何帮助都会是一种祝福。 我大部分都在复制评论代币。

目标是在发布“问题”内容项时发送电子邮件。

以下是我对内容类型'问题'的解决方案:

public interface ITokenProvider : IEventHandler
{
    void Describe(dynamic context);
    void Evaluate(dynamic context);
}

public class QuestionTokens : ITokenProvider

{
    public QuestionTokens()
    {
        T = NullLocalizer.Instance;
    }
public Localizer T { get; set; }

public void Describe(dynamic context)
{
    //presume this is correct 
    context.For("Content", T("Content Items"), T("Content Items"))
        .Token("QuestionText", T("Question Text"), T("Text of the question"))
        .Token("QuestionAuthor", T("Question Author"), T("Author of the question"));
    //presume this is incorrect? correct for the content type?
    context.For("Question", T("Questions"), T("Questions from users"))
        .Token("QuestionText", T("Question Text"), T("Text of the question"))
        .Token("QuestionAuthor", T("Question Author"), T("Author of the question"));
}

public void Evaluate(dynamic context)
{

    Func<IContent, object> questionTextAccessorFromContent = (content) => { 
        var part = content.As<QuestionPart>();
        return part.QuestionText; 
    };

    Func<QuestionPart, object> questionTextAccessor = (part) =>
    {
        return part.QuestionText;
    };

    Func<IContent, object> authorAccessorFromContent = (content) => { 
        var part = content.As<QuestionPart>();
        return part.Author; 
    };

    Func<QuestionPart, object> authorAccessor = (part) =>
    {
        return part.Author;
    };

    //doesnt work 
    context.For<IContent>("Content")
        .Token("QuestionText", (Func<IContent, object>)
    (content => content.As<QuestionPart>().Record.QuestionText))
        .Token("QuestionAuthor", (Func<IContent, object>)
    (content => content.As<QuestionPart>().Record.Author));
    //doesnt work 
    context.For<IContent>("Question")
        .Token("QuestionText", (Func<IContent, object>)
    (content => content.As<QuestionPart>().Record.QuestionText))
        .Token("QuestionAuthor", (Func<IContent, object>)
    (content => content.As<QuestionPart>().Record.Author));
    //doesnt work 
    context.For<QuestionPart>("Question")
        .Token("QuestionText", (Func<QuestionPart, object>)
    (content => content.Record.QuestionText))
        .Token("Author", (Func<QuestionPart, object>)
    (content => content.Record.Author)); ;
}

private static string QuestionText(IContent question) 
{
    var questionPart = question.As<QuestionPart>();
    return questionPart.QuestionText;
}

private static string Author(IContent question) 
{
    var questionPart = question.As<QuestionPart>();
    return questionPart.Author;
}

}

这是行动(当问题发布时),它会发送一封包含正文的电子邮件: (更新以测试Medeiros的建议)

<p>A question has been created by: {Content.QuestionAuthor}</p>
<p>A question has been created by: {Content.QuestionAuthor.Text}</p>
<p>A question has been created by: {Content.QuestionAuthor.Value}</p>
<p>A question has been created by: {Question.QuestionAuthor}</p>
<p>A question has been created by: {Question.QuestionAuthor.Text}</p>
<p>A question has been created by: {Question.QuestionAuthor.Value}</p>
<p>Message: {Content.QuestionText}</p>
<p>Message: {Content.QuestionText.Text}</p>
<p>Message: {Content.QuestionText.Value}</p>
<p>Message: {Question.QuestionText}</p>
<p>Message: {Question.QuestionText.Text}</p>
<p>Message: {Question.QuestionText.Value}</p>

所有“我的”代币都替换为空白文本。其他令牌如:{Content.ContentType} {User.Email}工作得很好。任何人注意到的任何错误或提示都将非常有用。

谢谢,马特

3 个答案:

答案 0 :(得分:1)

IVe重写了令牌提供程序,它有点......(现在完全可以工作)

public class QuestionTokens : Orchard.Tokens.ITokenProvider
{
    private readonly IContentManager contentManager;
    private readonly IWorkContextAccessor workContextAccessor;

    public QuestionTokens(IContentManager contentManager, IWorkContextAccessor workContextAccessor)
    {
        this.workContextAccessor = workContextAccessor;
        this.contentManager = contentManager;
        T = NullLocalizer.Instance;
    }

    public Localizer T { get; set; }

    /// <summary>
    /// Describes the specified context.
    /// </summary>
    /// <param name="context">The context.</param>
    public void Describe(DescribeContext context)
    {
        context.For("Content", T("Content Items"), T("Content Items"))
            .Token("QuestionText", T("Question Text"), T("Text of the question"))
            .Token("QuestionAuthor", T("Question Author"), T("Author of the question"));
    }

    /// <summary>
    /// Evaluates the specified context.
    /// </summary>
    /// <param name="context">The context.</param>
    public void Evaluate(EvaluateContext context)
    {
        context.For<IContent>("Content")
            .Token("QuestionText", content => QuestionText(content, context))
            .Token("QuestionAuthor", content => Author(content, context));
    }

    private string QuestionText(IContent question, EvaluateContext context) 
    {
        var questionPart = question.As<QuestionPart>();
        return questionPart.QuestionText;
    }

    private string Author(IContent question, EvaluateContext context) 
    {
        var questionPart = question.As<QuestionPart>();
        return questionPart.Author;
    }

}

我现在可以至少在私人QuestionText和Author方法中调试代码。由于在控制器中触发此行时发布的事件触发,因此检索到的值为“null”: services.ContentManager.Create( “问题”);

因此尚未填充内容项,并且“已发布”事件在其生命开始之前就已触发。是时候玩它的内容类型设置,看看是否有所作为......

最后所有工作都需要。事件部分'发布'事件仍在发生,当我不期望它,所以我改变了内容的生命。

从控制器:(某些代码已删除,因此我没有发布更多代码)

var item = services.ContentManager.New<Models.QuestionPart>("Question");
this.TryUpdateModel(item);
services.ContentManager.Create(item.ContentItem); //where the event is firing  
Services.ContentManager.Publish(item.ContentItem); //where i expected the event to fire :) 

最初是创建,更新和保存。但事件限制了这一点。所以现在它是新的,更新和创建。 至于代币。它们很简单: {Content.QuestionAuthor}和{Content.QuestionText}。当一切正常时,一切都是正确的,很简单。

答案 1 :(得分:0)

Matthew,尝试为:{Content.QuestionAuthor.Value}

添加.Value

如果这不起作用,请尝试.Text。

希望这有帮助。

答案 2 :(得分:0)

原始问题中的代码看起来很准确。您遵循正确的Orchard Events总线约定,即创建继承自IEventHandler link的接口。

您对控制器代码的更改可能是您获得值的原因。我调试代码的经验是,它取决于您的规则订阅的事件。例如,“Content Created”类型的事件在Evaluate方法中命中调试器,但所有自定义零件属性都为null。但是,“当提交自定义表单时”的事件会命中并填充值。

我花了一整天的时间对我的代码进行故障排除,看起来与上面的类似,直到我开始在我的规则中测试其他事件类型,它才在私有函数中填充了数据。

这是我的代码:

public interface ITokenProvider : IEventHandler
{
  void Describe(dynamic context);
  void Evaluate(dynamic context);
}

public class PersonTokens : ITokenProvider
{
  private readonly IContentManager _contentManager;

  public Localizer T { get; set; }

  public PersonTokens(IContentManager contentManager)
  {
    _contentManager = contentManager;
    T = NullLocalizer.Instance;
  }
  public void Describe(dynamic context)
  {
    context.For("Content", T("Content Items"), T("Content Items"))
      .Token("FirstName", T("First Name"), T("The Person's First Name"))
      .Token("LastName", T("Last Name"), T("The Person's Last Name"))
      .Token("EmailAddress", T("Email Address"), T("The Person's Email Address"))
      .Token("PhoneNumber", T("Phone Number"), T("The Person's Phone Number"));
  }

  public void Evaluate(dynamic context)
  {
    // Orchard.Tokens.Implementation.TokenManager.EvaluateContextImpl
    context.For<IContent>("Content")
      .Token("FirstName", (Func<IContent, object>)FirstName)
      .Token("LastName", (Func<IContent, object>)(content => content.As<PersonPart>().Record.LastName))
      .Token("EmailAddress", (Func<IContent, object>)(content => content.As<PersonPart>().EmailAddress))
      .Token("PhoneNumber", (Func<IContent, object>)PhoneNumber); // left the PhoneNumber out of sample
  }

  private string FirstName(IContent person)
  {
    var personPart = person.As<PersonPart>();
    return personPart.Record.FirstName;
  }
}