Обновление Социального профиля Sitecore во внешнюю систему

Мы используем Sitecore Social Connected Module версии 3.0 с Sitecore 7.5. Все работает нормально, в том смысле, что мы регистрируем пользователя и видим информацию профиля, сохраненную в 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 count всегда 0. Кажется, что код вызывается слишком рано.

Что мне действительно нужно, так это событие или конвейер ПОСЛЕ того, как Монго было обновлено, чтобы я мог получить его и обновить внешнюю систему.

Любые другие предложения о том, как этого добиться, также приветствуются. Благодарю.

2 ответа

Решение

Оказывается, я обдумывал весь процесс. С помощью декомпилятора я понял, что вызываемые методы входа в систему принимают Callback URL параметр подслоя. Это место, куда пользователь перенаправляется после входа в систему, поэтому я переписал кнопку входа в систему и добавил URL-адрес возврата в 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 гарантирует, что UserProfile объект в записи MongoDB был обновлен и доступен для меня на странице обратного вызова. Естественно, это связано с расходами.

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);
    }
}

По моему опыту использования 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>

Другие вопросы по тегам