Using promises to simplify javascript asynchronous development in SharePoint

SharePoint APIs have been dramatically improved over the last few years, especially when it comes to javascript but, even with those improvements, it’s sometimes very hard for developers with backend background to achieve goals that initially seem simple. To the fact that we don’t have (or we don’t know how to use) good development tools to help us with developing and debugging javascript code, we need to add the way you normally interact with SharePoint objects. Let me show you this with an example:

Imagine I want to show a list with elements coming from a taxonomy termset. Basically I would like to be able to query the site collection default term store and, by calling a method passing the name of the termset containing the items, retrieve the list of terms, iterate through them and fill my html control. To make it a little more complex, imagine we have actually two different html controls to fill with two different termset terms.

The first problem you are going to face when trying to implement the scenario above is the fact that SharePoint doesn’t provide you a method to retrieve the terms of a termset of the default group of the site collection’s default termstore. You will need to make a list of request to get the data, starting with this:

Code Snippet
  1. var getGroups = function () {
  2.     var clientContext = SP.ClientContext.get_current();
  3.     var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(clientContext);
  4.     var termStore = taxSession.getDefaultSiteCollectionTermStore();
  6.     var groups = termStore.get_groups();
  7.     clientContext.load(groups);
  9.     clientContext.executeQueryAsync(function () {
  11.         // Add here code to execute when groups are loaded
  13.     }, function (sender, args) {
  15.         console.log(args.get_message());
  17.     });
  18. }

Then, in line 11 you will need to iterate through the list of groups to search the one you are looking for. In the case we are working on we are selecting the site collection’s default group. Once we have it, we will need to create a new request to get the list of termsets included in the selected group and after that, a new request for getting the list of terms on those termsets we are interested in. You will easily end up with something like:

Code Snippet
  2. var getGroups = function () {
  3.     var clientContext = SP.ClientContext.get_current();
  4.     var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(clientContext);
  5.     var termStore = taxSession.getDefaultSiteCollectionTermStore();
  7.     var groups = termStore.get_groups();
  8.     clientContext.load(groups);
  10.     clientContext.executeQueryAsync(function () {
  12.         var groupsEnum = groups.getEnumerator();
  14.         while (groupsEnum.moveNext()) {
  16.             var currentGroup = groupsEnum.get_current();
  18.             if (currentGroup.get_isSiteCollectionGroup()) {
  19.                 var groupName = currentGroup.get_name();
  21.                 var termSets = currentGroup.get_termSets();
  22.                 var clientContext = SP.ClientContext.get_current();
  23.                 clientContext.load(termSets);
  25.                 clientContext.executeQueryAsync(function () {
  27.                     var clientContext = SP.ClientContext.get_current();
  29.                     var termSetsEnumerator = termSets.getEnumerator();
  31.                     while (termSetsEnumerator.moveNext()) {
  33.                         var currentTermSet = termSetsEnumerator.get_current();
  34.                         var termSetName = currentTermSet.get_name();
  36.                         if (termSetName === "field1" || termSetName === "field2") {
  38.                             var terms = currentTermSet.getAllTerms();
  39.                             clientContext.load(terms);
  41.                             clientContext.executeQueryAsync(function () {
  43.                                 // Fill your controls here…
  45.                             }, function (sender, args) {
  47.                                 console.log(args.get_message());
  49.                             });
  51.                         }
  52.                     }
  55.                 }, function (sender, args) {
  57.                     console.log(args.get_message());
  59.                 });
  61.                 break;
  62.             }
  63.         }
  65.     }, function (sender, args) {
  67.         console.log(args.get_message());
  69.     });
  70. }

Please, do not copy the code above. I have wrote it just to illustrate problems and I am sure it won’t work.

