SharePoint 2010: Limitaciones en las soluciones Sandbox (II)!

Como continuación al primer post sobre limitaciones en las soluciones SandBox en cuanto a que tipo de artefactos se pueden crear y el ámbito a nivel de desarrollo en el que nos podemos mover (Colección de Sitios hacia abajo), en esta ocasión quería entrar en un poco más de detalle en estas limitaciones teniendo en cuenta el modelo de ejecución de las soluciones SandBox. Básicamente, todo el código que corre dentro del servicio de SandBox está sujeto a una serie de restricciones tanto de ejecución como de acceso. Hay dos sistemas de restricciones:

  • Uno que se aplica únicamente a toda llamada que se realice a cualquier ensamblado exceptuando Microsoft.SharePoint.dll.
  • Otra que se aplica únicamente a toda llamada que se realice al modelo de objetos SharePoint incluido en Microsoft.SharePoint.dll y otros ensamblados como Microsoft.SharePoint.Linq.dll.

Request processing model in sandboxed solutions

¿Cómo se aplican estas restricciones? Para el primer tipo de llamadas a ensamblados, se definen dos mecanismos:

  • Una política muy restrictiva de seguridad de acceso a código (CAS) que se encarga de limitar lo que el código ejecutándose en el proceso de SandBox puede hacer (Nota: Esta política si permite acceder a ensamblados de Microsoft Office con un “strong-named”). Esta política se encuentra definida en el archivo web.config bajo la ruta %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\CONFIG,  impone restricciones como:

image

    • La imposibilidad de llamar a código no manejado desde el código de una solución SandBox.
    • La imposibilidad de llamar a las APIS de reflexión de .NET Framework 3.5 desde el código de una solución SandBox.
    • La condición de que para poder llamar desde código de una solución SandBox a ensamblados de .NET Framework 3.5 se necesita que tengan el atributo AllowPartiallyTrustedCallersAttribute.
   1: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

   2: <configuration>

   3:   <system.web>

   4:       <httpModules>

   5:          <clear/>

   6:       </httpModules>

   7:     <httpHandlers>

   8:       <add path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" validate="true"/>

   9:     </httpHandlers>

  10:     <securityPolicy>

  11:       <trustLevel name="WSS_Sandbox" policyFile="..\config\wss_usercode.config" />

  12:     </securityPolicy>

  13:     <trust level="WSS_Sandbox" originUrl="" />

  14:   </system.web>

  15:   <runtime>

  16:     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

  17:       <probing privatePath="assemblies" />

  18:       <dependentAssembly>

  19:         <assemblyIdentity name="Microsoft.SharePoint" publicKeyToken="71e9bce111e9429c" culture="neutral" />

  20:         <bindingRedirect oldVersion="0.0.0.0-14.900.0.0" newVersion="14.900.0.0" />

  21:       </dependentAssembly>

  22:     </assemblyBinding>

  23:   </runtime>

  24: </configuration>

  • A través de un token de seguridad con privilegios mínimos que impide que el worker process del servicio de SandBox:
    • Tenga permisos para leer o escribir en el sistema de archivos.
    • Tenga permisos para realizar llamadas a la red, de forma que solo se pueden acceder a recursos disponibles en el servidor dónde se está ejecutando el proceso.
    • Tenga permisos para escribir en el registro.
    • Tenga permisos para llamar a cualquier ensamblado que no esté en la GAC, incluso aunque disponga del atributo AllowPartiallyTrustedCallersAttribute.

Para el segundo sistema de restricciones, se define una versión “shim” del MO de servidor de SharePoint que junto con el MO completo son cargados por uno de los dos procesos que constituyen el servicio de SandBox (en concreto por SPUCWorkerProcessProxy.exe) que impiden que se llamen a objetos de la API no permitidos desde una solución SandBox. Además, existen otros dos ensamblados que son usados por este sistema y que se cargan en el Worker Process del servicio de SandBox (Microsoft.SharePoint.UserCode.dll) y en el proxy comentado (Microsoft.SharePoint.SubsetProxy.dll). El mecanismo de uso de estos ensamblados “shim” por los procesos del servicio de SandBox es el siguiente:

  • Cuando una solución SandBox hace uso de un parte permitida de la API de SharePoint, el primero de los ensamblados pasa la llamada al segundo en el proceso de proxy, que a su vez la pasa a la API estándar en Microsoft.SharePoint.dll.
  • Los resultados de la llamada realizad se pasan al código original que la realizó.

