domingo, 28 de septiembre de 2014

Simples comandos para diagnosticar el estado de nuestra distributed cache (diagnostic App Fabric Distributed Cache)

Abro Sharepoint 2013 Management Shell y ejecuto lo siguiente:
image

Get-SPServiceInstance | ? {($_.service.tostring()) -eq "SPDistributedCacheService Name=AppFabricCachingService"} | select Server, Status

El comando anterior, nos permitirá ver las instancias del Servicio DistributedCache, en que servidor están corriendo, y su estado.

image

A continuación ejecuto Use-CacheCluster , el cual nos permite utilizar los comandos específicos de AppFabric. A continuación ejecuto Get-CacheHost, cual nos permitirá ver el estado del servicio de cache en cada host del cluster.

image

En base al comando anterior (hostname:cacheport) ejecuto el siguiente comando.

Get-CacheHostConfig –ComputerName [yourServerName] -CachePort 22233

El mismo nos permite ver la configuración del host especificamente (puertos, tamaño, etc)

image

A continuación ejecuto el siguiente comando:  Get-CacheClusterHealth , el mismo nos permitirá ver las estadísticas de health (salud) de las named cache en el cluster.

image

A continuación ejecutar el siguiente comando: Get-CacheAllowedClientAccounts

El mismo nos permite ver que grupos o usuarios tienen acceso a la cache. Por default deberían estar los grupos WSS_Admin_WPG y WSS_WPG. Si la cuenta que corre el servicio del User Profile no está dentro de estos grupos, tendrán errores inesperados de acceso a la cache.

Para finalizar ejecutar el siguiente comando:

Get-AFCacheHostStatus | % {
    $ServerName = $_.HostName
    Get-AFCacheStatistics -ComputerName $_.HostName -CachePort $_.PortNo | Add-Member -MemberType NoteProperty -Name 'ServerName' -Value $ServerName -PassThru
} | Format-List -Property *

Este comando nos retornará el número de items en la cache, request count, size de la cache, etc.

image

Para finalizar ejecutar los siguientes comandos:

Get-EventLog –LogName System –Source *AppFabric*

Get-EventLog –LogName Application –Source *AppFabric*

Simple tip: Exportar la lista de logs del Event Viewer relacionados a Sharepoint

En una consola de powershell (run as a administrator) ejecuto el siguiente código de powershell:

Get-EventLog –LogName Application –Source *Sharepoint* | Export-Csv c:\LogsApplicationSharepoint.csv

Este comando nos exportará todos lo logs del EventViewer en un archivo .csv

image

image

En el caso que querramos exportar los eventos de la categoría System, simplemente cambiamos el LogName.

Get-EventLog –LogName System –Source *Sharepoint* | Export-Csv c:\LogsSystemSharepoint.csv

sábado, 27 de septiembre de 2014

Donde se instalan las dll´s cuando instalo Sharepoint 2013 Client Component SDK?

Cuando quiero utilizar client object necesito instalar el sdk de client object, el cual puede descargarse del siguiente link:

http://www.microsoft.com/en-in/download/details.aspx?id=35585

El instalador deja las dlls de client object en el siguiente path:

C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI

C:\Program Files\SharePoint Client Components\Assemblies

image

image

domingo, 21 de septiembre de 2014

Crear una estructura de folders mediante un archivo .csv con Client Object Model

Supongamos que tenemos un archivo .csv con el siguiente contenido

image

Todas las carpetas están separadas mediante una coma (,)

El sitio donde se creará esta estructura, tiene la siguiente url: http://sharepointsite.com.

La librería donde se crea la estructura, se llama “Proyectos”

El archivo csv, se encuentra en el siguiente path: E:\TEMP\carpetas.csv

El código para crear la estructura de carpetas es la siguiente:

Code:
using (ClientContext clientContext = new ClientContext("http://sharepointsite.com"))
{
Web web = clientContext.Web;
Microsoft.SharePoint.ClientList docLib = web.Lists.GetByTitle("Proyectos");
var folderRoot = docLib.RootFolder;
clientContext.Load(folderRoot);
clientContext.ExecuteQuery();

using (StreamReader file = new System.IOStreamReader(@"E:\TEMP\carpetas.csv"))
{
while (!file.EndOfStream)
{
string line = file.ReadLine();
string[] listaFolders = line.Split(new Char[] { ',' });
string estructuraFolders = "";

foreach (var folder in listaFolders)
{
estructuraFolders = estructuraFolders + "/" + folder;
}
if (estructuraFolders != "/")
{
Folder NewFolder = EnsureFolder(clientContext, folderRoot, estructuraFolders);
}
}

}
}


 