What I wanted to highlight with the previous example is the typical problems you are going to face if you follow a similar approach. The first and most obvious is the spaguetti code syndrome. Yes, you are right, this can be easily fixed using delegate functions instead of nesting calls but you are going to face then some problems with the scope of variables and functions’ returned objects. Those that, like me, are not experts on javascript, will finish declaring everything globally and then you are on your own. Good luck! In addition, you must take into consideration that the subsequent calls will be queued and executed in a way that is not probably the one you are expecting. Again, problems, waste of time and frustration.


So, is there any way to make this process easier? One possible answer is “use promises”. The basic idea is that you can work with functions in a similar way of how you would work in synchronous development. The main function of the example above could be something similar to this:

Code Snippet
  1. var p = getGroups();
  3. p.done(function (result) {
  5.     var p2 = getTermSets(result);
  7.     p2.done(function (result) {
  9.         var p3 = getTerms(result, "field1");
  11.         p3.done(function (result) {
  12.             // Fill your control here
  13.         });
  15. (result) {
  16.             console.log(result);
  17.         });
  19.         p3 = getTerms(result, "field2");
  21.         p3.done(function (result) {
  22.             // Fill your control here
  23.         });
  25. (result) {
  26.             console.log(result);
  27.         });
  29.     });
  31. (result) {
  32.         console.log(result);
  33.     });
  35. });
  37. (result) {
  38.     console.log(result);
  39. });

The magic is done within the methods GetGroups, GetTermSets and GetTerms. For example, the GetGroups method could look like:

Code Snippet
  1. var getGroups = function () {
  3.     var d = $.Deferred();
  5.     var clientContext = SP.ClientContext.get_current();
  6.     var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(clientContext);
  7.     var termStore = taxSession.getDefaultSiteCollectionTermStore();
  9.     var groups = termStore.get_groups();
  10.     clientContext.load(groups);
  12.     var o = { d: d, groups: groups };
  14.     clientContext.executeQueryAsync(
  15.         Function.createDelegate(o, this.getGroupsCallback),
  16.         Function.createDelegate(o, this.failCallback)
  17.     );
  19.     return d.promise();
  20. }
  22. var getGroupsCallback = function () {
  23.     this.d.resolve(this.groups);
  24. }
  26. var failCallback = function () {
  27.     this.d.reject("something bad happened");
  28. }

In order to see how you share information between methods, we could look at the GetTermSets method

Code Snippet
  1. var getTermSets = function (_groups) {
  3.     var d = $.Deferred();
  5.     var clientContext = SP.ClientContext.get_current();
  8.     var groupsEnum = _groups.getEnumerator();
  10.     while (groupsEnum.moveNext()) {
  12.         var currentGroup = groupsEnum.get_current();
  14.         if (currentGroup.get_isSiteCollectionGroup()) {
  15.             var groupName = currentGroup.get_name();
  17.             var termSets = currentGroup.get_termSets();
  18.             clientContext.load(termSets);
  20.             var o = { d: d, termSets: termSets };
  22.             clientContext.executeQueryAsync(
  23.                 Function.createDelegate(o, this.getTermSetsCallback),
  24.                 Function.createDelegate(o, this.failCallback)
  25.             );
  27.             return d.promise();
  29.             break;
  30.         }
  31.     }
  32. }

As you have probably seen, the final result is really cleaner and easy to follow and you won’t need to deal with global variables because you can easily send parameters to functions and retrieve returning values.

For those of you who are still reading, I need to clarify something. If you search for “Promises” and “Javascript” you will find that I’m not actually using the cool new feature natively supported by some browsers. I’m using the implementation of this pattern included in jquery called Deferred. If you want to learn more about this topic, I recommend you visiting

Language switch

When I started blogging my expectations were quite low. Having more than a couple of readers was something that was absolutely not in my mind. My main goal was having a place to share my experiences with my colleagues instead of redirecting them just to Google when they were stuck with something.

Now, after moving to Switzerland, the amount of colleagues who can read my posts has been reduced dramatically, as only a few of them speak Spanish. This fact has pushed me to take the decision of changing the main language of this blog.