Como ejemplo de restricción en cuanto al uso del MO de SharePoint tenemos:

  • No se puede acceder a la clase SPWebApplication ni a cualquiera definida bajo Microsoft.SharePoint.Administration.
  • No es posible realizar una elevación de privilegios en el código que se ejecute en modo SandBox.
  • No se pueden usar los controles definidos en Microsoft.SharePoint.WebControls de manera que estamos restringidos al uso de controles ASP.NET.

El listado completo de APIs dentro de Microsoft.SharePoint.dll que se pueden usar lo podéis encontrar aquí Microsoft.SharePoint.dll APIs Available from Sandboxed Solutions. Finalmente, otra limitación ya comentada en este blog es que a nivel de despliegue de una solución SadnBox está prohibido incluir cualquier tipo de archivo que se tenga que copiar en el servidor físico como controles de usuario, páginas de aplicación, o imágenes. Para más información recomendable ver SharePoint Deployment Models.

Anuncios

SharePoint 2010: Alternativas para montar el entorno de desarrollo (II)!

Siguiendo con la serie de post sobre alternativas para montar el entorno de desarrollo para SharePoint 2010, en esta ocasión voy a comentar otra posibilidad que tenemos dentro del movimiento de irnos “todos a la nube” Guiño…esta alternativa implica que nuestro entorno de desarrollo esté disponible en algún proveedor de servicios en la nube como puede ser Arsys en España, Amazon como ya nos ha explicado Mario Cortes o en la propia plataforma Azure de Microsoft …aunque en este post no voy a tratar este caso, sino que voy a hablaros de Cloudshare que es plataforma de cloud computing en modo autoservicio que facilita la creación de entornos virtuales para realizar demostraciones, pruebas de concepto o incluso formaciones…todo depende del tipo de suscripción adquirida. En mi caso, he tenido la suerte de poder contar con una invitación para usar Cloudshare Pro que facilita la creación rápida de estos entornos virtuales ya sean limpios o en base a plantillas predefinidas:

  • Crear un entorno es tan sencillo como pulsar el botón “Create new environment”. La licencia Pro sólo permite crear un entorno, pero en él podemos disponer de varias máquinas virtuales y crear snapshots del entorno para compartir con terceros…de hecho, disponemos de nada menos que 1.000 invitaciones que permiten usar los snapshots creados por un período de 48 horas…cool.
  • A la hora de crear una máquina virtual en el entorno, tenemos varias plantillas disponibles. Entre ellas una para SharePoint 2010 Sonrisa.
  • Una vez definido el entorno, basta con pulsar el botón View Environment para que las máquinas virtuales se arranquen. Estas máquinas las podremos acceder desde el explorador o bien por escritorio remoto Sonrisa
image image image
  image  

Por supuesto, podremos editar el entorno en todo momento y añadirle nuevas máquinas virtuales.

image

WSS 3.0 & MOSS: Compatibilidad de Office 2010!

El otro día planteaban en los foros de SharePoint un problema sobre la integración entre SharePoint 2007 (WSS 3.0 & MOSS) y Office 2010…la verdad, cuando ví el thread tampoco me sorprendí mucho en cuanto a que Office 2010 es una versión superior a las que soporta SharePoint 2007, aunque no debería dar ningún problema en cuanto a que Office 2010 es una evolución de Office 2007. Sin embargo, la integración es diferente como podéis ver en este thread. Por eso, cuando surja la duda sobre como se integra Office 2010 con SharePoint 2007 lo mejor es bajarse el siguiente documento creado por Microsoft en el que podemos ver que se soporta y que no en SharePoint 2010 en función de si trabajamos con Office 2010 u Office 2007 y extrapolarlo al uso de Office 2010 en SharePoint 2007.

SharePoint 2010: Añadiendo acciones personalizadas en la interfaz de usuario (VII)!

