Category Archives: Desenvolvimento do SharePoint

HTTP 406 Erro ao usar $http.get Angular contra pontos de extremidade de resto do SharePoint

Atualização: Marc AD ndersson apontou este grande pedaço de informação: http://Blogs.Office.com/2014/08/13/JSON-Light-support-REST-SharePoint-API-Released/. Isso explica muita coisa :).

Isso pode ser o pior título de um post de blog já! Seja como for.

Normalmente faço tudo do meu prototipagem contra uma instância O365. Eu tenho minha instância pessoal para que não tenho que me preocupar que afetam qualquer outro. Como um aparte – lembra quando nós chamamos carreg em torno de máquinas virtuais em nossos laptops com musgo – SQL Server, IIS, decidindo vs Hyper-V. VMWare? Seja como for...

Eu tinha desenvolvido um aplicativo usando Angular neste ambiente que faz, entre outras coisas, Isso:

$http.Get(serverUrl)
.sucesso(função(dados, estatuto, cabeçalhos, config) {

var getLinksResponse = dados;

getLinksResponse.value.forEach(função(theResult) {

// e assim por diante e então espuma

Isto estava funcionando muito bem em dois ambientes diferentes do SharePoint online. No entanto, Quando o meu colega é portado para uma instância de Cloudshare, Ele estava ficando um HTTP 406 erro (Qual foi a primeira vez que tive aquele, Então... yay, Eu suponho). Nós fizemos um pouco de pesquisa e notei que o cabeçalho de "Aceitar" estava fora. SharePoint online foi perfeitamente feliz com:

Aceitar: application/json

Mas a instância cloudshare (Qual é o SP na prem, hospedado em um servidor virtual) queria o clássico "odata = verbose" adicionado em também:

Aceitar: application/json;OData = verbose

Para corrigir isso, adicionamos o cabeçalho como tal:

config var = {cabeçalhos: {
'Aceitar': ' application/json;OData = verbose'
}
};

$http.Get(serverUrl,config)
.sucesso(função(dados, estatuto, cabeçalhos, config) {

var getLinksResponse = dados;

getLinksResponse.value.forEach(função(theResult) {

// e assim por diante e então espuma

Que livrou o 406, Mas isso também mudou o formato da resposta. Era mais... detalhado. (haha!) Mais mudanças foram necessárias e aqui está o resultado final:

config var = {cabeçalhos: {
'Aceitar': ' application/json;OData = verbose'
}
};

$http.Get(serverUrl,config)
.sucesso(função(dados, estatuto, cabeçalhos, config) {

var getLinksResponse = dados;

getLinksResponse.d.Results.forEach(função(theResult) {

// e assim por diante e então espuma

Este só se transformou em um 30 minuto problema para nós, Então nós tivemos sorte. Espero que alguém acha isso útil.

</fim>

Crescente consciência / Adoção de Frameworks JavaScript

Meu colega, Javed Ansari (http://www.bigapplesharepoint.com/team?showExpertName=Javed%20Ansari&rsource=pgblog), escreveu um curto Resumo blog post sobre frameworks ele gosta ou pelo menos tem usado com o SharePoint: http://www.bigapplesharepoint.com/pages/View-An-Insight.aspx?BlogID=53&rsource=PGBlog).

jQuery parece ter sido o vencedor no campo, por assim dizer, Há anos, Mas os outros são mais novos e Alambiques tipo de batem-, como Angular. (SPServices, É claro, é um salva-vidas há anos e continuará a ser, então eu acho que).

O que as pessoas estão usando? Eles são focados mais em ferramentas da Microsoft (CSOM / JSOM) ou movendo-se mais em direção Angular, Nocaute, Ember, etc?

Eu tenho uma crescente polarização em direção a essas estruturas não-Microsoft. Acho que as coisas MSFT são mais difícil e mais difícil de trabalhar com, exigindo quase tanto de curva de aprendizagem como estilo antigo colaborador de lado do servidor.

Postar um comentário aqui ou no Big Apple SharePoint Se você quer discutir (Big Apple terá mais probabilidade de uma boa discussão).

</fim>

Trabalhos de Timer do SharePoint do Site coleção configuração de giro

Meu colega, Ashish Patel, Escrevi um post de blog descrevendo uma arquitetura de trabalho flexível temporizador Isso permite alguma flexibilidade legal para apoiar as tarefas demoradas e/ou relatórios.  Em suas palavras:

1. Analisando Checked out arquivos e enviar lembretes para os indivíduos, se o número de dias (desde que o arquivo foi check-out) exceder certos limites de limiar

2. Remover links de outros conteúdos, quando um determinado conteúdo é removido ou Arquivado do sistema

3. Usuário deseja ver todos os alertas que ele inscrito em todas as webs do conjunto de sites

4. Enviando um lembretes aos autores para rever o conteúdo quando um tempo de revisão foi especificado no conteúdo e que data está se aproximando.

Bem, a lista continua...

– Veja mais em: http://www.bigapplesharepoint.com/ páginas/View-An-Insight.aspx?BlogID=40#sthash.7cKuiwly.dpuf

Há momentos em meu passado quando tendo algo como isso teria sido muito útil.

</fim>

Como: Configurar o teste unitário e cobertura de teste com QUnit.js e Blanket.js para um escritório 365 App do SharePoint

Intro

Eu estive explorando testes de unidade e teste de cobertura para JavaScript como eu trabalho em um novo aplicativo do SharePoint para SharePoint online no escritório 365 Suite.  Os caminhos de pesquisa óbvio levaram-me a Qunit.js e logo depois que, Para Blanket.js.

QUnit deixe-me criar testes de unidade e agrupá-los em módulos.  Um módulo é apenas uma maneira simples de organizar testes relacionados. (Não tenho certeza se que vou usá-lo como pretendido, Mas funcionou para mim até agora com o pequeno conjunto de testes que definiu até agora).

Blanket.js integra com Qunit e ele vai me mostrar as linhas reais de JavaScript que foram – e mais importante – não foram realmente executadas no decurso da execução dos testes.  Esta é a "cobertura" – linhas que executado são cobertas pelo teste, enquanto outros não são.

Entre a criação de casos de teste boas e visualização de cobertura, Podemos reduzir o risco de que nosso código escondido defeitos.  Bons tempos.

Qunit

Supondo que você tenha seu Visual Studio projeto configurado, Comece baixando o pacote de instalação JavaScript http://qunitjs.com.  Adicione o JavaScript e CSS correspondente à sua solução.  Mina parece com isso:

image

Figura 1

Como você pode ver, Eu estava usando 1.13.0 na época, eu escrevi este post de blog. Não se esqueça de baixar e adicionar o arquivo CSS.

Que saia do caminho, próximo passo é criar algum tipo de equipamento de teste e referenciar os bits Qunit.  Estou testando um monte de funções em um arquivo de script chamado "QuizUtil.js", então eu criei uma página HTML chamada "QuizUtil_test.html", como mostrado:

image Figura 2

Aqui está o código:

<!DOCTYPE HTML>
<HTML xmlns= "http://www.w3.org/TR/1998/REC-xml-19980210 1999/xhtml">
<cabeça>
    <título>Teste de QuizUtil com Qunit</título>
    <link rel= "stylesheet" href="../CSS/qunit-1.13.0.css" />
    <script tipo= text/javascript"" src="QuizUtil.js" dados-capa></script>
    <script type ="text/javascript" src ="qunit-1.13.0.js"></script>
    <script type ="text/javascript" src ="blanket.min.js"></script>

    <script>
        módulo("getIDFromLookup");
        teste("QuizUtil getIDFromLookupField", função () {
            var goodValue = "1;#Paul Galvin";

            igual(getIDFromLookupField(goodValue) + 1, 2), "ID do [" + goodValue + "] + 1 deve ser 2";
            igual(getIDFromLookupField(indefinido), indefinido, "O argumento de entrada indefinido deve retornar o resultado indefinido.");
            igual(getIDFromLookupField(""), indefinido, "O argumento de entrada vazio deve retornar um valor indefinido.");
            igual(getIDFromLookupField("gobbledigood3-thq;ada dkvn;skfja sdjfbvubvqrubqer0873407t534piutheqw;vn"), indefinido,"Deve sempre retornar um conversível de resultado para um número inteiro");
            igual(getIDFromLookupField("2;#outra pessoa"), "2", "Verificação [2;#outra pessoa].");
            igual(getIDFromLookupField("9834524;#valor longo"), "9834524", "Teste de grande valor.");
            notEqual(getIDFromLookupField("5;#qualquer um", 6), 6, "Testar um notEqual (5 Não é igual a 6 para esta amostra: [5;#qualquer um]");

        });

        módulo("htmlEscape");
        teste("QuizUtil htmlEscape()", função () {
            igual(htmlEscape("<"), "&lt;", "Escapando um menos que o operador ('<')");
            igual(htmlEscape("<classe div =  "someclass">Algum texto</div>"), "&lt;classe div =&quot;SomeClass&quot;&gt;Algum texto&lt;/div&gt;", "Sequência de teste mais complexa.");
        });

        módulo("getDateAsCaml");
        teste("QuizUtil getDateAsCaml()", função () {
            igual(getDateAsCaml(Novo Data("31/12/2013")), "2013-12-31T:00:00:00", "Teste codificada data: [12/31/2013]");
            igual(getDateAsCaml(Novo Data("01/05/2014")), "2014-01-05T:00:00:00", "Teste codificada data: [01/05/2014]");
            igual(getDateAsCaml(Novo Data("01/31/2014")), "2014-01-31T:00:00:00", "Teste codificada data: [01/31/2014]");
            igual(getTodayAsCaml(), getDateAsCaml(Novo Data()), "getTodayAsCaml() deve ser igual getDateAsCaml(nova data())");
            igual(getDateAsCaml("valor absurdo"), indefinido, "Tente obter a data de um valor absurdo.");
            igual(getDateAsCaml(indefinido), indefinido, "Tente obter a data da [indefinido] Data.");
        });

        módulo("getParameterByName");
        teste("QuizUtil getParameterByName (da cadeia de caracteres de consulta)", função () {
            igual(getParameterByName(indefinido), indefinido, "Tentar obter parâmetro indefinido deve retornar indefinido.");
            igual(getParameterByName("não existe"), indefinido, "Tentar obter o valor do parâmetro, quando sabemos que o parâmetro não existe.");

        });

        módulo("Cookies");
        teste("QuizUtil várias funções do cookie.", função () {
            igual(setCookie("teste", "1", -1), getCookieValue("teste"), "Obter um cookie eu definir deve funcionar.");
            igual(setCookie("anycookie", "1", -1), verdadeiro, "Definir uma cozedura válido deve retornar 'verdadeiro'.");
            igual(setCookie("nome do cookie louco !@#$%"%\^&*(()?/><.,", "1", -1), verdadeiro, "Definir um nome de cookie ruim deve retornar 'falso'.");
            igual(setCookie(indefinido, "1", -1), indefinido, "Passando indefinido como o nome do cookie.");
            igual(getCookieValue("não existe"), "", "Cookie não existe teste.");
        });

    </script>
</cabeça>
<corpo>
    <div ID= "qunit"></div>
    <div ID= "qunit-dispositivo elétrico"></div>

</corpo>
</HTML>

Existem várias coisas a acontecer aqui:

  1. Referenciando o meu código (QuizUtil.js)
  2. Referência Qunity.js
  3. Definição de alguns módulos (getIDFromLookup, Cookies, e outros)
  4. Colocando um <div> cuja ID é "qunit".

Em seguida, Só parar nesta página e você obter algo como isto:

image

Figura 3

Se você olhar no topo, Você tem algumas opções, dois dos quais são interessantes:

  • Ocultar passada testes: Bem óbvio.  Pode ajudar o seu olho vê apenas as áreas de problema e não um monte de desordem.
  • Módulo: (Deixe cair para baixo): Isso filtrará os testes até apenas os grupos de testes que você quer.

Quanto os testes se-alguns comentários:

  • Escusado será dizer que você precisa para escrever seu código de tal forma que é testável em primeiro lugar.  Usando a ferramenta pode ajudar a impor essa disciplina. Por exemplo, Eu tinha uma função chamada "getTodayAsCaml()”.  Isso não é muito testável, uma vez que não leva nenhum argumento de entrada e para testá-lo para a igualdade, precisamos atualizar constantemente o código de teste para refletir a data atual.  Eu refatorado isso adicionando um parâmetro de entrada de dados, em seguida, passando a data atual, quando eu quero a data atual no formato do CAML.
  • O quadro de Qunit documentos seus próprios testes e parece bastante robusto.  Ele pode fazer coisas simples, como teste de igualdade e também tem suporte para chamadas de estilo ajax ("real" ou fictícios usando seu favorito mocker).
  • Passando pelo processo também força você a pensar em casos extremos – o que acontece com o "indefinido" ou null é passado para uma função.  Torna absolutamente simples testar esses cenários para fora.  Coisas boas.

Cobertura com Blanket.js

Blanket.js complementa Qunit seguindo as linhas reais de código que executar durante o curso da executando os testes.  Então mesmo que é um aplicativo totalmente separado integra direito em Qunit, Ele joga muito bem – parece que é um app sem emenda.

Isto é blanket.js em ação:

image Figura 4

image

Figura 5

(Você realmente tem que clicar sobre a opção "Ativar a cobertura" no topo [Ver figura 3] para permitir isto.)

As linhas realçadas em figura 5 Não foram executados por qualquer um dos meus testes, Então eu preciso elaborar um teste que faz com que eles executar se quero cobertura completa.

Se blanket.js a trabalhar, seguindo estes passos:

  1. Baixá-lo http://blanketjs.org/.
  2. Adicioná-lo ao seu projeto
  3. Atualize sua página de equipamento de teste (QuizUtil_test.html no meu caso) como segue:
    1. O código de referência
    2. Decore seu <script> referência como este:
    <script tipo= text/javascript"" src="QuizUtil.js" dados-capa></script>

Blanket.js pega o atributo "dados-capa" e faz sua mágica.  Ganchos em Qunit, atualiza a interface do usuário para adicionar a opção "Ativar cobertura" e voila!

Resumo (TL; DR)

Use Qunit para escrever seus casos de teste.

  • Faça o download
  • Adicioná-lo ao seu projeto
  • Escrever uma página de teste arnês
  • Criar seus testes
    • Alguns dos seu código seja testável refatorar
    • Ser criativo!  Acho que de loucura, impossíveis cenários e testá-los de qualquer maneira.

Use blanket.js para garantir a cobertura

  • Certifique-se de que qunit está funcionando
  • Baixar blanket.js e adicioná-lo ao seu projeto
  • Adicioná-lo à sua página de equipamento de teste:
    • Adicionar uma referência a blanket.js
    • Adicionar um atributo "dados-capa" para seus <script> Tag
  • Executar testes Qunit.

Eu nunca fiz isso antes e tinha umas coisas rudimentares, trabalhando em um punhado de horas. 

Teste feliz!

</fim>

undefinedSubscreva ao meu blog.

Siga-me no Twitter em http://www.twitter.com/pagalvin

Lists. asmx, GetList e "valor não pode ser nulo”

Descobri hoje que o GetList() Método em lists. asmx serviço da Web tem de ser chamado com muito cuidado ou é propenso ao lançar uma misteriosa exceção "Valor não pode ser nulo" (e que está assumindo que você pode passar a mensagem de erro genérico ainda pior, "Exceção do tipo ' Microsoft.SharePoint.SoapServer.SoapServerException’ foi lançada.")  Especificamente, Achei que você não pode fornecer qualquer tipo de prefixo sobre o método GetList.  O seguinte trecho de jQuery ilustra o ponto:

image

Se você fizer isso, o serviço web responde com "Valor não pode ser nulo" como por isso Fiddler-desde transcrição HTTP:

<?XML version = "1.0" Encoding = "utf-8"?>
  <sabão:Envelope
     xmlns:sabão ="
http://schemas.xmlsoap.org/soap/envelope/"    
     xmlns:xsi = "
http://www.w3.org/2001/XMLSchema-instance
     xmlns:XSD ="
http://www.w3.org/2001/XMLSchema">

  <sabão:Corpo>
    <sabão:Falhas>
      <FaultCode>sabão:Servidor</FaultCode>
      <FaultString>
        Exceção do tipo ' Microsoft.SharePoint.SoapServer.SoapServerException’ foi lançada.
      </FaultString>
      <Detalhes>
        <ErrorString xmlns ="
http://schemas.Microsoft.com/SharePoint/SOAP/">
Valor não pode ser nulo.
        </ErrorString>
      </Detalhes>
    </sabão:Falhas>
  </sabão:Corpo>
</sabão:Envelope>

É claro, Você provavelmente não iria adicionar o prefixo "s0" em seu próprio país, mas algumas ferramentas são propensas a fazê-lo (como o Eclipse).

Isto é tanto mais confuso / frustrante porque outros métodos toleram prefixos.  Por exemplo, o GetListCollection Método não se importa se for prefixado, mesmo com prefixos de disparates como "xyzzy":

image

Este "valor não pode ser nulo" parece bastante comum com lists. asmx tão esperançosamente isto ajudará alguém fora no futuro.

</fim>

Subscreva ao meu blog.

Siga-me no Twitter em http://www.twitter.com/pagalvin

Infinitamente aninhando <div> Tags e jQuery

Este parece ser um tema tão excêntrico, Não tenho certeza realmente vale a pena blogar sobre, mas que nunca deixou de me antes, Então, aqui vamos nós Sorriso

Estou trabalhando fora de um projeto onde estou puxando alguns dados de uma pesquisa, embalagem em uma mensagem de XML e, em seguida, o XML é, finalmente, transformada em HTML através do XSLT.  Há um monte de jQuery envolvido, um pouco de que implementa algumas funcionalidades das tabulações.  Quando você clica em uma guia (realmente, uma <div>), jQuery chama Hide() e show() em várias divs (o carregamento da página inicial baixa todo o conteúdo assim lá não são nenhuma postagens neste caso).

Um monte de horas atrás, na guia comutação lógica começou a se comportar de forma irregular e ele não iria mostrar um dos meus guias.  Eu finalmente seguiu para baixo para o fato de que explorer internet (pelo menos) pensa-se que o <div> marcas aninhadas até agora, muito mais profundo do que se destinam.Mostra barra de ferramentas do desenvolvedor:

-<div id = "Tab1Content">
  -<div>
    -<div>
      -<div id = "Tab2Content">
        -<div>
           …………………………
                   </div>  <— Finalmente mostrando ele foi fechado todo o caminho aqui!

Assim, se eu fiz um $("# Tab1Content").esconder(), Eu também esconderia Tab2 e nunca poderia mostrar Tab2 se eu não mostrar também Tab1.  Copiei e colei o código em visual studio e ele mostrou tudo de forro da div acima agradàvel, exatamente como eles deveriam estar fazendo, parecido com isto:

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

Eu bati minha cabeça contra a parede por um tempo e notei que no HTML real código foi gerando um monte de vazio <div> marcas, como:

<corpo>

  <div id = "Tab1Content">

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

  </div>

  <div id = "Tab2Content">

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

  </div>

</corpo>

(O acima é waaaaaaaaaaaay simplificado.  As tags div vazia são totalmente válidas. Alguns dos meus <div> marcas estavam cheias de conteúdo, mas muitos outros não foram.  Cheguei à conclusão de que meu <XSL:for-each> directivas foram emitindo a forma curta div marcas quando o xsl:for each não ' encontrar qualquer dados.  Forcei um comentário HTML na saída, como mostrado:

image

 

Depois que eu fiz que, o div alinhado perfeitamente e meu guia comutação começou a trabalhar.

Como sempre, Espero que isso ajude alguém em um beliscão.

</fim>

Subscreva ao meu blog.

Siga-me no Twitter em http://www.twitter.com/pagalvin

Uma das causas para "O criador desta falha não especificou um motivo.”

Eu tenho feito muito trabalho com a pesquisa do SharePoint ultimamente e especificamente o KeywordQuery KeywordQuery classe, Propriedades e métodos.

Se você deseja que o conjunto de resultados para retornar resultados além dos suspeitos do costume (Consulte aqui), adicioná-lo à coleção SelectedProperties, como em:

myKeywordQuery.SelectProperties.Add("xyzzy");

Muito obrigado e uma ponta do chapéu a Corey Roth and Este post do blog extremamente útil (http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2008/02/19/how-to-use-the-moss-enterprise-search-keywordquery-class.aspx)

No meu caso, "xyzzy" não é realmente uma propriedade gerenciada.  Quando eu adicionei-a SelectedProperties de qualquer forma, SharePoint atirou um dos meu favorito sempre exceções de tempo de execução:

"O criador desta falha não especificou um motivo."

Eu gosto especialmente a capital "R" no razão.  Isso soa-me como o.LÍQUIDA equivalente de"Eu não tenho nenhuma boca, e eu deve gritar.”

</fim>

Subscreva ao meu blog.

Siga-me no Twitter em http://www.twitter.com/pagalvin

Referência útil: Resultados de padrão de pesquisa KeywordQuery

Quando você chamar Execute() Método em um KeywordQuery, Você pode criar um ResultTable baseado em ResultType.RelevantResults.  Este trecho de código ilustra o que quero dizer:

ResultTableCollection resultsTableCollection = myKeywordQuery.Execute();

ResultTable searchResultsTable = resultsTableCollection[ResultType.RelevantResults];

A tabela resultante terá as seguintes colunas de informações: 

WorkId
Classificação
Título
Autor
Tamanho
Caminho
Descrição
Gravação
Nome do site
CollapsingStatus de
HitHighlightedSummary
HitHighlightedProperties
ContentClass
IsDocument
PictureThumbnailURL
ServerRedirectedURL

Esta lista eu derivado um SharePoint 2010 meio ambiente, Enterprise edition.  Espero que seja útil a alguém no futuro.

</fim>

Subscreva ao meu blog.

Siga-me no Twitter em http://www.twitter.com/pagalvin

Uma das razões para: "Falha ao extrair o arquivo cab da solução”

Enquanto trabalhava em uma web part visual studio projeto hoje, Eu fiz uma pequena re-org de alguns arquivos para ser colocado na pasta Layouts como parte do processo de implantação. Especificamente, Eu renomeado o arquivo. js de "TypeAhead.js" para "TypeAhead(antigos).js"  Eu pretendo removê-lo assim que seu sucessor "TypeAhead.js" prova correta.  Parecia que isso:

image

Isso causou imediatamente um problema com o visual studio quando tentei implantar o projeto:

Ocorreu um erro na etapa de implantação 'Adicionar solução': Falha ao extrair o arquivo cab da solução.

Gira para fora que você não deve colocar um parêntese em nomes de arquivo.  Eu removi o parens e que resolveu o problema.

</fim>

Subscreva ao meu blog.

Siga-me no Twitter em http://www.twitter.com/pagalvin