I know it will be more difficult for me, as my English is far from being perfect, but this is also a challenge that I always wanted to face. The only thing I will ask you is patience while my writing skills improve on that new language. Probably I won’t be able to write long posts at the beginning and, that’s for sure, it will be really hard to add my small pieces of humor into them.

To ensure I can face this challenge I will try to publish a weekly post. This is something more than optimistic, as I’ve been unable to do this even in my own language. Let’s see for how long I can keep this 😉

Speaking at the European SharePoint Conference

Today I’ve been given the opportunity to deliver a session around social at the European SharePoint Conference in Barcelona. It has been a very special event for me because it has been my first event of its kind being a speaker, and also because it has taken place in the city I was born and raised. The session has been quite well for being my first one, in my opinion, but I have done at least two beginners’ mistakes (two that I’m aware of). First one is running out of time before finishing all the demos. Second one is forgetting to add my contact details in the last slide. I hope I can partially correct these two errors with this post.

For the first one, is difficult you get to this post if I haven’t shared the blog’s url with you. I will leave it to the magic of social networks and to the ESPC’s organization with regards to spreading the word.

For the second one, just wanted to let you know that all the code you have seen is publicly online in

As I have told you during the session, this is not production ready code. It’s not following best practices and, actually, it has been my first experience with AngularJS, so don’t expect this to be the best starting point for any project. However, it can give you some good ideas and I hope it can save you some time if you need to do things around social.

A can’t promise anything, but my idea is to continue improving the code and adding more capabilities so it really becomes a good starting point for any of you who are interested in this area. Stay tunned!

SharePoint, Cervantes, y por qué los espacios importan

Hoy me he tenido que enfrentar a una de esas cosas que tanto nos gustan a los desarrolladores. Aquello que ha funcionado toda la vida y de repente, sin cambio aparente, deja de funcionar. El caso es que en cierto desarrollo se había incluído una plantilla para representar los resultados de la búsqueda de SharePoint y todo iba a las mil maravillas hasta que a alguien se le ocurrió la brillante idea de utilizar el documento generado por un desarrollador para replicar la misma funcionalidad en otro sitio distinto.

Los alaridos de desesperación han llegado hasta mí de una manera que no puedo describir. "PERO SI ES EXACTAMENTE IGUAL! PERO SI HE SEGUIDO LOS PASOS VENTISIETE VECES!" En realidad no he entendido un carajo porque lo decían en francés, pero muy amablemente me lo han explicado antes de pedirme que lo arreglara. El caso es que el popup que aparece cuando sitúas el ratón encima de un resultado de búsqueda había tomado la decisión de no aparecer nunca más. A saber. Tras un poco de arqueología he descubierto que, en realidad, había una sutil diferencia. En cierta parte del documento se hacía referencia a lo siguiente:

[…] Localice el nodo <mso:ManagedPropertyMapping y edite su contenido para añadir el siguiente texto:

‘propiedad’: ‘propiedad_OWSTEXT’ […]

El problema que tienen los programas de edición de textos, y también Word ;), es que a menudo toman decisiones por nosotros para mejorar el resultado de nuestros escritos. Como todos sabréis, después de un signo de puntuación como son los dos puntos, Cervantes dijo que se ponía un espacio. Bonito, sí, pero me rompe mi SharePoint.

Conclusión: "Mierda pa cervantes!"

Failed to extract the cab file in the solution

Hoy me he encontrado con un error bastante peculiar a la hora de desplegar una solución en una granja SharePoint. El error era básicamente algo parecido a lo siguiente:

Error occurred in deployment step ‘Add Solution’: Failed to extract the cab file in the solution.

Lo extraño era que la solución no tenía nada de particular. Simplemente un par de páginas ASPX que se desplegaban en la carpeta LAYOUTS, alguna hoja de estilos y algún que otro fichero javascript.