Y el método EnsureFolder hace lo siguiente:




Code:
public static Folder EnsureFolder(ClientContext ctx, Folder ParentFolder, string FolderPath)
{
string[] PathElements = FolderPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string Head = PathElements[0];
Folder NewFolder = ParentFolder.Folders.Add(Head);
ctx.Load(NewFolder);
ctx.ExecuteQuery();
if (PathElements.Length > 1)
{
string Tail = string.Empty;
for (int i = 1; i < PathElements.Length; i++)
Tail = Tail + "/" + PathElements[i];

return EnsureFolder(ctx, NewFolder, Tail);
}
else
return NewFolder;
}

Cómo utilizar el debugger de Visual Studio con client side rendering

Primero verifico que esté desmarcado las siguientes opciones en las propiedades avanzadas del IE.

image

(function () {
    var itemCtx = {};
    itemCtx.Templates = {};
   
    itemCtx.Templates.Header = "<table>";
    itemCtx.Templates.Footer = "</table>";
    itemCtx.Templates.Fields = { 'Title': { 'View': ItemOverrideFun}};
    itemCtx.BaseViewID = 1;
    itemCtx.ListTemplateType = 101;         
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx);
})();

function ItemOverrideFun(ctx) {   
   debugger;
    var title = ctx.CurrentItem.Title;
    var fileRef = ctx.CurrentItem["FileRef"];
    var fileLeafRef = ctx.CurrentItem["FileLeafRef"];  
       var htmlToDeploy = "<a style='color:#000; font-weight:bold' href='" + ctx.CurrentItem["FileRef"] + "'>" + ctx.CurrentItem.Title + "</a><br><span>" + formattedDate(ctx.CurrentItem.Modified)  + " for <b><font color='#f58228'> "+ ctx.CurrentItem.Customer[0].lookupValue +"</font></b></span>";
 
    return htmlToDeploy;
}

En la función ItemOverrideFun, vemos la palabra debugger, esta es una palabra reservada que permite invocar el JIT (just in time) debugger

Al ejecutarse esta línea en el IE, me lanza la siguiente ventana

image

Al abrir el Visual Studio 2013, veo el stack de llamadas y me permite debuggear con VS

image

Si marca la variable htmlToDeploy, y selecciono Add Watch

image

image

Puedo ver el html que se renderiza en la página de forma fácil

image

Si veo en la página como queda,

image

sábado, 20 de septiembre de 2014

Cancelar un workflow de aprobación en el primer reject del workflow

Cuando se usa el portal web, permite elegir si se cancelará el workflow de aprobación en el primer reject del mismo (End on First Rejection)

image

Pero cuando usas Sharepoint Designer, tenés que setear la variable “CancelonChange” a Yes para que se termine el workflow de aprobación en el primer reject del proceso.

Si revisas el workflow de aprobación, puedes ver en la sección “Overral task process”

image

Y en la subsección “Al cambiarse el elemento”, pueden que tiene un IF que finaliza el proceso

image

Para solucionarlo, podemos ejecutar una acción de seteo de una variable del workflow antes del comienzo de aprobación (entonces Estableceer Variable:CancelonChanges como Yes)

Ej:

image

jueves, 18 de septiembre de 2014

Ejecutar manualmente una subscripción fallada en Reporting Services integrado en Sharepoint 2013 (Execute SSRS Subscription Manually in Sharepoint 2013 Integrate Mode)

Supongamos que la subscripción que habiamos hecho sobre un reporte en Sharepoint 2013 (Reporting Services modo integrado) fallo por algún motivo, y necesitamos ejecutarla manualmente

Para ello ingresamos en la sección de nuestro SQL de Sharepoint, y ejecutamos la siguiente query sobre la base ReportingService_Database (o cómo la hayan nombrado cuando crearon el servicio de SSRS en modo integrado)

image

Validamos cual es la row que hace referencia a nuestra subscripción (pueden ver el campo Description o MathData)

Por ejemplo, en este caso el SubscriptionID que me interesa es “79363907-67F5-44FA-80A1-39D3EA588557”

A continuación ingreso a la sección de SQL Agents/Jobs, y verifico los jobs con GUID, por ejemplo “8674C40B-03B7-4918-96D2-1C34EECF8427”

image

Click derecho Propiedades, voy a la solapa de Steps y edito el job step

image

Si ustedes ven en la sección de comandos, verán que se ejecuta, en este caso se ejecuta la subscripción “79363907-67F5-44FA-80A1-39D3EA588557”

image

De vuelta hacemos click derecho sobre el job, y seleccionamos “Start Job at Setp”

