将 Sitecore 社交资料更新到外部系统

Updating Sitecore Social Profile into an external system

我们在 Sitecore 7.5 中使用 Sitecore Social Connected Module 3.0 版。从我们登录用户并查看存储在 MongoDb 中的个人资料信息的意义上说,一切都运行良好。但是,需要将配置文件信息也存储到单独的系统中。

我已经通过利用以下社交模块事件成功做到了这一点:

<event name="social:connector:user:loggedin">
</event>
<event name="social:connector:user:socialprofileattached">
</event>

在这些事件中,我使用以下代码读取 MongoDb 并尝试更新我的外部系统中的配置文件:

INetworkManager networkManager = ExecutingContext.Current.IoC.Get<INetworkManager>(new IParameter[0]);
ISocialProfileManager socialProfileManager = ExecutingContext.Current.IoC.Get<ISocialProfileManager>(new IParameter[0]);
string name = networkManager.GetNetwork(new IDIdentifier(ID.Parse(MembershipParameters.LinkedIn_NetworkId))).Name;
SocialProfile socialProfile = socialProfileManager.GetSocialProfile(Tracker.Current.Contact.ContactId.GetIdentifier(), name);

if (!socialProfile.IsEmpty && socialProfile.Fields.Any())
{
    MembershipUtil.UpdateLinkedInPofile(socialProfile);
}

问题是这仅适用于第二次以上的登录尝试。第一次尝试时,socialProfile.Fields 计数始终为 0。似乎代码被调用得太早了。

我真正需要的是 mongo 更新后的事件或管道,以便我可以检索它并更新外部系统。

关于如何实现这一点的任何其他建议显然也将受到欢迎。谢谢

根据我将 MongoDB 与 Sitecore 一起使用的经验,有关用户访问的完整详细信息在会话结束并且一些数据存储在会话中之前不可用。在会话结束时,数据被刷新到 MongoDB。

获取社交数据的更可靠方法可能是使用 AggregationProcessor。此时您可以在此处理器中放入一些代码,将您的社交数据推送到您的外部系统。

namespace MyNamespace.Aggregation
{
    public class MyProcessor: AggregationProcessor
    {
      protected override void OnProcess(AggregationPipelineArgs args)
      {
          //your code
      }
   }
}

然后在配置文件中:

 <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
 <sitecore>
    <pipelines>
        <group groupName="analytics.aggregation">
            <pipelines>
                <interactions>
                    <processor type="Mynamespace.aggregation.MyProcessor, MyDll" />
                </interactions>
            </pipelines>
        </group>
    </pipelines>
</sitecore>

原来我在整个过程中想多了。在反编译器的帮助下,我意识到调用的登录方法接受一个 Callback URL 子布局参数。这是用户在登录后被重定向到的地方,所以我覆盖了登录按钮并在回调 url 中添加了 return url。然后在回调url中调用了我的数据库更新方法

登录代码是从Sitecore.Social.Client.Connector.Controls.LoginButtonBase.Login

反编译而来
protected void NewLogin(string networkName)
{
    var pageUrl = Request["pageUrl"];
    ILoginHelper loginHelper = ExecutingContext.Current.IoC.Get<ILoginHelper>(new IParameter[0]);
    Sublayout parent = this.Parent as Sublayout;
    NameValueCollection nameValueCollection = (parent != null ? WebUtil.ParseUrlParameters(parent.Parameters) : new NameValueCollection());
    Dictionary<string, object> dictionary = nameValueCollection.AllKeys.ToDictionary<string, string, object>((string key) => key, (string key) => nameValueCollection[key]);
    string callbackUrl = string.Empty;
    if (dictionary.ContainsKey("Callback URL") && !string.IsNullOrEmpty((string)dictionary["Callback URL"]))
    {
        try
        {
            try
            {
                callbackUrl = ExecutingContext.Current.IoC.Get<ILinkManager>(new IParameter[0]).GenerateLink(dictionary["Callback URL"].ToString(), string.Empty);
                if (string.IsNullOrEmpty(callbackUrl))
                {
                    ExecutingContext.Current.IoC.Get<ILogManager>(new IParameter[0]).LogMessage(string.Format("Could not parse the '{0}' link value. Context item ID: {1}", dictionary["Callback URL"], (Sitecore.Context.Item != null ? Sitecore.Context.Item.ID.ToString() : "null")), LogLevel.Error, this);
                }
                else if (!string.IsNullOrEmpty(callbackUrl) && !string.IsNullOrEmpty(pageUrl))
                {
                    callbackUrl += string.Format("?pageurl={0}", pageUrl);
                }
            }
            catch (Exception exception1)
            {
                Exception exception = exception1;
                ExecutingContext.Current.IoC.Get<ILogManager>(new IParameter[0]).LogMessage(string.Format("Could not parse the '{0}' link value. Context item ID: {1}", dictionary["Callback URL"], (Sitecore.Context.Item != null ? Sitecore.Context.Item.ID.ToString() : "null")), LogLevel.Error, this, exception);
            }
        }
        finally
        {
            dictionary.Remove("Callback URL");
        }
    }
    if (string.IsNullOrEmpty(callbackUrl))
    {
        callbackUrl = base.Request.Url.ToString();
    }
    loginHelper.Login(networkName, false, dictionary, callbackUrl);
}

此处有一条重要说明。下一行中的第二个参数指示配置文件是否应异步更新。如果此项设置为 true,那么当您点击回调 url 时,配置文件可能仍然不可用。将其设置为 false 可确保 MongoDB 记录中的 UserProfile 对象已更新并在回调页面上可供我使用。这自然是有成本的。

loginHelper.Login(networkName, false, dictionary, callbackUrl);

在回调 url 着陆页中调用:

INetworkManager networkManager = ExecutingContext.Current.IoC.Get<INetworkManager>(new IParameter[0]);
ISocialProfileManager socialProfileManager = ExecutingContext.Current.IoC.Get<ISocialProfileManager>(new IParameter[0]);
string name = networkManager.GetNetwork(new IDIdentifier(Sitecore.Data.ID.Parse(MembershipParameters.LinkedIn_NetworkId))).Name;
if (Tracker.Current != null)
{
    SocialProfile socialProfile =
        socialProfileManager.GetSocialProfile(Tracker.Current.Contact.ContactId.GetIdentifier(),
            name);

    if (!socialProfile.IsEmpty && socialProfile.Fields.Any())
    {
        MembershipUtil.UpdateLinkedInPofile(socialProfile);
    }
}