Después de unas cuantas vueltas he acabado dando con la raíz del problema. En algún punto del proceso de despliegue, SharePoint necesita extraer el contenido del paquete WSP en alguna ruta del sistema de archivos y debe haber alguna limitación en el tamaño máximo que puede tener una ruta en Windows que hacía que el proceso fallara. Es importante entender que a la hora de extraer el contenido de la solución, SharePoint crea una carpeta cuyo nombre coincide con el nombre del proyecto. La solución ha sido fácil: cambiar el nombre del proyecto por algo más corto. De todas maneras, esto me da pie a dar algún consejo a la hora de dar nombre y de organizar vuestras soluciones.

Lo primero que os recomiendo es no escoger nombres demasiado largos para vuestras soluciones. Es más habitual de lo que parece escoger nombres como el siguiente:


No os voy a decir que el nombre no es correctísimo para describir lo que contiene la solución pero, realmente creeis que es necesario? Seguramente sea más apropiado tener una solución que se llame “Proyecto” y dentro una característica que se llame “SocialWebParts”.

Hay mucha gente que es partidaria de construir multitud de paquetes dentro del paraguas de un mismo proyecto de cara a “protegerse” de otros desarrolladores y de los conflictos que pueda ocasionar el trabajo en equipo. Yo soy más partidario de todo lo contrario: un proyecto, un paquete. Para mí construir paquetes independientes se debe hacer únicamente en base a razones del tipo: “esta parte de la solución se tiene que poder desplegar de manera independiente” o “esta parte de la solución puede ser reutilizada sin la necesidad de desplegar todo el resto del proyecto”. Si el trabajo en equipo produce conflictos, soluciona el problema, no lo rodees.

Me he ido por las ramas. El segundo consejo que os voy a dar es organizar de manera adecuada vuestros elementos dentro de la solución. Hay elementos, como por ejemplo las características, que tienen que ir en un sitio determinado y ante lo que poco podemos hacer. Otros elementos, sin embargo, son más “flexibles”. En ocasiones me encuentro con proyectos con varias carpetas a nivel raíz. Esas carpetas no son más que carpetas mapeadas a los directorios LAYOUTS, IMAGES, RESOURCES, etc. de SharePoint. Mi recomendacion habitual es mapear únicamente la carpeta raíz (14, 15 o lo que venga) y crear la estructura que necesites dentro de esa carpeta mapeada. De esa manera te resultará mucho más fácil separar todo aquello que va a desplegarse directamente a los servidores de SharePoint de aquello que va a tener que aprovisionarse a través de características.

En general, si seguís estos dos consejos, o si no seguís ninguno de ellos, no os encontraréis nunca con el error al que hacía referencia al inicio de este artículo. Sin embargo, si seguís únicamente uno de los dos consejos, el riesgo es bastante alto. En mi caso, tenía los elementos muy bien organizados pero se me ocurrió la brillante idea de darle a mi solución un nombre extremadamente largo.

En casa del herrero…

I’m speaking at the European SharePoint Conference 2014

The European SharePoint Conference is less than three weeks away and I’m delighted to be part of such an exceptional line up. The conference will take place in Barcelona, Spain from the 5-8th May 2014 and is Europe’s largest SharePoint event bringing you great sessions and the latest innovations from Vegas.

Browse through the superb conference programme including 110 sessions, keynotes, and tutorials, including topics covering the latest news from SPC14 including what’s new with SharePoint 2013 SP1 – Office Graph/Oslo – new Office 365 REST APIs – Access Apps – Cloud Business Apps.

I will be conducting a session on “Enhancing SharePoint 2013 Social Capabilities” aimed at Developers.

“Enhancing SharePoint 2013 Social Capabilities”

"Social Corporate Networking is one of the pillars of SharePoint and one of the areas with bigger improvements. This session will cover the available social APIs and will drive you through the process of enhancing the out-of-box social experience by using them to build server solutions and Apps.”


The European SharePoint Conference will be run over four days and with over 1000 SharePoint attendee’s already signed up don’t miss this fantastic opportunity to mingle with the European SharePoint Community.

If you want to deepen your SharePoint expertise, to understand the trend of the SharePoint market, and to learn how to leverage Microsoft Office 365 for your business, including the revolutionary Enterprise Social wave, the European SharePoint Conference is the best place to be in 2014!

Prices start from €1150! There is also special group discounts for bookings of 3 or more people.

Book Now and I’ll see you in Barcelona in May

Winter is coming

No, no voy a hablar sobre Juego de Tronos ni sobre ninguna otra serie de televisión. Tras el título de este artículo se esconde la noticia que más me ha costado dar en toda mi carrera profesional: después de 10 años trabajando para Spenta (o Beezy) he decidido dar por terminada esta etapa y comenzar una nueva en otra empresa, y en otro país.

No puedo hacer más que dar las gracias por haber tenido el privilegio de formar parte de la familia Spentana durante tanto tiempo. Ahí he podido compartir momentos con profesionales de un nivel altísimo de los cuales podría decir que he aprendido todo lo que hoy sé. Y si a nivel profesional queda fuera de toda duda el talento que ha habido, hay y habrá en la compañía habida cuenta de los éxitos que se han cosechado a lo largo de todos estos años, tengo que decir, para quien no lo sepa, que la calidad personal del equipo humano de Spenta supera con creces sus habilidades profesionales.

La pregunta que os haréis muchos es:

La verdad es que es muy difícil responder a esta pregunta. Durante estos 10 años de relación profesional ha habido momentos de todo tipo pero, en general, han sido momentos tan buenos como duros. Se ha trabajado muy fuerte para tirar hacia adelante ciertos proyectos y estos últimos 3 años especialmente, cuando nos embarcamos en la aventura de crear un producto de la nada y convertirlo en lo que hoy está considerados por muchos la mejor red social corporativa construida sobre SharePoint. Ya no trabajo para Spenta así que no es publicidad, realmente lo creo. Y, ahora que el producto está acabado, ahora que se empiezan a cosechar los resultados de tantos años de sacrificios ¿me voy?. Las razones son varias y aquí os voy a poner alguna de ellas.

  1. La principal razón que me ha llevado a tomar esta decisión es que siempre he tenido la necesidad personal de tener una aventura en el extranjero. En el año 2007 estuve una temporada en Londres, pero no era realmente lo que estaba buscando. Desde entonces he tenido siempre esta idea en la cabeza y, unas veces por falta de valor, otras por falta de autorización expresa de la jefa (muaks) y otras por compromiso con mi trabajo, siempre había acabado desestimando todas las oportunidades. Hasta ahora.
  2. Otra razón muy importante para mí ha sido el darme cuenta que no estaba aportando lo que yo querría aportar a Spenta. En el pasado creo (o quiero creer) que fui una pieza importante en el desarrollo de la compañía. Ahora había llegado un momento en el que mi capacidad de aportar valor se había visto muy menguada. No es que la empresa no me diera cancha para crecer en una u otra dirección, ha sido más bien que yo no me he visto capacitado para asumir un cambio de rol más orientado a la gestión y, a nivel técnico, honestamente creo que todo funcionaba igual si yo estaba o si yo dejaba de estar. Vamos, se puede decir que he hecho un “Puyol” en toda regla.
  3. Quizá se puede decir que es circunstancial, pero el momento que está viviendo este país ha ayudado mucho a tomar esta decisión. Si antes tenía curiosidad por irme al extranjero, ahora mismo la sensación es que tenía necesidad de irme. Seguro que vaya donde vaya me voy a encontrar con situaciones que no me gusten, pero lo de este país es para mear y no echar gota. Y como no entiendo de política no voy a elaborar más este asunto. Si alguno de vosotros quiere, no tendré ningún inconveniente en hablar sobre este asunto con todo detalle delante de una cocacola.

Más adelante iré escribiendo sobre mis aventuras en el extranjero, pero como adelanto os diré que me voy a una consultora con su sede principal en Ginebra y que seguiré vinculado al mundo SharePoint. No os libraréis de mí tan fácilmente.

¿Qué espero de esta experiencia? A decir verdad, nada. Bastante duro es dejar atrás amigos, familia, un trabajo cojonudo y una ciudad en la que me encanta vivir. De momento me conformo con integrarme rápidamente, mejorar mi inglés y aprender algo de francés. Una vez cumpla esos primeros objetivos, ya me plantearé cosas más ambiciosas.

En fin, seguiremos en contacto porque seguiré escribiendo en este blog (espero que con mayor frecuencia que estos útimos meses) y porque seguiré participando en la medida de mis posibilidades en eventos de comunidad. Para empezar, a muchos espero veros en Mayo en la European SharePoint Conference de Barcelona.

A más ver!

El programa MVP de Microsoft

Tal día como hoy, hace  exactamente 3 años, recibía la gran noticia de entrar a formar parte del grupo de profesionales que Microsoft reconoce con el galardón MVP (Most Valuable Professional). Gozar de dicho privilegio, a priori, no te otorga ninguna virtud ni es ninguna garantía de que tengas unas aptitudes especiales más allá de ser una persona activa en la comunidad técnica. Ni ser MVP indica obligatoriamente que eres un genio en tu especialidad ni, por supuesto, que seas el mejor en tu campo está necesariamente ligado a que te otorguen ese galardón, y os podría poner aquí algún caso que lo demostraría. Dicho esto, y tras 3 años seguidos formando parte del programa MVP, tengo que decir que he tenido la oportunidad de compartir momentos con auténticos portentos tanto de mi especialidad como de muchas otras. He podido aprender de muchos de ellos, y espero haberles podido dejar también alguna enseñanza.

Así como el programa no otorga, como ya he dicho, ninguna virtud, tampoco ofrece “grandes beneficios materiales” a los galardonados. Pongo el entrecomillado porque, a decir verdad, cualquiera podría decir que estoy loco al decir esto. Vayamos por partes. Los MVP somos agasajados con multitud de regalos: subscripción MSDN (que incorpora grandes beneficios extra como, por ejemplo, recursos de Azure), licencias gratuitas de herramientas de terceros o material técnico como, por ejemplo, libros o cursos online, normalmente a cambio de publicar alguna reseña en tu blog o en la página del fabricante. Esto, en muchos casos –o por lo menos en el mío– es un beneficio personal al que ya podía acceder a través de la compañía para la que trabajo. Los beneficios reales que te ofrece el programa, a mi juicio, no son materiales. Tienes acceso a información antes que el resto del público (aunque esto depende mucho de la especialidad a la que pertenezcas) y también tienes acceso a equipos de producto (de nuevo depende de la especialidad y, sobretodo, de tu país de origen). De todas maneras, y después de 3 años, lo que yo destacaría por encima de todo como ventaja de ser parte del programa son una serie de eventos que sí marcan la diferencia. Como MVP estás invitado a algunos eventos entre los que destaca el MVP Summit que se celebra de manera anual en Redmon y en el que tienes la posibilidad de interactuar tanto con otros MVP de todo el mundo como con equipos de producto de Microsoft. Eso, hacedme caso, no tiene precio.

Si habéis llegado hasta aquí habréis pensado que esto huele a despedida. Pues lamento comunicaros que vais a tener que aguantarme como MVP, al menos por un año más. Dejar esto para el final del artículo se debe principalmente a que se me ha antojado darle un tinte más dramático al asunto.

En fin, agradecer de nuevo la confianza depositada en mí a las personas que han hecho posible que siga metido en el programa. Intentaré hacer todo lo posible para, de aquí a un año, volver a escribir un artículo similar a este y deciros que será el inicio de mi año número 5 (ahora tengo algo por lo que luchar :P) como MVP.

Se acerca la Iberian SharePoint Conference…

