Kategori Arkiv: SharePoint utveckling

HTTP 406 Fel när du använder kantiga $http.get mot SharePoint resten slutpunkter

Uppdatering: Marc AD ndersson påpekade detta stor bit av information: http://blogs.Office.com/2014/08/13/JSON-Light-support-rest-SharePoint-API-Released/. Som förklarar en hel del :).

Det kan vara den värsta titeln på ett blogginlägg någonsin! Anyhoo.

Jag gör alla min prototyping mot en O365-instans. Jag har min personliga instans så att jag slipper vara orolig som påverkar någon annan. Som en parentes – kom ihåg när vi kallar burna runt virtuella maskiner på våra bärbara datorer med MOSS-SQL Server, IIS, beslutande Hyper-V vs. VMWare? Hur som helst...

Jag hade utvecklat en app som använder vinkelformig i denna miljö som gör, bland annat, Detta:

$http.get(serverUrl)
.framgång(funktionen(data, status, headers, config) {

var getLinksResponse = data;

getLinksResponse.value.forEach(funktionen(Resultatet) {

// och så vidare och så skum

Detta fungerade bara bra i två olika SharePoint online miljöer. Men, När min kollega portat det till en Cloudshare-instans, Han var att få en HTTP 406 fel (vilket var första gången jag någonsin fått det, så... yay, Tror jag). Vi gjorde lite forskning och märkte att "Acceptera" huvudet var off. SharePoint online var helt nöjd med:

Acceptera: Application/json

Utom den cloudshare instansen (som är SP på prem, värd i en virtual server) ville ha klassiskt "odata = verbose" tillagda i:

Acceptera: Application/json;OData = verbose

Att fixa det, Vi lade till i huvudet som sådan:

var config = {headers: {
"Acceptera": ' application/json;OData = verbose "
}
};

$http.get(serverUrl,config)
.framgång(funktionen(data, status, headers, config) {

var getLinksResponse = data;

getLinksResponse.value.forEach(funktionen(Resultatet) {

// och så vidare och så skum

Som fick bort den 406, men det ändras även formatet för svaret. Det var mer... verbose. (haha!) Fler ändringar var nödvändiga och här är slutresultatet:

var config = {headers: {
"Acceptera": ' application/json;OData = verbose "
}
};

$http.get(serverUrl,config)
.framgång(funktionen(data, status, headers, config) {

var getLinksResponse = data;

getLinksResponse.d.results.forEach(funktionen(Resultatet) {

// och så vidare och så skum

Detta bara förvandlats till en 30 minut problem för oss, så vi lucked ut. Förhoppningsvis hittar någon detta användbara.

</slutet>

Växande medvetenhet / Antagandet av JavaScript-ramverk

Min kollega, Javed Ansari (http://www.bigapplesharepoint.com/team?showExpertName=Javed%20Ansari&rsource=pgblog), skrev en kort sammanfattande blogginlägg om ramar han gillar eller åtminstone har varit med med med SharePoint: http://www.bigapplesharepoint.com/pages/View-An-Insight.aspx?BlogID=53&rsource=PGBlog).

jQuery verkar ha varit victor på fältet, så att säga, i år nu, men de andra är fler nya och stillbilder slags slåss, som vinkelformig. (SPServices, Självklart, har varit en livräddare i år och kommer att fortsätta att vara så jag tror).

Vad använder folk? De fokuserar mer på Microsofts verktyg (CSOM / JSOM) eller går mer mot vinkelformig, Knockout, Glödande kol, m.m.?

Jag har en växande slagsida mot dessa icke-Microsoft-ramar. Jag tror MSFT grejer är svårare och svårare att arbeta med, kräver nästan lika mycket av inlärningskurva som gammaldags SSI-dev.

Posta en kommentar här eller över på Big Apple SharePoint Om du vill diskutera (Big Apple kommer att ha mer sannolikheten för en bra diskussion).

</slutet>

Spinning SharePoint-tidstjänsten jobb från samling webbplatskonfiguration

Min kollega, Ashish Patel, skrev ett blogginlägg som beskriver en flexibel timer jobb arkitektur som ger viss fin flexibilitet att stödja tidskrävande uppgifter eller rapporter.  I hans ord:

1. Analysera markerat ut filer och skicka påminnelser till individerna om numrera av dagar (eftersom filen checkades ut) överskrider vissa gränsvärden

2. Att ta bort länkar från andra innehåll när en särskilt innehåll tas bort eller arkiveras från systemet

3. Användaren vill se alla aviseringar som han tecknade i alla webbplatser i webbplatssamlingen

4. Skicka en påminnelser till författarna att granska innehållet när en översyn tid angavs i innehåll och datum närmar

Brunn, listan går på...

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

Det finns tillfällen i mitt förflutna när ha något sånt här skulle ha varit mycket hjälpsam.

</slutet>

Hur: Konfigurera enhetstest och testa täckning med QUnit.js och Blanket.js för kontor 365 SharePoint App

Intro

Jag har utforskat enhetstestning och testa täckning för JavaScript som jag arbetar på en ny SharePoint-app för SharePoint online i Office 365 svit.  De uppenbara forskning vägar ledde mig till Qunit.js och direkt efter att, till Blanket.js.

QUnit Låt mig ställa in enhetstester och gruppera dem i moduler.  En modul är bara ett enkelt sätt att organisera relaterade tester. (Jag vet inte om jag använder det som avsett, men det fungerar för mig hittills med liten uppsättning tester som jag hittills har definierat).

Blanket.js integreras med Qunit och det kommer Visa mig de faktiska rader JavaScript som var – och ännu viktigare-inte faktiskt avrättades under kör testerna.  Detta är "täckning"-rader som avrättades omfattas av testet medan andra inte är.

Mellan att ställa in bra testfall och Visa täckning, Vi kan minska risken att vår kod har dolda defekter.  Goda tider.

Qunit

Förutsatt att du har din Visual Studio projektet skapa, börja med att ladda ner JavaScript paketet från http://qunitjs.com.  Lägga till JavaScript och motsvarande CSS i din lösning.  Mine ser ut såhär:

image

Figur 1

Som ni kan se, Jag var med 1.13.0 på tiden skrev jag detta blogginlägg. Glöm inte att hämta och lägga till CSS-filen.

Som ur vägen, Nästa steg är att skapa något slags test sele och referera de Qunit bitarna.  Jag testar en massa funktioner i en skriptfil som kallas "QuizUtil.js" så jag skapade en HTML-sida som kallas "QuizUtil_test.html" som visas:

image Figur 2

Här är koden:

<!DOCTYPE HTML>
<HTML xmlns= "http-://www.w3.org/ 1999/xhtml">
<huvud>
    <titel>QuizUtil test med Qunit</titel>
    <länk rel= "stylesheet" href="../CSS/qunit-1.13.0.CSS" />
    <skript typ= text/javascript"" src="QuizUtil.js" data-cover></skript>
    <script typ ="text/javascript" src ="qunit-1.13.0.js"></skript>
    <script typ ="text/javascript" src ="blanket.min.js"></skript>

    <skript>
        modul("getIDFromLookup");
        Testa("QuizUtil getIDFromLookupField", funktionen () {
            var goodValue = "1;#Paul Galvin";

            lika(getIDFromLookupField(goodValue) + 1, 2), "ID för [" + goodValue + "] + 1 bör vara 2";
            lika(getIDFromLookupField(undefined), undefined, "Odefinierad indataargumentet bör återvända odefinierat resultatet.");
            lika(getIDFromLookupField(""), undefined, "Tom indataargumentet ska returnera ett odefinierat värde.");
            lika(getIDFromLookupField("gobbledigood3-thq;dkvn ada;skfja sdjfbvubvqrubqer0873407t534piutheqw;vn"), undefined,"Ska alltid returnera ett resultat Cabriolet till ett heltal");
            lika(getIDFromLookupField("2;#någon annan person"), "2", "Kontrollera [2;#någon annan person].");
            lika(getIDFromLookupField("9834524;#lång värde"), "9834524", "Stort värde test.");
            notEqual(getIDFromLookupField("5;#någon", 6), 6, "Testa en notEqual (5 är inte lika med 6 för detta prov: [5;#någon]");

        });

        modul("htmlEscape");
        Testa("QuizUtil htmlEscape()", funktionen () {
            lika(htmlEscape("<"), "&LT;", "Fly en mindre än-operator ('<')");
            lika(htmlEscape("<div class =  "someclass">Lite text</div>"), "&LT;div class =&quot;someclass&quot;&gt;Lite text&LT;/div&gt;", "Mer komplex test sträng.");
        });

        modul("getDateAsCaml");
        Testa("QuizUtil getDateAsCaml()", funktionen () {
            lika(getDateAsCaml(nya Datum("12/31/2013")), "2013-12-31T:00:00:00", "Testa hårdkodade datum: [12/31/2013]");
            lika(getDateAsCaml(nya Datum("01/05/2014")), "2014-01-05T:00:00:00", "Testa hårdkodade datum: [01/05/2014]");
            lika(getDateAsCaml(nya Datum("01/31/2014")), "2014-01-31T:00:00:00", "Testa hårdkodade datum: [01/31/2014]");
            lika(getTodayAsCaml(), getDateAsCaml(nya Datum()), "getTodayAsCaml() ska vara lika getDateAsCaml(nytt datum())");
            lika(getDateAsCaml("nonsens värde"), undefined, "Försöka få datum för ett nonsens värde.");
            lika(getDateAsCaml(undefined), undefined, "Försöka få datum för den [undefined] datum.");
        });

        modul("getParameterByName");
        Testa("QuizUtil getParameterByName (från frågesträngen)", funktionen () {
            lika(getParameterByName(undefined), undefined, "Försöka få odefinierad parameter bör återvända odefinierat.");
            lika(getParameterByName("finns inte"), undefined, "Försöka få parametervärde när vi vet att parametern inte finns.");

        });

        modul("Cookies");
        Testa("QuizUtil olika cookie funktioner.", funktionen () {
            lika(setCookie("test", "1", -1), getCookieValue("test"), "Få en cookie som jag ska fungera.");
            lika(setCookie("anycookie", "1", -1), sant, "Ange en giltig matlagning ska returnera 'true'.");
            lika(setCookie("crazy cookie-namn !@#$%"%\^&*(()?/><.,", "1", -1), sant, "Ställa in en dålig cookie-namn ska returnera"falska".");
            lika(setCookie(undefined, "1", -1), undefined, "Passerar odefinierat som namnet på cookie.");
            lika(getCookieValue("finns inte"), "", "Cookie finns inte testet.");
        });

    </skript>
</huvud>
<organ>
    <div ID= "qunit"></div>
    <div ID= "qunit-fixtur"></div>

</organ>
</HTML>

Det finns flera saker som händer här:

  1. Referera till min kod (QuizUtil.js)
  2. Referenser Qunity.js
  3. Definiera några moduler (getIDFromLookup, Cookies, och andra)
  4. Att placera en <div> vars ID är "qunit".

Sedan, Jag dra bara upp denna sida och du får något sådant:

image

Figur 3

Om du tittar överst, har du några alternativ, varav två är intressant:

  • Dölj klarat tester: Ganska uppenbart.  Kan hjälpa ögat bara se problemområden och inte en massa skräp.
  • Modul: (släpp ner): Detta kommer att filtrera testerna till just dessa grupper av tester som du vill.

När det gäller testerna själva-några kommentarer:

  • Det säger sig självt att du måste skriva din kod så att det är testbara i första hand.  Med hjälp av verktyget kan hjälpa till att upprätthålla den disciplinen. Till exempel, Jag hade en funktion som kallas "getTodayAsCaml()”.  Detta är inte mycket testbara eftersom det tar ingen indataargumentet och testa det för jämställdhet, Vi skulle behöva ständigt uppdatera Provningsmetod för att återspegla det aktuella datumet.  Jag refactored det genom att lägga till en indataparameter för data sedan passerar det aktuella datumet när jag vill ha dagens datum i CAML-format.
  • Ramen Qunit dokumenterar sina egna tester och det verkar ganska robust.  Det kan göra enkla saker som att testa för jämställdhet och har även stöd för ajax stil samtal (både "riktiga" eller hånade med din favorit knäcka).
  • Gå igenom processen också tvingar dig att tänka igenom kant fall – vad händer med "odefinierade" eller null överförs till en funktion.  Det gör att det är död enkel att testa dessa scenarier ut.  Bra grejer.

Täckning med Blanket.js

Blanket.js kompletterar Qunit genom att spåra de faktiska kodrader som kör under köra dina tester.  Det integrerar rätt in i Qunit så även om det är en helt separat app, Det leker fint-det ser verkligen ut som det är en smidig app.

Detta är blanket.js i aktion:

image Figur 4

image

Figur 5

(Du måste faktiskt Klicka på kryssrutan "Aktivera täckning" överst [se figur 3] att möjliggöra detta.)

Markerade rader i figur 5 har inte utförts av någon av mina tester, så jag behöver att utforma ett test som orsakar dem att köra om jag vill ha full täckning.

Få blanket.js fungerar på följande sätt:

  1. Ladda ner från http://blanketjs.org/.
  2. Lägg till det i projektet
  3. Uppdatera din sele testsida (QuizUtil_test.html i mitt fall) enligt följande:
    1. Referens koden
    2. Dekorera din <skript> referens gillar detta:
    <skript typ= text/javascript"" src="QuizUtil.js" data-cover></skript>

Blanket.js plockar upp attributet "data-cover" och gör sin magi.  Det krokar i Qunit, uppdateringar av UI för att lägga till alternativet "Aktivera täckning" och voila!

Sammanfattning (TL; DR)

Använda Qunit för att skriva din testfall.

  • Ladda ner den
  • Lägg till det i projektet
  • Skriva en testsida sele
  • Skapa dina tester
    • Refactor några av din kod vara testbara
    • Vara kreativ!  Tror galen, omöjligt scenarier och testa dem ändå.

Använd blanket.js för att säkerställa täckning

  • Kontrollera att Qunit fungerar
  • Hämta blanket.js och lägga till ditt projekt
  • Lägga till din sele testsida:
    • Lägg till en hänvisning till blanket.js
    • Lägga till en "data-cover" attribut till din <skript> tag
  • Köra din Qunit tester.

Jag aldrig gjorde något av detta innan och hade några elementära saker som arbetar i en handfull timmar. 

Glad testning!

</slutet>

undefinedPrenumerera på min blogg.

Följ mig på Twitter vid http://www.twitter.com/pagalvin

Lists.asmx, GetList och "värde kan inte vara null”

Jag upptäckte idag att GetList() metod i lists.asmx webbtjänsten har att kallas mycket noggrant eller den är benägna att kasta en mystisk "Värdet får inte vara null" undantag (och som förutsatt att du kan komma förbi ännu värre allmänna felmeddelande, "-Undantag av typ" Microsoft.SharePoint.SoapServer.SoapServerException’ kastades.")  Särskilt, Jag tyckte att du inte kan tillhandahålla någon form av prefixet på metoden GetList.  Följande jQuery utdrag illustrerar punkten:

image

Om du gör det, webbtjänsten svarar med "Värdet får inte vara null" visas enligt detta Spelman-enligt HTTP avskrift:

<?XML-version = "1.0" Encoding = "utf-8"?>
  <tvål:Kuvert
     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">

  <tvål:Organ>
    <tvål:Fel>
      <faultcode>tvål:Servern</faultcode>
      <faultstring>
        -Undantag av typ "Microsoft.SharePoint.SoapServer.SoapServerException’ kastades.
      </faultstring>
      <detalj>
        <ErrorString xmlns ="
http://schemas.microsoft.com/SharePoint/SOAP/">
Värdet får inte vara null.
        </ErrorString>
      </detalj>
    </tvål:Fel>
  </tvål:Organ>
</tvål:Kuvert>

Självklart, du skulle inte förmodligen till att "s0" prefix på egen, men vissa verktyg är benägna att göra det. (som Eclipse).

Detta är desto mer förvirrande / frustrerande eftersom andra metoder tolerera prefix.  Till exempel, den GetListCollection metoden hänsyn inte till om det är förutfastställt, även med nonsens prefix som "xyzzy":

image

Detta "värdet inte får vara null" verkar ganska vanligt med lists.asmx så förhoppningsvis detta kommer att hjälpa någon i framtiden.

</slutet>

Prenumerera på min blogg.

Följ mig på Twitter vid http://www.twitter.com/pagalvin

Oändligt kapsla <div> Märken och jQuery

Detta verkar vara sådan en oddball-avsnittet, Jag är inte säker på att det verkligen är värt att blogga om, men det har aldrig hindrat mig innan, Så här går vi Leende

Jag arbetar med ett projekt där jag dra vissa data från en sökning, förpackning till ett XML-meddelande och sedan att XML till slut förvandlas till HTML via XSLT.  Det finns mycket av jQuery, en bit som implementerar tabbing funktionalitet.  När du klickar på en flik (Verkligen, en <div>), jQuery anropar .hide() och .show() på olika Divar (första sidan laddar hämtningar allt innehåll så det finns ingen postbacks i detta fall).

Ett gäng timmar sedan, fliken växling logik började bete sig underligt och det skulle inte visar en av Mina flikar.  Jag slutligen spårade det till faktum att internet explorer (minst) trodde att det <div> Märken som kapslade långt, mycket djupare än avsett.Verktygsfältet utvecklare skulle visa:

-<div id = "Tab1Content">
  -<div>
    -<div>
      -<div id = "Tab2Content">
        -<div>
           …………………………
                   </div>  <— Slutligen visar det lades hela vägen ner här!

Så, om jag gjorde en $("# Tab1Content").Dölj(), Jag döljer också Tab2 och jag kunde aldrig visa Tab2 om jag inte visar också på Tab1.  Jag kopierade och klistrade in koden till visual studio och det visade alla den div beklädnad upp snyggt, precis som de ska göra, Titta här:

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

Jag slog mitt huvud mot väggen ett tag och märkte att koden i den faktiska HTML genererar mycket tom <div> Märken, liksom:

<organ>

  <div id = "Tab1Content">

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

  </div>

  <div id = "Tab2Content">

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

  </div>

</organ>

(Ovanstående är waaaaaaaaaaaay banaliseras.  Tom div-taggarna är helt giltiga. Några av mina <div> Märken var fulla av innehåll, men många fler var inte.  Jag kom till insikten att min <XSL:för varje> direktiven avger i kortform div-taggar när xsl:för varje inte "hitta några data.  Jag tvingas en HTML-kommentar till utdata, som visas:

image

 

När jag gjorde det, alla div uppradade snyggt och min fliken växling började arbeta.

Som alltid, Jag hoppas att detta hjälper någon i en nypa.

</slutet>

Prenumerera på min blogg.

Följ mig på Twitter vid http://www.twitter.com/pagalvin

En orsak för "skaparen av det här felet inte angav en anledning.”

Jag har gjort en hel del arbete med SharePoint search-på sistone och särskilt klassen KeywordQuery, egenskaper och metoder.

Om du vill att resultatuppsättningen till resultat utöver de vanliga misstänkta (se här), du lägger till det i SelectedProperties samling, som i:

myKeywordQuery.SelectProperties.Add("xyzzy");

Stort tack och ett tips av en keps till Corey Roth och denna oerhört hjälpsamma blogginlägg (http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2008/02/19/how-to-use-the-moss-enterprise-search-keywordquery-class.aspx)

I mitt fall, "xyzzy" inte är faktiskt en hanterad egenskap.  När jag har lagt till det SelectedProperties ändå, SharePoint kastade en av min favorit någonsin runtime undantag:

"Skaparen av det här felet angav inte ett skäl."

Jag gillar särskilt kapital "R" i skäl.  Detta låter för mig som .net motsvarande"Jag har ingen mun, och jag måste skrika.”

</slutet>

Prenumerera på min blogg.

Följ mig på Twitter vid http://www.twitter.com/pagalvin

Praktisk: Standard resultatet från KeywordQuery sökning

När du anropar Execute() metoden på en KeywordQuery, Du kan skapa en ResultTable som bygger på ResultType.RelevantResults.  Denna kodavsnitt illustrerar vad jag menar:

ResultTableCollection resultsTableCollection = myKeywordQuery.Execute();

ResultTable searchResultsTable = resultsTableCollection[ResultType.RelevantResults];

Den resulterande tabellen kommer att ha följande kolumner av information: 

Arbets-ID
Rang
Avdelning
Författare
Storlek
Sökväg
Beskrivning
Skriva
Platsnamn
CollapsingStatus
HitHighlightedSummary
HitHighlightedProperties
ContentClass
IsDocument
PictureThumbnailURL
ServerRedirectedURL

Jag kommer denna lista från en SharePoint 2010 miljö, Enterprise edition.  Förhoppningsvis blir det praktiskt till någon i framtiden.

</slutet>

Prenumerera på min blogg.

Följ mig på Twitter vid http://www.twitter.com/pagalvin

En anledning till: "Det gick inte att extrahera cab-filen i lösningen”

När du arbetar med en webbdel för visual studio-projektet idag, Jag gjorde en mindre re-org vissa filer sättas i mappen _layouts som en del av driftsättningsprocessen. Särskilt, Jag har bytt namn en JS-fil från "TypeAhead.js" till "TypeAhead(gamla).JS"  Jag planerar att ta bort det så snart som dess efterföljare "TypeAhead.js" visar sig rätt.  Det såg ut såhär:

image

Detta orsakat omedelbart problem med visual studio när jag försökte distribuera projektet:

Fel uppstod i distributionen steg "Lägga till lösning": Det gick inte att extrahera cab-filen i lösningen.

Det visar sig att du inte bör lägga en parentes i filnamn.  Jag tagit bort den parens och som löst problemet.

</slutet>

Prenumerera på min blogg.

Följ mig på Twitter vid http://www.twitter.com/pagalvin