SharePoint Tip #11: The Web Part Maintenance Page

In SharePoint, when an error occurs in a web part that prevents it to be rendered on the page, an error page is displayed to the user with a link to the web part maintenance page. This page lists all the web parts that were added to the web part page and their current state, allowing you to remove web part that is causing the error. 

Although this page is very useful, accessing it is not as easy as one would expect. There are two ways to do so. 

Method 1

  1. Go to Site Actions > View All Site Content
  2. Open the Pages list that stores the page about which we wish to get information
  3. Using the file's context menu, select the Edit Properties option
  4. In the bottom of the properties page, there is a link to the web part maintenance page

Method 2

Add ?contents=1 to the URL of the page about which you want to get web part maintenance information.

Example
If the page has the address http://server/site/mypage.aspx, you can access the web part maintenance page using the address http://server/site/mypage.aspx?contents=1.

SharePoint Tip #10: Using RunWithElevatedPrivileges()

When developing SharePoint (MOSS or WSS) componentes, you might have to write code that some users won't have permissions to execute. For instance, if an event handler associated with a list needs to access an item of another list, and the user that caused the event to be fired has no permissions to access it, SharePoint will throw an access denied exception. 

The solution to this kind of problems is the RunWithElevatedPrivileges of the SPSecurity class (included in the assembly Microsoft.SharePoint.dll). This method allows the execution of code as the application pool identity account and, for that reason, should be used with caution. 

Example
SPSecurity.RunWithElevatedPrivileges(delegate()
{
    // begin code to be executed with app pool account
    SPSite site = new SPSite("http://server/site");
    SPWeb web = site.OpenWeb();

    SPList
lista = web.Lists["ListaAdmin"];

    web.Dispose();
    site.Dispose();
    // end of code to be executed with app pool account
}

Attention: I placed the creation of the SPSite object inside the elevated privilege zone on purpose. The reason for this is that, if the SPSite object is created outside this zone (when the user still has its original permissions) all the actions that are executed on SPWeb or SPList objects obtained from that SPSite object, even if inside the privileged zone, will use the original permissions of the user. So, it is mandatory that the creation of SPSite objects (and similars) is placed inside the elevated privilege code block. 

SharePoint Tip #9: Utilizar o DisableEventFiring() e o EnableEventFiring()

Num event handler de um lista é frequente haver a necessidade de actualizar um item recorrendo ao método Update() da classe SPListItem. Quando este método é chamado são disparados dois novos eventos, ItemUpdating e ItemUpdated. É fácil perceber que, se o event handler em causa for para um destes eventos, o facto de provocar o disparo dos eventos vai levar a que se entre num ciclo potencialmente infinito (não o é porque o SharePoint acaba por interrompê-lo).

Solução: para evitar esta situação podemos chamar o método DisableEventFiring() no início do event handler, e o método EnableEventFiring() no final do mesmo, fazendo com que não sejam disparados novos eventos mesmo que se chame o método Update() do item.

SharePoint Tip #8: BeforeProperties e AfterProperties em Event Handlers

Os Event Handlers das listas recebem como parâmetro um objecto SPListEventProperties através do qual podemos aceder ao item da lista, ao ID da lista bem como a outros objectos relevantes para o tratamento do evento. De entre estes objectos estão duas colecções de propriedades, as BeforeProperties e as AfterProperties que, como os seus nomes indicam, correspondem ao conjunto das propriedades do item antes e depois da ocorrência do evento.

Apesar das enormes vantagens que estas colecções de propriedades nos trazem, há alguns cuidados a ter na sua utilização:

  1. Num evento ItemAdding, as BeforeProperties ainda não existem uma vez que o item ainda não foi criado
  2. As BeforeProperties são apenas para leitura
  3. As AfterProperties são apenas para leitura nos eventos assíncronos (eventos –ed) como o ItemAdded ou ItemUpdated
  4. As AfterProperties podem ser alteradas em alguns eventos síncronos (eventos –ing) como o ItemAdding ou o ItemUpdating

Este último ponto é, na minha opinião, a maior vantagem na actualização destas colecções. Isto porque podemos actualizar as propriedades do item antes que este seja criado (no evento ItemAdding) ou mesmo depois de criado (no evento ItemUpdating) sem ser necessário chamar o método Update() e, portanto, sem incrementar a versão do item nem desencadear novos eventos de actualização.

SharePoint Tip #7: Utilizar o SystemUpdate()

Muitas vezes pretendemos fazer um Update a um item de uma lista de SharePoint mas não queremos que seja actualizada a data da última modificação e o utilizador responsável pela mesma. Nessas situações podemos utilizar o método SystemUpdate() da classe SPListItem, que faz a actualização do item sem modificar esses campos. Adicionalmente podemos utilizar a versão deste método com um parâmetro booleano que indica se a versão do item deve ser incrementada quando existe versionamento.

Atenção: apesar do nome, este método é executado com as credenciais do utilizador corrente portanto está sujeito às mesmas regras de execução do método Update().

O Unknown Document Type

Quando se associam Content Types a uma Document Library existe a possibilidade de definir que a Document Library aceita qualquer Content Type. Isso corresponde a associar um tipo especial de Content Type à Document Library chamado Unknown Document Type. A razão pela qual este Content Type existe prende-se com a forma como funcionam os Document Parsers do SharePoint e que passo a explicar com um exemplo.

Exemplo

Suponha-se que tenho uma Document Library designada Documentos de Entrada e outra chamada Documentos de Saída. Tenho também dois Content Types, um chamado Correio Normal, com os campos Data de Envio e Remetente, e outro chamado Correio Expresso, com o campos Data de Envio e Referência. O que acontece se eu criar um documento do tipo Correio Expresso na biblioteca Documentos de Entrada, preencher as suas propriedades, e depois o copiar para a biblioteca Documentos de Saída?

Situação 1: À biblioteca Documentos de Entrada estão associados ambos os Content Types, mas à biblioteca Documentos de Saída não estão associados quaisquer Content Types.

Neste caso, porque a biblioteca Documentos de Saída não permite Content Types, o documento vai perder a sua associação ao Content Type mantendo apenas os valores dos campos que sejam mapeados nos campos do Default Content Type da biblioteca. Ou seja, neste exemplo perderia todas as suas propriedades e respectivos valores.

Situação 2: À biblioteca Documentos de Entrada estão associados ambos os Content Types, mas à biblioteca Documentos de Saída está apenas associado o tipo Correio Normal.

Nesta situação, a biblioteca Documentos de Saída permite a existência de Content Types mas não possui o tipo usado como base para o documento. Assim sendo, o documento não perde as suas propriedades mas o SharePoint apenas promove aquelas que possam ser mapeadas em campos da biblioteca. Ou seja, neste exemplo, seria promovido o valor do campo Data de Envio uma vez que é um campo também presente em ambos os Content Types.

É aqui que entra o Unknown Document Type. Para não perdermos as propriedades dos documentos quando estes são copiados entre Document Libraries, as bibliotecas de destino têm que ter pelo menos um Content Type associado. No entanto, nem sempre queremos definir um Content Type específico para todas as bibliotecas. Nessa altura devemos usar o Unknown Document Type que, por si só, não possui quaisquer propriedades mas, pelo facto de estar associado à biblioteca, impede que o SharePoint apague os metadados dos documentos como aconteceu na situação 1.

SharePoint Tip #6: Conteúdo de um campo do tipo MultiChoice

O SharePoint permite configurar um campo do tipo Choice para aceitar a selecção de múltiplas alternativas, passando a ser do tipo MultiChoice (SPFieldMultiChoice). Uma vez que se trata apenas de uma coluna numa lista, o SharePoint guarda todas as selecções numa só string, separando cada uma pelos caracteres ponto-e-vírgula e cardinal (;#), como é feito com os campos do tipo lookup.

Exemplo:
Se num campo de múltipla escolha, seleccionarmos as hipóteses Lisboa, Porto e Coimbra, o conteúdo do campo MultiChoice será:

Lisboa;#Porto;#Coimbra

SharePoint Tip #5: Conteúdo de um campo do tipo Lookup

Em SharePoint, utilizam-se campos do tipo Lookup (SPFieldLookup) quando se pretende que exista uma relação 1-N entre duas listas. Ao colocar-se um campo deste tipo numa lista A, é-nos dada a possibilidade de seleccionar uma lista B do mesmo site e um campo dessa lista. São os valores assumidos por esse campo da lista B que aparecem na dropdown list quando o utilizador edita o campo lookup na lista A.

Depois desta pequena introdução, é importante perceber como é que o SharePoint guarda os valores deste tipo de campos. Uma vez que a única forma de identificar univocamente um item de uma lista é através do seu ID (isto porque não podemos garantir que o utilizador que populou a lista não repetiu valores nos restantes campos), o SharePoint tem que guardar este valor no campo lookup. Mas para facilitar, guarda também o valor do campo descritivo (o tal que foi seleccionado na configuração do lookup), separando ambos os valores pelos caracteres ponto-e-vígula e cardinal (;#).

Exemplo:
Se no campo lookup Marca for seleccionado o item com a descrição Porsche, que possui o ID 5 na lista relacionada, o que fica guardado no campo lookup é:

5;#Porsche