Artículo original publicado el martes, 29 de septiembre de 2011

NOTA:  descargue los datos adjuntos para obtener un documento de Word con esta publicación en formato legible por el ojo humano.

Hace poco recibí una solicitud interesante de alguien que deseaba esencialmente poder migrar etiquetas sociales entre dos granjas de servidores diferentes.  Hay algunas cosas listas para usar que pueden ayudarle a lograrlo, y otras que son tentadores, pero no suficientes.

Probé la obtención de las propias etiquetas sociales sin ningún tipo de suplantación “real”.  Me funcionó pero no puedo garantizar que lo haga en todos los casos porque inicié sesión como administrador de UPA.  Si no es así, podría usar la misma técnica de suplantación que describiré a continuación. Para obtener las etiquetas para un usuario, acabo de intentar crear un contexto de SPSite como ese usuario y, a continuación, he tratado de crear todos los objetos de contexto necesarios para recuperar etiquetas para dicho usuario, de la siguiente manera:

SPUserToken sut = null;

//get the user token for user first so we can

//use that to get a site context as that user

using (SPSite userSite = new SPSite(UrlTxt.Text))

{

   using (SPWeb rootWeb = userSite.RootWeb)

   {

       SPUser socialUser =

          rootWeb.EnsureUser(AccountTxt.Text);

       sut = socialUser.UserToken;

   }

}

                

//now get the site as that user – NOTE: these are

//all class scoped variables

using (SPSite newSite = new SPSite(UrlTxt.Text, sut))

{

   sc = SPServiceContext.GetContext(newSite);

   stm = new SocialTagManager(sc);

   upm = new UserProfileManager(sc);

   up = upm.GetUserProfile(AccountTxt.Text);

}

 

Una vez que tengo los contextos que se crearon como el usuario actual, resulta bastante sencillo obtener las etiquetas para dicho usuario:

SocialTag[] tags = stm.GetTags(up);

 

TagLst.Items.Clear();

foreach (SocialTag tag in tags)

{

   TagLst.Items.Add(tag.Term.Name + " - " + tag.Url.ToString());

}

 

Esta parte fue bastante sencilla y fácil.  Escribir una etiqueta social para un usuario diferente no resultó, lamentablemente, tan sencillo.  El SocialTagManager incluye un método AddTag pero no ofrece una sobrecarga que incluye un UserProfile como el método GetTags.  Esto es un duro descuido y, lamentablemente el uso del contexto del usuario que se pasó al nuevo constructor de SPSite no ayuda.  Como resultado, tiene que usar la suplantación para ello.  En este caso acabo de volver usar el enfoque que he descrito en esta publicación – http://blogs.msdn.com/b/sharepoint_sp/archive/2011/10/07/utilizaci-243-n-de-notificaciones-de-saml-claims-sharepoint-wcf-notificaciones-al-servicio-de-token-de-windows-y-delegaci-243-n-restringida-para-acceder-a-sql-server.aspxdelegation-to-access-sql-server.aspx.  He configurado el CTWTS para que permita (puesto que mi aplicación se estaba ejecutando en mi contexto de usuario) suplantar usuarios.  Se describen aquí detalles específicos para ello:  http://msdn.microsoft.com/en-us/library/ee517258.aspx.

De modo que teniendo ese enfoque presente, esta es la manera en que realicé la suplantación primero:

//start the impersonation

//create the WindowsIdentity for impersonation

WindowsIdentity wid = null;

 

try

{

   wid = S4UClient.UpnLogon(EmailTxt.Text);

}

catch (SecurityAccessDeniedException adEx)

{

   MessageBox.Show("Could not map the Email to " +

       "a valid windows identity: " + adEx.Message);

}

 

//see if we were able to successfully login

if (wid != null)

{

   using (WindowsImpersonationContext ctx = wid.Impersonate())

   {

       //code goes here to add a new tag

   }

}

else

{

   MessageBox.Show("Couldn't impersonate user - can't add tag.");

}

 

El propio código de suplantación no es particularmente complejo; solo necesita la dirección de correo electrónico del usuario (que podría obtener probablemente de su UserProfile, que este código recupera).  También necesita el CTWTS en ejecución, que se instala en cada servidor de SharePoint, y este código se tiene que ejecutar en un servidor de SharePoint puesto que usa el modelo de objetos.  Así que de nuevo, esto no debería ser un obstáculo importante.

Por último, la adición de la nueva etiqueta para el usuario requiere hacer algunos malabares pero es bastante administrable.  Este es el aspecto que tiene el código:

//this is the code that gets the SPSite, SPServiceContext, etc

GetServiceContext();

 

//work with the taxonomy classes so we

//can reuse any existing term, or create a

//new one if it doesn't exist

TaxonomySession txs = stm.TaxonomySession;

TermStore ts = txs.DefaultKeywordsTermStore;

 

TermCollection terms =

   ts.KeywordsTermSet.GetTerms(TagTxt.Text,

   ts.DefaultLanguage, true);

 

Term t = null;

 

if (terms.Count == 0)

{

   t = ts.KeywordsTermSet.CreateTerm(TagTxt.Text,

       ts.DefaultLanguage);

       ts.CommitAll();

}

else

   t = terms[0];

 

//add the tag

stm.AddTag(new Uri(TagUrlTxt.Text), t);

 

De modo que lo que ocurre aquí es que acabamos de buscar en el almacén de taxonomía la etiqueta que se está agregando.  Si la encontramos allí, usamos ese término; de no ser así, lo creamos y lo agregamos al almacén de términos.  A continuación, agregamos el término y lo asociamos a una dirección URL y se agrega a las etiquetas sociales de dicho usuario.

En general, el código y el enfoque es bastante sencillo.  El principal problema aquí es justamente trabajar en torno a la incapacidad de especificar a qué usuario se debe agregar una etiqueta social.  El código de suplantación y CTWTS cuida de esa parte por nosotros sin requerir la contraseña para cada usuario.  El código de origen para este proyecto se adjunta a la publicación.

 

Esta entrada de blog es una traducción. Puede consultar el artículo original en Working with Social Tags in SharePoint 2010