image

Y automáticamente se dispará la subscripción.

Podriamos haber ejecutado de forma manual mediante el siguiente comando en el SQL Managemente? Si claro, Por ejemplo:

exec [ReportingService_Database].dbo.AddEvent @EventType='TimedSubscription', @EventData='79363907-67f5-44fa-80a1-39d3ea588557'

domingo, 14 de septiembre de 2014

Cómo definir correctamente nuestros archivos de CSR (Client Side Rendering) o jslink

Un problema que suele pasar con jslink es cuando tenemos una página con dos o más webparts que cada uno tiene asignado un archivo jslink. Puede pasar que creamos nuestras funciones de override de campos/header/footer/grouping/etc con nombres iguales en cada archivo jslink.

Ej:

En el web part 1 llama al archivo documentosCSR.js

En el web part 2 llama al archivo taskCSR.js

Ambos archivos tienen un override de la view del campo “Title” y ambos archivos usan la función titleFieldOverride(ctx).

(function() {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    
    overrideCtx.Templates.Fields = {
        'Title': {'View': titleFieldOverride }
    };
    
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

function titleFieldOverride(ctx)
{

}

Que pasa en estos casos? El último archivo js que se cargue será el que prevalece, lo cual puede ocasionar errores dificiles de detectar.

Para ello, siempre crea los archivos jslink con funciones definidas en global namespaces de javascript. Los namespaces nos permiten definir variables, funciones dentro de un “contenedor” ( a efectos prácticos es un objeto ), la idea de trasfondo consiste en que cada archivo jslink utilice su propio namespace para que de esta forma no perdamos funcionalidad al “solapar” el código.

Veamos un ejemplo correcto.

En el archivo documentosCSR.js defino el código de la siguiente manera

var solutionDocumentosCSR = solutionDocumentosCSR || {};
solutionDocumentosCSR.Fields = (function () {
    
    function convertirFecha(fecha) {
        /* convierto la fecha al formato ddMMYYY */
    };
 
    return {
        titleFieldOverride: function (ctx) {
            var html = "<div><strong>" + ctx.CurrentItem.Title + "</strong></div>";
           //aca puedo usar la funcion convertirFecha la cual esta definida dentro del mismo namespace
            return html;
        }
    }
})();

(function() {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    
    overrideCtx.Templates.Fields = {
        'Title': {'View': solutionDocumentosCSR.Fields.titleFieldOverride }
    };
    
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

En el otro archivo  taskCSR.js defino el código de la siguiente manera

var solutionTasksCSR = solutionTasksCSR || {};
solutionTasksCSR.Fields = (function () {
    
    function convertirFecha(fecha) {
        /* convierto la fecha al formato mmDDyyyy */
    };
 
    return {
        titleFieldOverride: function (ctx) {
            var html = "<div><strong>" + ctx.CurrentItem.Title + "</strong></div>";
            //aca puedo usar la funcion convertirFecha la cual esta definida dentro del mismo namespace, y no se toma en cuenta la función definida en el otro namespace
            return html;
        }
    }
})();

(function() {
    var overrideCtx = {};
    overrideCtx.Templates = {};
    
    overrideCtx.Templates.Fields = {
        'Title': {'View': solutionTasksCSR.Fields.titleFieldOverride }
    };
    
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

sábado, 13 de septiembre de 2014

Cómo usar el plugin SPWidgets para subir documentos vía Jquery/SPServices en Sharepoint 2010

En nuestra página agregamos las referencias a los siguientes archivos:

jquery.js (http://jquery.com/download/)

jquery.SPServices.min.js (http://spservices.codeplex.com/)

jqueryui.min.js (http://jqueryui.com/download/)

/_layouts/1033/init.js

/_layouts/1033/sp.core.js

/_layouts/1033/sp.runtime.js

/_layouts/1033/sp.js

jquery.SPWidgets.min.js  (http://purtuga.github.io/SPWidgets/)

Después agregar las referencias a los archivos css de jQueryUI

En nuestra página agregamos un anchor que levante el siguiente popup

image

Para realizar esto, agregamos el siguiente div en nuestro código html

<div id="dialog-AddAttachments" title="Agregar adjuntos" style="display:none">   
        <b>Seleccione un archivo y presionar adjuntar.</b></br></br></br>

        <div style="height:350px;width:100%;padding:.5em;" id="file_upload"></div>

</div>

$( "#dialog-AddAttachments" ).dialog({
                autoOpen: false,
                resizable: false,
                draggable: false,
                width:450,
                height:180,
                modal: true               
});

El código anterior levanta el popup

$("#file_upload").SPControlUpload({
                listName: 'Documentos',               
                noFileErrorMessage: "No hay un archivo seleccionado!",
                selectFileMessage: "Click aquí para agregar un attachement...",
                uploadDoneMessage: "Se subió correctamente el archivo!",              
                onUploadDone: function(file){
                   
                }
});
El código anterior permite configurar el div para que el usuario pueda subir archivos a la librería “Documentos”.

image

Cómo usar el plugin SPWidgets para buscar usuarios con Jquery/SPServices (javascript people picker)

En nuestra página agregamos las referencias a los siguientes archivos:

jquery.js (http://jquery.com/download/)

jquery.SPServices.min.js (http://spservices.codeplex.com/)

jqueryui.min.js (http://jqueryui.com/download/)

/_layouts/1033/init.js

/_layouts/1033/sp.core.js

/_layouts/1033/sp.runtime.js

/_layouts/1033/sp.js

jquery.SPWidgets.min.js  (http://purtuga.github.io/SPWidgets/)

Después agregar las referencias a los archivos css de jqueryUI

En nuestra página agregamos un textbox con un icono de usuario, que al hacer click se muestra el siguiente popup

image

image

Para hacer esto, debermos tener el siguiente div.

<div id="dialog-message" title="Buscar usuario" style="display:none">   
        <b>Busque por mail,por sigla o por nombre. Es necesario al menos 3 caracteres para iniciar la búsqueda.</b></br></br></br>

        <input name="users" value="" style="width:350px!important" >   
</div>

Dentro del document.ready de jquery ejecutamos el siguiente código de javascript, que permite agregar toda la funcionalidad de búsqueda de usuarios estilo people picker de Sharepoint.

$("input[name='users']").pickSPUser({
        allowMultiples: false,
        meKeyword: "[me]",
        meKeywordLabel: "Current User",
        onPickUser: function(person){           
            var mail = GetMailfromSigla(person.accountName );
            if (mail != "")
                $('#' + inputSearchSelect).val(mail);
           
            $( "#dialog-message" ).dialog('close');
        }                     
    });       

En el caso que quieramos limpiar la búsqueda, podemos ejecutar el siguiente script.

$("input[name='users']").pickSPUser("method", "clear");

image

Una granja Sharepoint 2013 de 3 servidores sobre Azure de manera simple

Hace un tiempo había hecho un post de cómo crear un pequeño entorno de desarrollo de Sharepoint 2013 sobre azure: http://todosharepoint.blogspot.com.ar/2014/06/crear-un-entorno-de-desarrollo-de.html

En este caso usaremos una nuevo elemento de la galería que se disponibilizó hace poco para crear granjas de Sharepoint. Primero para poder utilizar la creación de granjas de Sharepoint 2013 sobre Azure, deberemos ingresar al portal nuevo de Azure.

image

La idea es crear una arquitectura de este estilo

SharePoint-Farm-in-Azure-8

agrego un nombre de Resource Group, nombre de administrador y password

image image image

imageimage

Si marcas la opción de “Enable High availability” te creará una granja de alta disponibilidad

spfarm_highavail

Después de unos minutos (variossss) se tiene la granja completa sobre Azure.

image

image

image

image

Revisa que tengas el acces role habilitado para nuestra cuenta de suscribción

image

Cuando abro una de las máquinas virtuales de Sharepoint, veo los siguientes iconos en el desktop

image

Si abro la sección de Servers in Farm en el CA.

image

En el caso de los DC y SQL, vemos en la sección Peer Resources las VM´s

image

Si veo la configuración del SQL Server

image

image

En el G están los logs de los datafiles

image

En el F están los datafiles

image

En el D, veo un warning de no usar esta partición para almacenar datos no temporarios

image

Los datafiles y logs de la tempdb están en el C

image

Revisando la configuración de la base, se ve que le aplicaron algunas configuraciones requeridas para que Sharepoint funcione correctamente, ej: deshabilitar estadísticas

image

MAXDOP = 1

image

Pero hay algunas que deberían haber configurado. Ej: Max y Min memory server

image

El fill factor también lo deberían haber configurado (80% para Sharepoint)

image

image

En el caso del DC, ejecuto el siguiente comando de PowerShell Get-DnsServer, y veo los siguientes datos.

Zonas de DNS

image

Si ejecuto el siguiente comando Get-DnsServerResourceRecord -ZoneName "contoso.com"

image

Si yo me enfoco en un A record, puedo ejecutar el siguiente comando:

Get-DnsServerResourceRecord -ZoneName "contoso.com" -Name "GROUPHASHA-SP”