Siguiendo con la serie de posts en torno a como añadir acciones personalizadas a la interfaz de usuario, en esta ocasión os quería mostrar las posibilidades que tenemos a la hora de extender las distintas partes que constituyen la Ribbon mediante nuevas pestañas, grupos de acciones, acciones y controles, así como la lógica necesaria para dotar de funcionalidad a estas extensiones. En este sentido, y mejor que repetir lo que ya se ha comentado en torno a este tema en la red, os recomiendo este excelente artículo de MSDN escrito por Andrew Connell:Customizing and Extending the SharePoint 2010 Server Ribbon. Finalmente, os dejo el resto de posts de la serie:

SharePoint2010_thumb

SharePoint 2010: Limitaciones en campos proyectados al hacer Joins!

Como sabéis, una de las novedades que incorpora SharePoint 2010 es la posibilidad de hacer Joins en las consultas que hagamos a listas que están relacionadas mediante campos de lookup con otras listas. Este soporte es posible gracias a la actualización del esquema CAML subyacente, de forma que podemos incorporar Joins a nuestras consultas ya sea en CAML o utilizando LINQ To SharePoint (el proveedor se encarga de generar el código correspondinte). Así por ejemplo:

  • En el caso de usar un objeto SPQuery, podemos definir un Join en CAML de la siguiente forma (en este caso tenemos una lista Projects que está relacionada mediante un campo de lookup con la lista Employees…el ejemplo está tomado del Training Kit de desarrollo de SharePoint 2010):
   1: using (SPSite siteCollection = new SPSite("http://demo2010a:100"))

   2: {

   3:     SPList list = siteCollection.RootWeb.Lists["Projects"];

   4:  

   5:     SPQuery query = new SPQuery();

   6:     query.Joins =

   7:         @"

   8:         <Join Type='LEFT' ListAlias='Primary_x0020_Contact'><!--List Name: Employees-->

   9:             <Eq>

  10:                 <FieldRef Name='Primary_x0020_Contact' RefType='ID' />

  11:                 <FieldRef List='Primary_x0020_Contact' Name='ID' />

  12:             </Eq>

  13:         </Join>

  14:         ";

  15:     query.ProjectedFields =

  16:         @"

  17:         <Field Name='Primary_x0020_ContactTitle' Type='Lookup' List='Primary_x0020_Contact' ShowField='Title' />

  18:         <Field Name='Primary_x0020_ContactJobTitle' Type='Lookup' List='Primary_x0020_Contact' ShowField='JobTitle' />

  19:         ";

  20:     query.ViewFields =

  21:         @"

  22:         <FieldRef Name='Title' />

  23:         <FieldRef Name='Primary_x0020_ContactTitle' />

  24:         <FieldRef Name='Primary_x0020_ContactJobTitle' />

  25:         ";

  26:     query.Query =

  27:         @"

  28:         <Where>

  29:             <Eq>

  30:                 <FieldRef Name='Primary_x0020_ContactTitle' /><Value Type='Lookup'>Contact1</Value>

  31:             </Eq>

  32:         </Where>

  33:         ";

  34:     Console.WriteLine("CAML Query sent");

  35:     Console.WriteLine(query.ViewXml.ToString());

  36:     Console.ReadLine();

  37:     Console.WriteLine("Query results");

  38:     SPListItemCollection results = list.GetItems(query);

  39:     foreach (SPListItem item in results)

  40:     {

  41:         Console.WriteLine("{0} - {1} - {2}",

  42:             item["Title"].ToString(),

  43:             item["Primary_x0020_ContactTitle"].ToString(),

  44:             item["Primary_x0020_ContactJobTitle"].ToString());

  45:     }

  46: }

  • Como veis, el objeto SPQuery incorpora dos nuevas propiedades:
    • Joins, que permite definir el join o joins en la consulta.
    • ProjectedFields, que permite incorporar en los resultados devueltos campos proyectados, es decir, campos que están en la lista relacionada con la lista principal. En este caso estamos devolviendo dos campos de la lista Employees.
  • En el caso de usar LINQ To SharePoint, el uso de Joins es mucho más intuitivo. Por ejemplo:
   1: try

   2: {

   3:     SPLINQProxySiteDataContext ctx =

   4:         new SPLINQProxySiteDataContext(SPContext.Current.Web.Url);

   5:     var productsList = from p in ctx.Productos

   6:                        select new

   7:                        {

   8:                            Producto = p.Título,

   9:                            Descripcion = p.Descripción,

  10:                            Fabricante = p.Fabricante.Título

  11:                        };

  12:     ctx.Log = swWriter;

  13:     grdProductos.DataSource = productsList;

  14:     grdProductos.DataBind();

  15:     txtConsultaCAML.Text = "Consulta: " +

  16:         swWriter.ToString();

  17: }

  18: catch (Exception ex)

  19: {

  20:     txtError.Text = ex.Message;

  21: }

  • En  este caso, tras definir una instancia del objeto DataContext correspondiente, estamos haciendo una consulta a la lista Productos que está relacionada con la lista Empresas mediante el campo de lookup Fabricante. En el select realizado estamos consultando dos campos de la lista Productos y uno de la lista Empresas por lo que el proveedor de LINQ To SharePoint generará por nosotros el correspondiente Join (lo podemos ver con ctx.log=swWriter):
   1: <View>

   2:     <Query>

   3:         <Where>

   4:             <BeginsWith>

   5:                 <FieldRef Name="ContentTypeId" />

   6:                     <Value Type="ContentTypeId">0x0100</Value>

   7:             </BeginsWith>

   8:         </Where>

   9:     </Query>

  10:     <ViewFields>

  11:         <FieldRef Name="Title" />

  12:         <FieldRef Name="Descripci_x00f3_n" />

  13:         <FieldRef Name="FabricanteTitle" />

  14:     </ViewFields>

  15:     <ProjectedFields>

  16:         <Field Name="FabricanteTitle" Type="Lookup" List="Fabricante" ShowField="Title" />

  17:         </ProjectedFields>

  18:     <Joins>

  19:         <Join Type="LEFT" ListAlias="Fabricante">

  20:         <!--List Name: Empresas-->

  21:             <Eq>

  22:                 <FieldRef Name="Fabricante" RefType="ID" />

  23:                 <FieldRef List="Fabricante" Name="ID" />

  24:             </Eq>

  25:         </Join>

  26:     </Joins>

  27:     <RowLimit Paged="TRUE">2147483647</RowLimit>

  28: </View>

  • Finalmente, y después de tanto “rollo”, la respuesta a las preguntas que dan título al post:
    • ¿Cuántos Joins podemos tener? La respuesta es que el umbral tope definido (por aplicación web) por defecto es de 8 como podéis consultar en este enlace:http://technet.microsoft.com/en-us/library/cc262787.aspx. Este es el umbral que se fija en la administración central y que se puede sobreescribir ya que no es un valor límite, aunque si el máximo recomendado sin penalizar el rendimiento. Si se intenta realizar una consulta que implique superar este número de Joins por defecto, la consulta se bloqueará y se generará la correspondiente excepción. En este thread de los foros de MSDN podéis encontrar un caso en el que se pudo configurar el uso de 13 Joins antes de obtener la excepción: http://social.msdn.microsoft.com/Forums/en-US/sharepoint2010general/thread/f48f36f8-108f-4ac8-a5d6-c347b7adb5ce. En lo que a realizar consultas simples, sin Joins, SharePoint devolverá en este caso hasta un máximo de 8 campos de lookup.
    • ¿Se pueden hacer Joins con cualquier tipo de campo? La respuesta es que no. Por ejemplo, no se permite hacer un Join con campos que no tienen sentido como los de texto enriquecido.

SharePoint: Resumen de posts publicados sobre publicación de formularios InfoPath!

Últimamente en los foros de SharePoint se están planteando bastantes dudas en torno a la publicación de formularios InfoPath en SharePoint por lo que me ha parecido adecuado recoger los posts al respecto publicados en este blog:

SharePoint 2010: Personalización con temas (IV)!

Siguiendo con la serie de posts sobre la personalización de sitios de SharePoint 2010 usando el nuevo motor de temas que incorpora la plataforma y las posibilidades para crear y aplicar temas, en esta ocasión os voy a presentar otra alternativa para crear temas para SharePoint 2010. Pero antes, os recuerdo los posts publicados en torno a esta temática hasta ahora:

Como decía, una alternativa interesante que me he encontrado hace poco para crear estos temas la podéis ver en este post: Working with SharePoint 2010 Themes (Anweshi Deverasetty). Lo interesante de este post es el uso de la utilidad Theme Builder para crear esos temas y por supuesto el despliegue y aplicación de temas usando Visual Studio 2010: