Archivo de la categoría: Desarrollo de SharePoint

HTTP 406 Error al utilizar $http.get Angular contra SharePoint resto puntos finales

Actualización: Marc AD ndersson señaló esta gran pieza de información: http://blogs.Office.com/2014/08/13/JSON-Light-support-Rest-SharePoint-API-released/. Eso explica mucho :).

Nunca puede ser el peor título de una entrada de blog! ANYHOO.

Normalmente hago todos mis prototipos contra una instancia O365. Tengo mi instancia personal así que no tengo que estar preocupado de afectando a nadie. Como acotación al margen – recuerda cuando llamamos llevados alrededor de las máquinas virtuales en nuestros ordenadores portátiles con musgo – SQL Server, IIS, decidir vs Hyper-V. VMWare? En fin...

Había desarrollado una aplicación usando Angular en este entorno que hace, entre otras cosas, Esto:

$http.Get(serverUrl)
.éxito(función(datos, estado, cabeceras, config) {

var getLinksResponse = datos;

getLinksResponse.value.forEach(función(theResult) {

// y así sucesivamente y así producir espuma

Esto estaba trabajando muy bien en dos diferentes entornos en línea de SharePoint. Sin embargo, Cuando mi colega lo portado a una instancia de Cloudshare, Me estaba poniendo un HTTP 406 error (que fue la primera vez que he tenido esa, Así que... ¡ yay, Creo que sí). Hicimos un poco de investigación y notó que el encabezado de "Aceptar" estaba fuera de. Estaba perfectamente contento con SharePoint online:

Aceptar: application/json

Pero la instancia cloudshare (que es SP en prem, alojado en un servidor virtual) Quería que el clásico "odata = verbose" agregó también en:

Aceptar: application/json;OData = verbose

Para arreglar eso, Hemos añadido la rúbrica como tal:

var config = {cabeceras: {
'Aceptar': ' application/json;OData = verbose'
}
};

$http.Get(serverUrl,config)
.éxito(función(datos, estado, cabeceras, config) {

var getLinksResponse = datos;

getLinksResponse.value.forEach(función(theResult) {

// y así sucesivamente y así producir espuma

Que se deshizo de la 406, pero también cambió el formato de la respuesta. Era más... detallado. (jaja!) Más cambios fueron necesarios y aquí está el resultado final:

var config = {cabeceras: {
'Aceptar': ' application/json;OData = verbose'
}
};

$http.Get(serverUrl,config)
.éxito(función(datos, estado, cabeceras, config) {

var getLinksResponse = datos;

getLinksResponse.d.results.forEach(función(theResult) {

// y así sucesivamente y así producir espuma

Esto sólo se convirtió en un 30 minuto problema para nosotros, así que suerte. Esperemos que alguien encuentra esta útil.

</final>

Creciente conciencia / Adopción de Frameworks JavaScript

Mi colega, Javed Ansari (http://www.bigapplesharepoint.com/team?showExpertName=Javed%20Ansari&rsource=pgblog), escribió un blog Resumen corto en los marcos que le gusta o por lo menos ha estado usando con SharePoint: http://www.bigapplesharepoint.com/pages/View-An-Insight.aspx?BlogID=53&rsource=PGBlog).

jQuery parece haber sido el vencedor en el campo, por así decirlo, desde hace años, Pero los otros son más nuevos y alambiques luchando contra lo, como Angular. (SPServices, Claro, ha sido un salvavidas durante años y seguirá siendo así creo que).

Lo utilizan personas? Se enfocaron más en herramientas de Microsoft (OMSC / JSOM) o moviendo más hacia Angular, Octavos de final, Ember, etc.?

Tengo un sesgo creciente hacia estos marcos no son de Microsoft. Creo que las cosas MSFT están más difícil y más difícil de trabajar con, que requieren casi tanto de la curva de aprendizaje como al viejo estilo del lado del servidor dev.

Publicar un comentario aquí o en Gran manzana SharePoint Si quieres hablar (Gran manzana tendrán más probabilidad de que una buena discusión).

</final>

Trabajos de temporizador de SharePoint desde configuración de colección de sitios de giro

Mi colega, Ashish Patel, escribió un blog describiendo una arquitectura de trabajo flexibles temporizador Eso da cierta flexibilidad agradable para apoyar las tareas o informes de larga duración.  En sus palabras:

1. Analizando Checked archivos y enviar recordatorios a los individuos si el número de días (desde que se desprotegió el archivo) exceder ciertos límites umbral

2. Quitar enlaces de otros contenidos cuando un contenido particular es eliminado o archivado desde el sistema

3. Usuario quiere ver todas las alertas que suscrito en todas las webs en la colección de sitios

4. Enviar un recordatorio a los autores a revisar el contenido cuando un tiempo de revisión fue especificado en el contenido y que se aproxima la fecha

Bien, la lista continúa...

– Ver más en: http://www.bigapplesharepoint.com/ páginas/vista-An-Insight.aspx?BlogID=40#sthash.7cKuiwly.dpuf

Hay momentos en mi pasado cuando tener algo como esto habría sido muy útil.

</final>

Cómo: Configurar prueba unitaria y cobertura de la prueba con QUnit.js y Blanket.js para una oficina 365 Aplicación de SharePoint

Intro

Me han estado explorando pruebas unitarias y cobertura de prueba para JavaScript como trabajo en una nueva aplicación de SharePoint para SharePoint en línea en la oficina 365 Suite.  Los caminos de investigación obvio me llevaron a Qunit.js y justo después, Para Blanket.js.

QUnit Déjame crear pruebas unitarias y agruparlas en módulos.  Un módulo es una manera simple de organizar pruebas relacionadas. (No sé si que lo estoy usando como se pretendía, Pero está funcionando para mí hasta ahora con el pequeño conjunto de pruebas que hasta el momento he definido).

Blanket.js se integra con Qunit y me mostrará las líneas reales de JavaScript que eran – y lo más importante – no fueron realmente ejecutadas en el transcurso de las pruebas.  Esta es "la cobertura" – líneas que ejecutan están cubiertas por la prueba mientras que otras no lo son.

Entre establecer buenos casos de prueba y visualización de cobertura, podemos reducir el riesgo de que nuestro código ha ocultado defectos.  Buenos tiempos.

Qunit

Suponiendo que tienes tu Visual Studio proyecto establecido, empezar descargando el paquete de JavaScript desde http://qunitjs.com.  Añadir el JavaScript y CSS correspondiente a su solución.  Mina se parece a esto:

image

Figura 1

Como se puede ver, Estaba usando 1.13.0 en el momento que escribí esta entrada de blog. No te olvides de descargar y agregar el archivo CSS.

Fuera del camino, siguiente paso es crear una especie de prueba del arnés y los bits de Qunit de referencia.  Estoy probando un montón de funciones en un archivo de script llamado "QuizUtil.js" así que he creado una página HTML llamada "QuizUtil_test.html" como se muestra:

image Figura 2

Aquí está el código:

<!DOCTYPE HTML>
<HTML xmlns= "http://www.w3.org/ 1999/xhtml">
<cabeza>
    <Título>QuizUtil prueba con Qunit</Título>
    <enlace REL= "stylesheet" href="../CSS/qunit-1.13.0.CSS" />
    <secuencia de comandos tipo= text/javascript"" src="QuizUtil.js" datos de la cubierta></secuencia de comandos>
    <tipo de script ="text/javascript" src ="qunit-1.13.0.js"></secuencia de comandos>
    <tipo de script ="text/javascript" src ="blanket.min.js"></secuencia de comandos>

    <secuencia de comandos>
        módulo("getIDFromLookup");
        prueba("QuizUtil getIDFromLookupField", función () {
            var goodValue = "1;#Paul Galvin";

            igual(getIDFromLookupField(goodValue) + 1, 2), "ID de [" + goodValue + "] + 1 debe ser de 2";
            igual(getIDFromLookupField(undefined), undefined, "Undefined argumento de entrada debe devolver resultado indefinido.");
            igual(getIDFromLookupField(""), undefined, "Argumento de entrada vacío debe devolver un valor no definido.");
            igual(getIDFromLookupField("gobbledigood3-thq;ada dkvn;skfja sdjfbvubvqrubqer0873407t534piutheqw;vn"), undefined,"Debería volver un convertible de resultado a un entero");
            igual(getIDFromLookupField("2;#alguna otra persona"), "2", "Checking [2;#alguna otra persona].");
            igual(getIDFromLookupField("9834524;#valor de tipo Long"), "9834524", "Prueba de gran valor.");
            SqlDouble(getIDFromLookupField("5;#Nadie", 6), 6, "Prueba de un SqlDouble (5 No es igual a 6 para este ejemplo: [5;#Nadie]");

        });

        módulo("htmlEscape");
        prueba("QuizUtil htmlEscape()", función () {
            igual(htmlEscape("<"), "&lt;", "Escape a menos de operador ('<')");
            igual(htmlEscape("<div class =  "someclass">Parte del texto</div>"), "&lt;div class =&quot;SomeClass&quot;&gt;Parte del texto&lt;/div&gt;", "La secuencia de prueba más compleja.");
        });

        módulo("getDateAsCaml");
        prueba("QuizUtil getDateAsCaml()", función () {
            igual(getDateAsCaml(Nuevo Fecha("31/12/2013")), "2013-12-31T:00:00:00", "Testing fecha duro codificado: [12/31/2013]");
            igual(getDateAsCaml(Nuevo Fecha("01/05/2014")), "2014-01-05T:00:00:00", "Testing fecha duro codificado: [01/05/2014]");
            igual(getDateAsCaml(Nuevo Fecha("01/31/2014")), "2014-01-31T:00:00:00", "Testing fecha duro codificado: [01/31/2014]");
            igual(getTodayAsCaml(), getDateAsCaml(Nuevo Fecha()), "getTodayAsCaml() debe ser igual a getDateAsCaml(nueva fecha())");
            igual(getDateAsCaml("valor de tonterías"), undefined, "Tratar de obtener la fecha de un valor de tonterías.");
            igual(getDateAsCaml(undefined), undefined, "Tratar de obtener la fecha de la [undefined] fecha.");
        });

        módulo("getParameterByName");
        prueba("QuizUtil getParameterByName (de la cadena de consulta)", función () {
            igual(getParameterByName(undefined), undefined, "Tratar de conseguir parámetro definido debe devolver indefinido.");
            igual(getParameterByName("no existe"), undefined, "Tratar de obtener el valor del parámetro cuando sabemos que no existe el parámetro.");

        });

        módulo(Cookies"");
        prueba("QuizUtil varias funciones de la galleta.", función () {
            igual(setCookie("prueba de", "1", -1), getCookieValue("prueba de"), "Conseguir una galleta puse debería funcionar.");
            igual(setCookie("anycookie", "1", -1), verdadero, "Establecer una cocción válido debe devolver 'true'.");
            igual(setCookie("nombre de la cookie loco !@#$%"%\^&*(()?/><.,", "1", -1), verdadero, "Establecer un nombre de la cookie mal debe devolver 'falso'.");
            igual(setCookie(undefined, "1", -1), undefined, "Paso definido como el nombre de la cookie.");
            igual(getCookieValue("no existe"), "", "Cookie no existe prueba.");
        });

    </secuencia de comandos>
</cabeza>
<cuerpo>
    <div ID.= "qunit"></div>
    <div ID.= "qunit-fixture"></div>

</cuerpo>
</HTML>

Hay varias cosas que pasan aquí:

  1. Mi código de referencia (QuizUtil.js)
  2. Referencia Qunity.js
  3. Definir algunos módulos (getIDFromLookup, "Cookies", y otros)
  4. Colocar un <div> cuyo ID es "qunit".

A continuación, Sólo hago esta página y obtienes algo como esto:

image

Figura 3

Si te ves en la parte superior, Tienes varias opciones, dos de los cuales son interesantes:

  • Ocultar pruebas pasado: Bastante obvio.  Puede ayudar el ojo a ver las áreas problemáticas y no un montón de desorden.
  • Módulo: (menú desplegable): Esto filtrará las pruebas a esos grupos de pruebas que quieres.

En cuanto a las pruebas de sí mismos – unos comentarios:

  • Hace falta decir que tienes que escribir el código que es comprobable en primer lugar.  Usando la herramienta puede ayudar a hacer cumplir esa disciplina. Por ejemplo, Tenía una función llamada "getTodayAsCaml()”.  Esto no es muy comprobable desde no toma ningún argumento de entrada y para probarlo por la igualdad, Necesitamos actualizar constantemente el código de prueba para reflejar la fecha actual.  Yo lo refactorizado por adición de un parámetro de entrada de datos y luego pasar la fecha actual cuando quiera la fecha actual en formato CAML.
  • El marco Qunit documenta sus propias pruebas y parece bastante robusto.  Puede hacer cosas simples como prueba para la igualdad y también tiene soporte para llamadas de estilo ajax (tanto "real" o escarnecido usando tu favorito mocker).
  • El proceso también te obliga a pensar en casos de borde – ¿qué pasa con "indefinido" o nulo se pasa a una función.  Resulta muerto simple probar estos escenarios hacia fuera.  Muy bueno.

Cobertura con Blanket.js

Blanket.js complementa Qunit mediante el seguimiento de las actuales líneas de código que se ejecutan durante el curso de sus pruebas.  Integra el derecho en Qunit así que aunque es una aplicación totalmente independiente, juega muy bien, parece que es una aplicación perfecta.

Esto es blanket.js en acción:

image Figura 4

image

Figura 5

(Tienes que hacer clic en la casilla "Habilitar la cobertura" en la parte superior [ver figura 3] para permitir esto.)

Las líneas resaltadas en la figura 5 No han sido ejecutados por cualquiera de mis pruebas, Tengo que diseñar una prueba que hacen que se ejecutarán si quiero cobertura completa.

Conseguir trabajo siguiendo estos pasos blanket.js:

  1. Descargar de http://blanketjs.org/.
  2. Añádelo a tu proyecto
  3. Actualizar la página de mazo de cables de prueba (QuizUtil_test.html en mi caso) como sigue:
    1. El código de referencia
    2. Decorar tu <secuencia de comandos> referencia así:
    <secuencia de comandos tipo= text/javascript"" src="QuizUtil.js" datos de la cubierta></secuencia de comandos>

Blanket.js recoge el atributo "data-cubierta" y hace su magia.  Se conecta a Qunit, actualiza la interfaz de usuario para agregar la opción "Habilitar la cobertura" y listo!

Resumen (TL; DR)

Utilizar Qunit para escribir sus casos de prueba.

  • Descargar
  • Añádelo a tu proyecto
  • Escribir una página de prueba de arnés
  • Crear tus pruebas
    • Refactorizar algunas de tu código para ser comprobable
    • Ser creativo!  Creo que de locos, escenarios imposibles y ponerlas a prueba de todos modos.

Blanket.js de uso para asegurar una cobertura

  • Asegúrese de que está trabajando Qunit
  • Descargar blanket.js y agregarla a su proyecto
  • Agregar a la página de mazo de cables de prueba:
    • Agregue una referencia a blanket.js
    • Agregar un atributo "datos-cubierta" para su <secuencia de comandos> etiqueta
  • Ejecutar las pruebas Qunit.

Nunca hice nada de esto antes y tenía algo rudimentario en un puñado de horas de trabajo. 

Prueba feliz!

</final>

undefinedSuscribirse a mi blog.

Sígueme en Twitter en http://www.twitter.com/pagalvin

Lists.asmx, GetList y "valor no puede ser nulo”

Hoy he descubierto que la GetList() método en lists.asmx servicio Web tiene que ser llamado muy cuidadosamente o es propenso a tirar un misterioso "Valor no puede ser nulo" excepción (y que está suponiendo que puede superar el peor mensaje de error genérico, "Excepción de tipo ' Microsoft.SharePoint.SoapServer.SoapServerException’ fue arrojado.")  Específicamente, Me encontré con que no puede ofrecer ningún tipo de prefijo en el método GetList.  El siguiente fragmento de código de jQuery ilustra el punto:

image

Si haces, el servicio web responde con "Valor no puede ser nulo" por esto violinista-proporciona la transcripción HTTP:

<?XML version = "1.0" Encoding = "utf-8"?>
  <jabón:Envolvente
     xmlns:jabón ="
http://schemas.xmlsoap.org/SOAP/Envelope/"    
     xmlns:XSi = "
http://www.w3.org/2001/XMLSchema-instance
     xmlns:XSD ="
http://www.w3.org/2001/XMLSchema">

  <jabón:Cuerpo>
    <jabón:Fallas>
      <faultcode>jabón:Servidor</faultcode>
      <FaultString>
        Excepción de tipo ' Microsoft.SharePoint.SoapServer.SoapServerException’ fue arrojado.
      </FaultString>
      <detalle>
        <ErrorString xmlns ="
http://schemas.Microsoft.com/SharePoint/SOAP/">
Valor no puede ser nulo.
        </ErrorString>
      </detalle>
    </jabón:Fallas>
  </jabón:Cuerpo>
</jabón:Envolvente>

Claro, probablemente no agregar ese prefijo "s0" sobre su propia, pero algunas herramientas son propensas a hacerlo (como Eclipse).

Esto es aún más confuso / frustrante porque otros métodos toleran prefijos.  Por ejemplo, el GetListCollection método no importa si se es prefijo, incluso con prefijos de tonterías como "xyzzy":

image

Este "valor no puede ser nulo" parece bastante común con lists.asmx así que esperemos que esto nos ayudará a alguien fuera en el futuro.

</final>

Suscribirse a mi blog.

Sígueme en Twitter en http://www.twitter.com/pagalvin

Sin cesar de anidamiento <div> Etiquetas y jQuery

Esto me parece un tema tan extraños, No estoy seguro vale blogs acerca de, pero que nunca ha dejado de mi antes, así que aquí vamos Sonreír

Estoy elaborando un proyecto donde estoy tirando de algunos datos de una búsqueda, embalaje en un mensaje XML y, a continuación, ese XML en última instancia es transformado en HTML mediante XSLT.  Hay un montón de jQuery involucrados, un bit que implementa algunas funciones de tabulación.  Cuando hace clic en una ficha (realmente, un <div>), jQuery invoca .hide() y .show() en diferentes divs (la carga de la página inicial descargas todo el contenido por lo que en este caso no hay ninguna devoluciones).

Un montón de horas hace, la ficha conmutación lógica comenzó a comportarse de manera irregular y no mostrará uno de mis fichas.  Yo finalmente seguimiento es el hecho de internet explorer (por lo menos) pensaba que el <div> etiquetas anidadas mucho, mucho más profundo que pretende.Mostrar la barra de herramientas de desarrollador:

-<div id = "Tab1Content">
  -<div>
    -<div>
      -<div id = "Tab2Content">
        -<div>
           …………………………
                   </div>  <— mostrando finalmente cerró todo el camino aquí!

Por lo tanto, si hice un $("# Tab1Content").ocultar(), También podría ocultar Tab2 y nunca pude mostrar Tab2 si también no muestro Tab1.  Copia y pega el código visual studio y mostró todos del revestimiento del div hasta bien, al igual que se suponía que iban a estar haciendo, mirando como este:

-<div id = "Tab1Content">
  +<div>
  +<div>
-<div id = "Tab2Content">
  +<div>
  +<div>

Golpearon la cabeza contra la pared durante un tiempo y notó que en el código HTML actual código estaba generando un montón de vacío <div> Etiquetas, como:

<cuerpo>

  <div id = "Tab1Content">

    <div id = "row1" />
    <div id = "row2" />

  </div>

  <div id = "Tab2Content">

    <div id = "row1" />
    <div id = "row2" />

  </div>

</cuerpo>

(Lo anterior es waaaaaaaaaaaay simplificada.  Las etiquetas div vacía son totalmente válidas. Algunos de mis <div> Etiquetas estaban llenos de contenido, pero no fueron muchos más.  Llegué a la realización que mi <XSL:para cada> directivas estaban emitiendo el formulario corto cuando las etiquetas div el xsl:no para cada ' encontrar ningún dato.  Obligó a un comentario HTML en la salida, como se muestra:

image

 

Después de hice, el div se alinearon bien y mi ficha conmutación empezó a trabajar.

Como siempre, Espero que esto ayude a alguien en una pizca.

</final>

Suscribirse a mi blog.

Sígueme en Twitter en http://www.twitter.com/pagalvin

Una causa por "el creador de este fallo no especificó una razón.”

Yo he estado haciendo un montón de trabajo con SharePoint search últimamente y específicamente en la clase de KeywordQuery, propiedades y métodos.

Si desea que el conjunto de resultados a devolver resultados más allá de los sospechosos habituales (ver aquí), se agrega a la colección de SelectedProperties, como en:

myKeywordQuery.SelectProperties.Add("xyzzy");

Muchas gracias y una punta del sombrero a Corey Roth y Esta entrada de blog enormemente útil (http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2008/02/19/how-to-use-the-moss-enterprise-search-keywordquery-class.aspx)

En mi caso, "xyzzy" no es realmente una propiedad administrada.  Cuando agregado a SelectedProperties de todas formas, SharePoint tiró uno de mi favorito nunca excepciones de tiempo de ejecución:

"El creador de este fallo no especificó una razón".

Me gusta especialmente la capital "R" en la razón.  Esto me suena como el.NET equivalente de"No tengo ninguna boca, y yo debo gritar.”

</final>

Suscribirse a mi blog.

Sígueme en Twitter en http://www.twitter.com/pagalvin

Referencia práctica: Resultados predeterminados de búsqueda KeywordQuery

Cuando se invoca la ejecución() método en un KeywordQuery, puede crear un ResultTable basado en ResultType.RelevantResults.  Este fragmento de código ilustra lo que quiero decir:

ResultTableCollection resultsTableCollection = myKeywordQuery.Execute();

ResultTable searchResultsTable = resultsTableCollection[ResultType.RelevantResults];

La tabla resultante tendrá las siguientes columnas de información: 

WorkId
Rango
Título
Autor
Tamaño
Ruta de acceso
Descripción
Escribir
SiteName
CollapsingStatus
HitHighlightedSummary
HitHighlightedProperties
ContentClass
IsDocument
PictureThumbnailURL
ServerRedirectedURL

Deriva esta lista un SharePoint 2010 medio ambiente, Enterprise edition.  Esperemos que será útil a alguien en el futuro.

</final>

Suscribirse a mi blog.

Sígueme en Twitter en http://www.twitter.com/pagalvin

Uno de los motivos: "Error al extraer el archivo cab en la solución”

Mientras trabajaba en un elemento web de visual studio proyecto hoy, Hice una re-org menor de algunos archivos para poner en la carpeta _layouts como parte del proceso de implementación. Específicamente, Nombre un archivo .js desde "TypeAhead.js" "TypeAhead(antigua).JS"  Plan de quitarla tan pronto como su sucesor "TypeAhead.js" resulta correcto.  Esto parecía:

image

Esto causó inmediatamente un problema con visual studio cuando trató de implementar el proyecto:

Error en el paso de implementación Agregar solución: Error al extraer el archivo cab en la solución.

Resulta que no debería poner un paréntesis en nombres de archivo.  Me quitaron el paréntesis y que resolvió el problema.

</final>

Suscribirse a mi blog.

Sígueme en Twitter en http://www.twitter.com/pagalvin