Обновление Социального профиля 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>