Kategori Arkiv: SharePoint udvikling

HTTP 406 Fejl når du bruger kantede $http.get mod SharePoint resten slutpunkter

Opdatering: Marc AD ndersson påpegede dette store stykke af info: http://Blogs.Office.com/2014/08/13/JSON-Light-support-rest-SharePoint-API-Released/. Det forklarer en masse :).

Det kan være den værste titlen på et blog-indlæg nogensinde! Anyhoo.

Jeg typisk gøre alle mine prototyping mod en O365-forekomst. Jeg har min personlige instans, så jeg ikke behøver at være bekymret om påvirker alle andre. Som en sidebemærkning--huske, når vi kalder udført omkring virtuelle maskiner på vores bærbare computere med mos-SQL Server, IIS, besluttende Hyper-V vs. VMWare? Anyhoo...

Jeg havde udviklet en app ved hjælp af kantede i dette miljø, der gør, blandt andet, Dette:

$http.get(serverUrl)
.succes(funktion(data, status, overskrifter, config) {

var getLinksResponse = data;

getLinksResponse.value.forEach(funktion(Myndigheden) {

// og så videre og så skum

Det virkede fint i to forskellige SharePoint online miljøer. Dog, Når min kollega porteret det til en forekomst af Cloudshare, Han fik en HTTP 406 fejl (der var første gang jeg nogensinde fik at man, så... yay, Jeg gætter). Vi gjorde en smule forskning og bemærket, at overskriften "Acceptere" var off. SharePoint online var helt tilfreds med:

Acceptere: ansøgning/json

Men cloudshare forekomsten (der er SP på prem, hostet i en virtuel server) ønskede klassiske "odata = verbose" tilføjet i samt:

Acceptere: ansøgning/json;OData = verbose

Hen til lave at, vi tilføjede i hovedet som sådan:

var config = {overskrifter: {
'Acceptere': «ansøgning/json;OData = verbose'
}
};

$http.get(serverUrl,config)
.succes(funktion(data, status, overskrifter, config) {

var getLinksResponse = data;

getLinksResponse.value.forEach(funktion(Myndigheden) {

// og så videre og så skum

Der fik befri for den 406, men det også ændret format af respons. Det var mere... verbose. (haha!) Flere ændringer var nødvendige og her er det endelige resultat:

var config = {overskrifter: {
'Acceptere': «ansøgning/json;OData = verbose'
}
};

$http.get(serverUrl,config)
.succes(funktion(data, status, overskrifter, config) {

var getLinksResponse = data;

getLinksResponse.d.Results.forEach(funktion(Myndigheden) {

// og så videre og så skum

Dette kun forvandlet til et 30 minut problem for os, så vi lucked ud. Forhåbentlig finder nogen dette nyttigt.

</slutningen>

Voksende bevidsthed / Vedtagelse af JavaScript rammer

Min kollega, Javed Ansari (http://www.bigapplesharepoint.com/team?showExpertName=Javed%20Ansari&rsource=pgblog), skrev et kort sammendrag blog-indlæg på rammer han kan lide eller i det mindste har været bruger med med SharePoint: http://www.bigapplesharepoint.com/pages/View-An-Insight.aspx?BlogID=53&rsource=PGBlog).

jQuery synes at have været victor på feltet, så at sige, for år nu, men de andre er nye og stills slags kæmper det, ligesom kantede. (SPServices, Selvfølgelig, har været et liv saver i år og vil fortsat være så jeg tror).

Hvad bruger folk? De fokuserer mere på Microsofts værktøjer (CSOM / JSOM) eller bevæger sig mere mod kantede, Knockout, Aske, osv?

Jeg har en voksende bias mod disse ikke-Microsoft rammer. Jeg tror MSFT ting er sværere og sværere at arbejde med, kræver næsten lige så meget af indlæringskurven som gammeldags serverside-dev.

Skriv en kommentar her eller over på Big Apple SharePoint Hvis du ønsker at diskutere (Big Apple vil have mere sandsynligheden for en god Diskussion).

</slutningen>

Spinning SharePoint Timer job fra samling Webstedskonfiguration

Min kollega, Ashish Patel, skrev et blog-indlæg beskriver en fleksibel timer job arkitektur Det giver nogle nice fleksibilitet til at understøtte langvarige opgaver og/eller rapporter.  I hans ord:

1. Analysere checket ud filer og at sende påmindelser til personerne, hvis antallet af dage (da filen blev tjekket ud) overskride en vis tærskel grænse

2. Fjerner links fra andre indhold, når en bestemt indhold er fjernet eller arkiveret fra systemet

3. Brugeren ønsker at se alle de beskeder, han tegnede i alle websteder i gruppen af websteder

4. At sende en påmindelser til forfattere at gennemgå indholdet, når en anmeldelse tid blev angivet i indholdet, og at datoen nærmer

Godt, listen fortsætter...

– Se mere på: http://www.bigapplesharepoint.com/ sider/se-en-Insight.aspx?BlogID=40#sthash.7cKuiwly.dpuf

Der er tidspunkter i min fortid, når at have noget som dette ville have været meget hjælpsom.

</slutningen>

Hvordan: Konfigurere enhedstest og testdækning med QUnit.js og Blanket.js For et kontor 365 SharePoint App

Intro

Jeg har været at udforske test af enheder og teste dækning for JavaScript, som jeg arbejder på en ny SharePoint app for SharePoint online i Office 365 Suite.  De åbenlyse forskning stier førte mig til Qunit.js og lige efter at, til Blanket.js.

QUnit Lad mig oprette unit-tests og gruppere dem i moduler.  Et modul er bare en simpel måde at organisere relaterede tests. (Jeg er ikke sikker på, jeg bruger det efter hensigten, men det virker for mig så langt med den lille sæt af tests jeg hidtil har defineret).

Blanket.js integrerer med Qunit og sig vil røbe sig mig de faktiske linjer af JavaScript, der var – og endnu vigtigere – var ikke faktisk udføres under kører test.  Dette er "dækning"-linjer, der udføres er omfattet af testen, mens andre ikke.

Mellem opsætning af god testcases og visning dækning, Vi kan reducere den risiko, at vores kode har skjulte defekter.  Gode tider.

Qunit

Forudsat at du har din Visual Studio projekt oprettet, starte med at hente JavaScript-pakke fra http://qunitjs.com.  Tilføje JavaScript og tilsvarende CSS til din løsning.  Mine ser sådan ud:

image

Figur 1

Som du kan se, Jeg var ved hjælp af 1.13.0 på tidspunktet skrev jeg dette blogindlæg. Glem ikke at downloade og tilføje CSS-fil.

Der ud af måde, næste skridt er at skabe en form for test sele og reference Qunit bits.  Jeg tester en masse funktioner i en scriptfil kaldet "QuizUtil.js", så jeg har oprettet en HTML-side kaldet "QuizUtil_test.html" som vist:

image Figur 2

Her er koden:

<!DOCTYPE HTML>
<HTML xmlns= "http://www.w3.org/ 1999/xhtml">
<hoved>
    <titel>QuizUtil test med Qunit</titel>
    <link rel= "stylesheet" href="../CSS/qunit-1.13.0.css" />
    <script type= text/javascript"" src="QuizUtil.js" data-cover></script>
    <script type ="text/javascript" src ="qunit-1.13.0.js"></script>
    <script type ="text/javascript" src ="blanket.min.js"></script>

    <script>
        modul("getIDFromLookup");
        test("QuizUtil getIDFromLookupField", funktion () {
            varians goodValue = "1;#Paul Galvin";

            lig(getIDFromLookupField(goodValue) + 1, 2), "ID af [" + goodValue + "] + 1 bør være 2";
            lig(getIDFromLookupField(ikke defineret), ikke defineret, "Udefineret inputargumentet skal returnere udefineret resultat.");
            lig(getIDFromLookupField(""), ikke defineret, "Tom inputargumentet skal returnere en udefineret værdi.");
            lig(getIDFromLookupField("gobbledigood3-thq;dkvn ada;skfja sdjfbvubvqrubqer0873407t534piutheqw;VN"), ikke defineret,"Skal altid returnere et resultat cabriolet til et heltal");
            lig(getIDFromLookupField("2;#en anden person"), "2", "Kontrol [2;#en anden person].");
            lig(getIDFromLookupField("9834524;#lang værdi"), "9834524", "Store værdi test.");
            notEqual(getIDFromLookupField("5;#nogen", 6), 6, "Test en notEqual (5 er ikke lig med 6 for denne prøve: [5;#nogen]");

        });

        modul("htmlEscape");
        test("QuizUtil htmlEscape()", funktion () {
            lig(htmlEscape("<"), "&lt;", "Undslippe et mindre end-operatør ('<')");
            lig(htmlEscape("<div class =  "someclass">Nogle tekst</div>"), "&lt;div class =&quot;someclass&quot;&gt;Nogle tekst&lt;/div&gt;", "Mere komplekse test streng.");
        });

        modul("getDateAsCaml");
        test("QuizUtil getDateAsCaml()", funktion () {
            lig(getDateAsCaml(nye Dato("12/31/2013")), "2013-12-31T:00:00:00", "Test hårdt kodet dato: [12/31/2013]");
            lig(getDateAsCaml(nye Dato("01/05/2014")), "2014-01-05T:00:00:00", "Test hårdt kodet dato: [01/05/2014]");
            lig(getDateAsCaml(nye Dato("01/31/2014")), "2014-01-31T:00:00:00", "Test hårdt kodet dato: [01/31/2014]");
            lig(getTodayAsCaml(), getDateAsCaml(nye Dato()), "getTodayAsCaml() skal lige getDateAsCaml(ny dato())");
            lig(getDateAsCaml("vrøvl værdi"), ikke defineret, "Prøv at få datoen for en sludder værdi.");
            lig(getDateAsCaml(ikke defineret), ikke defineret, "Prøv at få datoen for den [ikke defineret] dato.");
        });

        modul("getParameterByName");
        test("QuizUtil getParameterByName (fra forespørgselsstrengen.)", funktion () {
            lig(getParameterByName(ikke defineret), ikke defineret, "Prøv at få udefineret parameter skal returnere udefineret.");
            lig(getParameterByName("findes ikke"), ikke defineret, "Prøv at få værdi for parameteren, når vi ved, at parameteren ikke findes.");

        });

        modul("Cookies");
        test("QuizUtil forskellige cookie funktioner.", funktion () {
            lig(setCookie("test", "1", -1), getCookieValue("test"), "Få en cookie, jeg indstille bør arbejde.");
            lig(setCookie("anycookie", "1", -1), True, "Indstilling af en gyldig madlavning skal returnere 'sand'.");
            lig(setCookie("crazy Cookienavn !@#$%"%\^&*(()?/><.,", "1", -1), True, "Indstilling af en dårlig Cookienavn skal returnere 'false'.");
            lig(setCookie(ikke defineret, "1", -1), ikke defineret, "Passerer udefineret som cookie-navn.");
            lig(getCookieValue("findes ikke"), "", "Cookie ikke eksisterer test.");
        });

    </script>
</hoved>
<kroppen>
    <div id= "qunit"></div>
    <div id= "qunit-armatur"></div>

</kroppen>
</HTML>

Der er flere ting der sker her:

  1. Refererer til min kode (QuizUtil.js)
  2. Refererer til Qunity.js
  3. Definere nogle moduler (getIDFromLookup, Cookies, m.fl.)
  4. Placere en <div> Hvis ID er "qunit".

Derefter, Jeg trække bare op denne side og du får noget som dette:

image

Figur 3

Hvis du ser øverst, du har et par muligheder, hvoraf to er interessante:

  • Skjul bestået test: Temmelig indlysende.  Kan hjælpe øjet bare se problemområderne og ikke en masse rod.
  • Modul: (drop): Dette vil filtrere tests ned til netop disse grupper af tests du vil.

Hvad angår prøverne sig selv – et par kommentarer:

  • Det er en selvfølge at du skal skrive din kode, så det er testbare i første omgang.  Ved hjælp af værktøjet kan hjælpe med at håndhæve denne disciplin. For eksempel, Jeg havde en funktion kaldet "getTodayAsCaml()”.  Dette er ikke meget testbare, da det tager ingen inputargumentet og teste det for ligestilling, Vi skal konstant opdatere test-kode for at afspejle den aktuelle dato.  Jeg refactored det ved at tilføje en data input-parameteren derefter passerer den aktuelle dato, når jeg ønsker dags dato i CAML format.
  • Qunit rammer dokumenterer sine egne test og det synes temmelig robust.  Det kan gøre enkle ting som test for ligestilling og har også støtte til ajax stil opkald ("rigtige" eller hånet ved hjælp af din foretrukne mocker).
  • Gå gennem processen også tvinger dig til at tænke gennem kanten tilfælde – hvad sker der med "Udefineret" eller null er gået ind i en funktion.  Det gør det døde nemt at teste disse scenarier ud.  Gode ting.

Dækning med Blanket.js

Blanket.js supplerer Qunit ved at spore de faktiske linjer kode, der udføres i løbet af kører din test.  Det integrerer ret i Qunit så selv om det er en helt separat app, det spiller pænt-det ser virkelig ud som om det er en problemfri app.

Dette er blanket.js i aktion:

image Figur 4

image

Figur 5

(Du faktisk nødt til at klikke på afkrydsningsfeltet "Aktiver dækning" øverst [Se figur 3] at muliggøre dette.)

De fremhævede linjer i figur 5 ikke er blevet henrettet af nogen af mine tests, så jeg nødt til at udtænke en test, der forårsager dem til at udføre hvis jeg ønsker fuld dækning.

Få blanket.js arbejde ved at følge disse trin:

  1. Downloade det fra http://blanketjs.org/.
  2. Føje det til dit projekt
  3. Opdatere din testside sele (QuizUtil_test.html i mit tilfælde) som følger:
    1. Reference koden
    2. Dekorere din <script> reference som denne:
    <script type= text/javascript"" src="QuizUtil.js" data-cover></script>

Blanket.js opfanger attributten "data-cover" og gør sin magi.  Det kroge til Qunit, opdaterer UI for at tilføje indstillingen "Aktiver dækning" og voila!

Resumé (TL; DR)

Brug Qunit til at skrive din prøvesager.

  • Download det
  • Føje det til dit projekt
  • Skrive en test sele side
  • Oprette din analyser
    • Refactor nogle af jeres kode hen til blive testbare
    • Være kreativ!  Tænk på crazy, umuligt scenarier og teste dem alligevel.

Brug blanket.js til at sikre dækning

  • Kontroller, at Qunit fungerer
  • Download blanket.js og føje den til dit projekt
  • Føje det til din testside sele:
    • Tilføjelse af en henvisning til blanket.js
    • Tilføje en "data-cover" attribut til din <script> Tag
  • Køre din Qunit test.

Jeg har aldrig gjorde noget af dette før og havde nogle rudimentære ting arbejder i en håndfuld timer. 

Happy test!

</slutningen>

undefinedAbonner på min blog.

Følg mig på kvidre på http://www.twitter.com/pagalvin

Lists.asmx, GetList og "værdi kan ikke være null”

Jeg opdagede i dag, GetList() metode i lists.asmx webtjenesten har kaldt meget omhyggeligt, eller det er tilbøjelige til at smide en mystisk "Værdi kan ikke være null" undtagelse (og antages kan du få forbi den endnu værre generiske fejlmeddelelse, "Undtagelse af typen ' Microsoft.SharePoint.SoapServer.SoapServerException’ der blev udløst.")  Specifikt, Jeg fandt, at du ikke kan give nogen form for præfiks på metoden GetList.  Den følgende jQuery snippet illustrerer punktet:

image

Hvis du gør det, Webtjenesten svarer med "Værdi kan ikke være null" som pr. dette spillemand-forudsat http-transcript:

<?XML version = "1.0" encoding = "utf-8"?>
  <SOAP:Konvolut
     xmlns:SOAP ="
http://schemas.xmlsoap.org/SOAP/Envelope/"    
     xmlns:xsi = "
http://www.w3.org/2001/XMLSchema-instance
     xmlns:XSD ="
http://www.w3.org/2001/XMLSchema">

  <SOAP:Organ>
    <SOAP:Fejl>
      <faultcode>SOAP:Server</faultcode>
      <faultString>
        Undtagelse af typen ' Microsoft.SharePoint.SoapServer.SoapServerException’ der blev udløst.
      </faultString>
      <detaljer>
        <ErrorString xmlns ="
http://schemas.Microsoft.com/SharePoint/SOAP/">
Værdi må ikke være null.
        </ErrorString>
      </detaljer>
    </SOAP:Fejl>
  </SOAP:Organ>
</SOAP:Konvolut>

Selvfølgelig, du ville sandsynligvis tilføje denne "s0" præfiks på dine egne, men nogle værktøjer er tilbøjelige til at gøre det. (ligesom Eclipse).

Dette er så meget desto mere forvirrende / frustrerende fordi andre metoder tolerere præfikser.  For eksempel, den GetListCollection metode huske ikke, hvis det er blevet præfikset, selv med nonsens præfikser ligesom "xyzzy":

image

Dette "værdi ikke kan være null" forekommer temmelig fælles med lists.asmx så forhåbentlig dette vil hjælpe en anden person ud i fremtiden.

</slutningen>

Abonner på min blog.

Følg mig på kvidre på http://www.twitter.com/pagalvin

Uendelige indlejring <div> Mærker og jQuery

Dette synes at være sådan en oddball emne, Jeg er ikke sikker på, at det er virkelig værd at blogging om, men der er aldrig stoppet mig før, så her gå vi Smil

Jeg arbejder på et projekt, hvor jeg trækker nogle data fra en søgning, emballage det i en XML-besked og derefter at XML er i sidste ende omdannes til HTML via XSLT.  Der er en masse af jQuery involveret, en smule som implementerer nogle Tabber funktionalitet.  Når du klikker på en fane (Virkelig, en <div>), jQuery påberåber sig .hide() og .show() på forskellige divs (den første side belastning henter alt indholdet, så der er ingen postbacks i dette tilfælde).

En flok af timer siden, fanen skifte logik begyndte at opføre sig ustabilt og det ville ikke vise en af mine faner.  Jeg i sidste ende sporede det ned til faktum, at internet explorer (mindst) troede, at den <div> Tags indlejret langt, langt dybere end beregnet.Udvikler værktøj vil vise:

-<div id = "Tab1Content">
  -<div>
    -<div>
      -<div id = "Tab2Content">
        -<div>
           …………………………
                   </div>  <— Endelig viser det var lukket helt ned her!

Så, Hvis jeg gjorde en $("#Tab1Content").Skjul(), Jeg ville også skjule Fane2, og jeg kunne aldrig vise Fane2 hvis jeg ikke også vise Fane1.  Jeg har kopieret og indsat koden i visual studio og det viste alle div's foring op pænt, ligesom de skulle gøre, ser ud som dette:

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

Jeg slog mit hoved mod væggen for et stykke tid og bemærket, at i den faktiske HTML kode genererer en masse tomme <div> Tags, ligesom:

<kroppen>

  <div id = "Tab1Content">

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

  </div>

  <div id = "Tab2Content">

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

  </div>

</kroppen>

(Ovenstående er waaaaaaaaaaaay forsimplede.  Tom div tags er helt gyldigt. Nogle af mine <div> Tags var fuld af indhold, men mange flere blev ikke.  Jeg kom til erkendelsen at min <XSL:for hver> direktiverne udsender kort form div tags når xsl:for hver gjorde ikke ' finde data.  Jeg tvunget en HTML-kommentar til output, som vist:

image

 

Efter at jeg gjorde det, alle div foret pænt og min fane skifte begyndte at arbejde.

Som altid, Jeg håber dette hjælper en person i en knivspids.

</slutningen>

Abonner på min blog.

Følg mig på kvidre på http://www.twitter.com/pagalvin

Én årsag til "opretteren af fejlen ikke angav en årsag.”

Jeg har gjort en masse arbejde med SharePoint søgning det seneste og specifikt klassen KeywordQuery, egenskaber og metoder.

Hvis du vil resultatsættet til returnere resultater ud over de sædvanlige mistænkte (Se her), Du føjer det til samlingen SelectedProperties, som i:

myKeywordQuery.SelectProperties.Add("xyzzy");

Mange tak og en spids af hatten til Corey Roth og denne enormt nyttigt blog-indlæg (http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2008/02/19/how-to-use-the-moss-enterprise-search-keywordquery-class.aspx)

I mit tilfælde, "xyzzy" er ikke ligefrem en administreret egenskab.  Når jeg tilføjet det til SelectedProperties alligevel, SharePoint kastede en af mine yndlings nogensinde runtime undtagelser:

"Skaberen af fejlen angav ikke en årsag."

Jeg kan specielt godt lide kapital "R" i grunden.  Dette lyder for mig som .NET svarende til"Jeg har ingen munden, og jeg må skrige.”

</slutningen>

Abonner på min blog.

Følg mig på kvidre på http://www.twitter.com/pagalvin

Nyttigt opslagsværk: Standard resultater fra KeywordQuery søgning

Når du aktiverer Execute() metode på en KeywordQuery, Du kan oprette en ResultTable baseret på ResultType.RelevantResults.  Dette kodestykke illustrerer, hvad jeg mener:

ResultTableCollection resultsTableCollection = myKeywordQuery.Execute();

ResultTable searchResultsTable = resultsTableCollection[ResultType.RelevantResults];

Den resulterende tabel vil have følgende kolonner af oplysninger: 

Arbejds-id'et
Rang
Titel
Forfatter
Størrelse
Sti
Beskrivelse
Skrive
SiteName
CollapsingStatus
HitHighlightedSummary
HitHighlightedProperties
ContentClass
IsDocument
PictureThumbnailURL
ServerRedirectedURL

Jeg afledte denne liste fra et SharePoint 2010 miljø, Enterprise edition.  Forhåbentlig vil det være praktisk at en person i fremtiden.

</slutningen>

Abonner på min blog.

Følg mig på kvidre på http://www.twitter.com/pagalvin

Én grund til: "Mislykkedes at udpakke filen cab i løsningen”

Mens du arbejder på en visual studio webdel projekt i dag, Jeg gjorde en mindre re-org af nogle af filerne til bringes i mappen _layouts som led i implementeringsprocessen. Specifikt, Jeg omdøbt en .js fil fra "TypeAhead.js" til "TypeAhead(gamle).js"  Jeg planlægger at fjerne det så snart dens efterfølger "TypeAhead.js" godtgør korrekte.  Det lignede dette:

image

Dette umiddelbart forårsagede et problem med visual studio, da jeg prøvede at implementere projektet:

Der opstod fejl i installationen trin 'Tilføje løsning': Mislykkedes at udpakke filen cab i løsningen.

Det viser sig, at du ikke bør sætte en parentes i filnavne.  Jeg fjernet den parens og som løst problemet.

</slutningen>

Abonner på min blog.

Følg mig på kvidre på http://www.twitter.com/pagalvin