Para aquellos que no estén familiarizados con linq 2 sharepoint, os recomiendo este link con un sencillo “Get Started”:
Como veréis en el link, se hace referencia a la herramienta de SharePoint SPMetal, que nos permite sacar entidades tipadas de nuestras listas de SharePoint (similar a lo que hace Entity Framework con una base de datos).
Ahora bien, si intentamos lanzar la herramienta SPMetal contra un site de Office 365, veremos que nos dará un error de acceso denegado, a pesar de haber utilizado los comandos de useremoteapi, user y password
Al parecer, según comentan los ingenieros de MS del foro de soporte de Office 365, la herramienta SPMetal no está diseñada para funcionar con sitios de SharePoint Online.
Sin embargo, Linq to SharePoint sí está soportado en desarrollos sandbox, tal y como podemos ver en este enlace: http://msdn.microsoft.com/en-us/library/hh147180.aspx
La pena es que sin SPMetal, tiene poca utilidad.
Si tenéis mucho interés en utilizar linq2sp en vuestros desarrollos para Office 365, y disponéis de algún servidor SharePoint on-premise, podéis utilizar un sencillo truco para hacerlo.
Lo que yo he hecho (sólo por probar si era viable. no he hecho nada serio), ha sido:
- Crear una lista en mi SharePoint Online. Ejm. Products
- Guardamos esa lista como plantilla y la exportamos a nuestro sitio de SharePoint on premise.
- Desde SharePoint On Premise, ejecutamos SPMetal, y usamos el parámetro /parameters que nos permite pasarle un fichero XML con un esquema predefinido que permite configurar mucho la forma en que SPMetal genera las clases desde las listas. Esto nos ayudará a generar código sobre las listas o tipos de contenido que nos interese, evitando posibles problemas de tipos entre el sitio completo de Office 365 y el de OnPremise. Yo he utilizado el siguiente fichero XML, para generar el código únicamente de la Lista de Products
1 |
<span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff"><?</span><span style="color: #800000">xml</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="1.0"</span> <span style="color: #ff0000">encoding</span><span style="color: #0000ff">="utf-8"</span>?<span style="color: #0000ff">></span> |
1 |
<span style="color: #606060" id="lnum2"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">Web</span> <span style="color: #ff0000">AccessModifier</span><span style="color: #0000ff">="Internal"</span> <span style="color: #ff0000">xmlns</span><span style="color: #0000ff">="http://schemas.microsoft.com/SharePoint/2009/spmetal"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #606060" id="lnum3"> 3:</span> <span style="color: #0000ff"><</span><span style="color: #800000">List</span> <span style="color: #ff0000">Name</span><span style="color: #0000ff">="Products"</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff"><</span><span style="color: #800000">ContentType</span> <span style="color: #ff0000">Name</span><span style="color: #0000ff">="Item"</span> <span style="color: #ff0000">Class</span><span style="color: #0000ff">="Product"</span> <span style="color: #0000ff">/></span> |
1 |
<span style="color: #606060" id="lnum5"> 5:</span> <span style="color: #0000ff"></</span><span style="color: #800000">List</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff"><</span><span style="color: #800000">ExcludeOtherLists</span><span style="color: #0000ff">></</span><span style="color: #800000">ExcludeOtherLists</span><span style="color: #0000ff">></span> |
1 |
<span style="color: #606060" id="lnum7"> 7:</span> <span style="color: #0000ff"></</span><span style="color: #800000">Web</span><span style="color: #0000ff">></span> |
- SPMetal detectará posibles dependencias entre tipos de contenido, y añadirá todo lo necesario para generar las entidades a partir de la lista Products, como por ejemplo, incluyendo una entidad para el tipo de contenido “Item”, ya que la lista de products hereda de ese tipo de contenido.
- Una vez generado el fichero de código, ya lo podemos añadir a nuestra solución de usuario en Visual Studio y probarlo.
- Para las pruebas, he creado un webpart visual en modo sandbox, con 2 botones que ejecutan una sencilla consulta LINQ y sacan ítems de la lista Products.
- Este es el código utilizado:
1 |
<span style="color: #606060" id="lnum1"> 1:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">void</span> btnShowAll_Click(<span style="color: #0000ff">object</span> sender, EventArgs e) |
1 |
<span style="color: #606060" id="lnum2"> 2:</span> { |
1 |
<span style="color: #606060" id="lnum3"> 3:</span> Label1.Text = String.Empty; |
1 |
<span style="color: #606060" id="lnum4"> 4:</span> <span style="color: #0000ff">using</span> (LinqcodeDataContext context = <span style="color: #0000ff">new</span> LinqcodeDataContext(SPContext.Current.Web.Url)) |
1 |
<span style="color: #606060" id="lnum5"> 5:</span> { |
1 |
<span style="color: #606060" id="lnum6"> 6:</span> <span style="color: #0000ff">foreach</span> (var product <span style="color: #0000ff">in</span> context.Products) |
1 |
<span style="color: #606060" id="lnum7"> 7:</span> { |
1 |
<span style="color: #606060" id="lnum8"> 8:</span> <span style="color: #0000ff">string</span> productInfo = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"Title: {0} - {1} <br />"</span>, product.Title, product.Description); |
1 |
<span style="color: #606060" id="lnum9"> 9:</span> Label1.Text += productInfo; |
1 |
<span style="color: #606060" id="lnum10"> 10:</span> } |
1 |
<span style="color: #606060" id="lnum11"> 11:</span> } |
1 |
<span style="color: #606060" id="lnum12"> 12:</span> } |
1 |
<span style="color: #606060" id="lnum13"> 13:</span>  |
1 |
<span style="color: #606060" id="lnum14"> 14:</span> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">void</span> btnFilter_Click(<span style="color: #0000ff">object</span> sender, EventArgs e) |
1 |
<span style="color: #606060" id="lnum15"> 15:</span> { |
1 |
<span style="color: #606060" id="lnum16"> 16:</span> Label1.Text = String.Empty; |
1 |
<span style="color: #606060" id="lnum17"> 17:</span> <span style="color: #0000ff">using</span> (LinqcodeDataContext context = <span style="color: #0000ff">new</span> LinqcodeDataContext(SPContext.Current.Web.Url)) |
1 |
<span style="color: #606060" id="lnum18"> 18:</span> { |
1 |
<span style="color: #606060" id="lnum19"> 19:</span> var productsWithStockGt5 = from product <span style="color: #0000ff">in</span> context.Products |
1 |
<span style="color: #606060" id="lnum20"> 20:</span> <span style="color: #0000ff">where</span> product.Stock > 5 |
1 |
<span style="color: #606060" id="lnum21"> 21:</span> select product; |
1 |
<span style="color: #606060" id="lnum22"> 22:</span>  |
1 |
<span style="color: #606060" id="lnum23"> 23:</span> <span style="color: #0000ff">foreach</span> (var product <span style="color: #0000ff">in</span> productsWithStockGt5) |
1 |
<span style="color: #606060" id="lnum24"> 24:</span> { |
1 |
<span style="color: #606060" id="lnum25"> 25:</span> <span style="color: #0000ff">string</span> productInfo = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"Title: {0} - {1} <br />"</span>, product.Title, product.Description); |
1 |
<span style="color: #606060" id="lnum26"> 26:</span> Label1.Text += productInfo; |
1 |
<span style="color: #606060" id="lnum27"> 27:</span> } |
1 |
<span style="color: #606060" id="lnum28"> 28:</span> } |
1 |
<span style="color: #606060" id="lnum29"> 29:</span> } |
De esta forma, si vuestro requerimiento de usar linq 2 sharepoint es muy fuerte, se puede llegar a conseguir.
Para acabar, comentar una curiosidad que me ha pasado durante estas pruebas. Inicialmente he intentado usar un GridView de asp.net para mostrar la información, configurando el DataSource al resultado de la query de Linq, y dejando la propiedad AutoGenerateColumns a true. Esto no me ha funcionado, ya que el GridView, de forma interna, ha intentado generar las columnas usando Reflection, y esas operaciones no están permitidas en la Sandbox.
Espero que os sirva.
Saludos!!
29 noviembre, 2011 at 8:13 pm
Hola Luis, debería funcionarte sin problemas.
🙂 muy buen post…lo que has experimentado con el control GridView se debe a que las soluciones de tipo Sandbox no soporte tipos anónimos. Si al control GridView le das un List
¡Un saludo!
29 noviembre, 2011 at 9:54 pm
Gracias JC!!
así da gusto 🙂
Un saludo.