El próximo día 10 de Octubre, en Madrid, se celebra la primera Iberian SharePoint Conference. El evento, primero de su clase en nuestro país, contará con la presencia de un gran grupo de expertos en SharePoint a nivel mundial entre los que se incluyen todos los SharePoint MVP de España.

Es un orgullo para mí formar parte del grupo de personas que tendrán la posibilidad de exponer en uno de los tres tracks que se han planteado: desarrollo, negocio y sistemas. Mi sesión está englobada en el primero de los tres grupos (aunque realmente tendrá una componente de cada una de las tres áreas) y girará en torno a ALM en el mundo SharePoint. Os daría más detalles sobre la sesión, pero entonces, ¿qué gracia tendría? os invito a venir y verlo con vuestros propios ojos.

Si alguno de vosotros está interesado en ir y todavía no tiene la entrada, podréis encontrar toda la información en

Apps vs Sandbox: presente y futuro

Mucho se ha hablado sobre el nuevo modelo de desarrollo de SharePoint, basado en Apps, y de lo que esto supone para las soluciones Sandbox. La mayoría de información que encuentras en la web está basada en opiniones o no es lo suficientemente sólida para ser tomada como referencia a la hora de plantear el modelo de desarrollo que quieres aplicar en tu compañía. A continuación os expongo la opinión que yo tengo sobre este asunto y, lo que os resultará más interesante, la visión que tiene Microsoft a este respecto de cara al futuro.

Lo primero que tengo que decir es que, personalmente, nunca me gustaron las soluciones Sandbox. Veía sus ventajas (básicamente que funcionan tanto en una instalación on-prem como en Office 365) pero también veía sus limitaciones. No hablaré de las limitaciones aquí porque encontraréis suficiente información en la web al respecto, pero sí os diré que para el tipo de soluciones en las que me suelo encontrar involucrado, esas limitaciones eran un stopper total. Con la versión 2013 de SharePoint apareció el concepto de App y con él llegó la polémica. De manera oficial, lo único que encontrabas en la documentación de Microsoft era que las soluciones Sandbox se habían declarado obsoletas y que, en la medida que te fuera posible, utilizases Apps para desarrollar tanto on-prem como en Office 365. Esto no estaría mal si no fuera por un par de detalles: el modelo de desarrollo de Apps, a día de hoy, tiene tantas limitaciones o más como el modelo Sandbox y todavía no hay documentación suficiente como para plantearse un movimiento en esa dirección si tienes una base de desarrollo lo suficientemente grande.

Además de lo expuesto anteriormente, había una serie de consideraciones que hacían que gente como yo se mostrara reacia a hacer un movimiento en firme en alguna dirección. Por un lado, Microsoft había tardado una única versión en descontinuar el concepto Sandbox. ¿Pasaría lo mismo con el concepto App? Por el otro, hay una carencia de información al respecto del número de usuarios de Office 365 y de su naturaleza. ¿Cuántos son usuarios activos de SharePoint Online? ¿Cuántas suscripciones pertenecen a compañías que también tienen una instalación de SharePoint local? En definitiva, cómo de grande es mi mercado potencial. Sin esa información, las empresas se mostrarán reticentes a apostar por algo que, a bien seguro, requerirá una fuerte inversión por su parte. Respecto a la segunda pregunta todavía no puedo aportar nada pero, respecto a la primera, Microsoft ha arrojado algo de luz el respecto, como podéis comprobar aquí.

El resumen es el siguiente: podéis seguir apostando por Sandbox siempre que sólo incluya elementos declarativos. Sandbox no está muerto, pero el código de usuario sí lo está.

Mi conclusión: más armas para seguir apostando por el método convencional y por soluciones de granja que únicamente funcionarán on-prem. Me alegro de no haber invertido demasiado tiempo en migrar todo mi código a Sandbox porque ahora me habrían confirmado que habría sido trabajo inútil. PERO, y aquí viene el motivo principal de este artículo, luz verde para todos aquellos que trabajáis con soluciones Sandbox para continuar haciéndolo siempre y cuando no incluyáis código de usuario.