Arhive de categorii: Dezvoltarea SharePoint

HTTP 406 Eroare atunci când se utilizează unghiulară $http.get împotriva SharePoint restul sfârşitul puncte

Actualizare: Marc AD ndersson a subliniat această bucată mare de informaţii: http://blogs.Office.com/2014/08/13/JSON-Light-support-rest-SharePoint-API-released/. Care explică mult :).

Care ar putea fi mai rău titlul un blog post vreodată! Anyhoo.

De obicei face tot de meu prototipuri împotriva o instanta O365. Am meu instanţă personale, astfel încât nu trebuie să fie îngrijorat de oricine altcineva care afectează. Ca o deoparte-amintesc când am apel efectuate în jurul maşinilor virtuale pe laptop-urile noastre cu muşchi – SQL Server, IIS, se decide Hyper-V vs. VMWare? Anyhoo...

Am dezvoltat un app folosind unghiulară în acest mediu care face, Printre alte lucruri, Acest lucru:

$http.get(serverUrl)
.succesul(funcţia(date, statutul, anteturi, config) {

var getLinksResponse = datele;

getLinksResponse.value.forEach(funcţia(Rezultatul) {

// şi aşa mai departe şi astfel încât spuma

Acest lucru a fost de lucru bine în două medii diferite SharePoint online. Cu toate acestea, când colegul meu l-a portat la o instanţă de Cloudshare, El a fost obtinerea o HTTP 406 eroare (care a fost prima dată am ajuns vreodată că unul, Deci... yay, bănuiesc). Am facut un pic de cercetare şi am observat că antetul "Accepta" a fost oprit. SharePoint online a fost perfect fericit cu:

Accepta: cerere/json

Dar instanta cloudshare (care este SP prem, Găzduit într-un server virtual) vrut clasic "odata = verbose" adăugat în, precum şi:

Accepta: cerere/json;Odata = verbose

Pentru a stabili că, am adăugat antetul ca atare:

var config = {anteturi: {
"Accept": ' cerere/json;Odata = verbose'
}
};

$http.get(serverUrl,config)
.succesul(funcţia(date, statutul, anteturi, config) {

var getLinksResponse = datele;

getLinksResponse.value.forEach(funcţia(Rezultatul) {

// şi aşa mai departe şi astfel încât spuma

Că am scăpat de 406, dar, de asemenea, modificat formatul de răspuns. A fost mai mult... "vorbaret". (haha!) Mai multe modificări au fost necesare şi aici este rezultatul final:

var config = {anteturi: {
"Accept": ' cerere/json;Odata = verbose'
}
};

$http.get(serverUrl,config)
.succesul(funcţia(date, statutul, anteturi, config) {

var getLinksResponse = datele;

getLinksResponse.d.results.forEach(funcţia(Rezultatul) {

// şi aşa mai departe şi astfel încât spuma

Acest lucru doar sa transformat într-un 30 problema minut pentru noi, asa ca am avut ghinion. Sperăm că cineva aceasta constată utile.

</scop>

Creşterea gradului de conştientizare / Adoptarea unor cadre JavaScript

Colegul meu, Javed Elisaveta (http://www.bigapplesharepoint.com/team?showExpertName=Javed%20Ansari&rsource=pgblog), a scris un post de blog rezumat scurt pe cadre el îi place sau cel puţin a fost folosind cu cu SharePoint: http://www.bigapplesharepoint.com/pages/View-An-Insight.aspx?BlogID=53&rsource=PGBlog).

jQuery pare să fi fost învingător pe teren, Deci de a vorbi, pentru vîrsta acum, dar altele sunt mai noi şi liniştit un fel de lupta, ca unghiulară. (SPServices, desigur, a fost un economizor de viaţă de ani şi va continua să fie aşa cred).

Ce sunt oameni folosind? Sunt acestea concentrat mai mult pe Microsoft scule (CSOM / JSOM) sau se deplasează mai mult faţă de unghiulară, Knock-out, Ember, etc?

Am o prejudecată în creştere faţă de aceste cadre de non-Microsoft. Cred că lucrurile MSFT este mai greu şi mai greu de a lucra cu, care necesită aproape la fel de mult de curbă de învăţare ca dev de server-side stil vechi.

Postati un comentariu aici sau la peste Big Apple SharePoint Dacă doriţi pentru a discuta despre (Big Apple va avea mai mult riscul de o discuţie bună).

</scop>

Cronometrate SharePoint din configuraţia de colectare site-ul de filare

Colegul meu, Andreea Patel, a scris un post de blog descrie o arhitectura de job flexibil timer care oferă unele frumos flexibilitatea de a suporta sarcini şi/sau rapoarte de lungă durată.  În cuvintele sale:

1. Analiza verificat afară dosar şi trimiterea memento-uri pentru a persoanelor fizice, dacă numărul de zile (din moment ce fişierul a fost verificat) să depășească anumite limite de prag

2. Eliminarea link-uri la alte tipuri de conţinut, atunci când un anumit conţinut este eliminat sau arhivate la sistemul

3. Pentru a vedea toate alertele care a subscris în toate Weburile în colecția de site-ul

4. Trimiterea unui memento-uri pentru autori pentru a revizui conţinutul atunci când un timp de revizuire s-a specificat în conţinut şi că se apropie data

Bine, lista continuă...

– Vezi mai multe la: http://www.bigapplesharepoint.com/ pagini/Vezi-o-Insight.aspx?BlogID=40#sthash.7cKuiwly.dpuf

Există ori în trecutul meu când având ceva de genul asta ar fi fost foarte util.

</scop>

cum să: Configuraţi unitatea de testare şi încercare de acoperire cu QUnit.js şi Blanket.js pentru oficiu 365 SharePoint App

Intro

I-am fost explorarea unitate de testare şi test de acoperire pentru JavaScript ca am de lucru pe un nou app SharePoint pentru SharePoint online la birou 365 Suită.  Direcţii de cercetare evidente a condus-mi Qunit.js şi chiar după aceea, pentru a Blanket.js.

QUnit să-mi configura unitatea de teste şi grupaţi-le în module.  Un modul este doar un mod simplu de a organiza teste conexe. (Eu nu sunt sigur că eu sunt, folosind ca destinate, dar este de lucru pentru mine până acum cu mic set de teste am definit-o până acum).

Blanket.js se integrează cu Qunit şi mă va arăta liniile reale de JavaScript care au fost – și mai important – au fost nu fapt executate în teste.  Acest lucru este "acoperire"-linii care execută sunt acoperite de încercare, în timp ce altele nu sunt.

Între crearea bun cazuri de testare şi vizualizarea de acoperire, putem reduce riscul că codul nostru a ascuns defecte.  Vremuri bune.

Qunit

Presupunând că aveţi dumneavoastră Visual Studio proiect înfiinţat, începe prin a descărca pachetul JavaScript la http://qunitjs.com.  Adauga JavaScript şi corespondente CSS la solutia ta.  A mea arata ca acest lucru:

image

Figura 1

După cum puteţi vedea, Am fost folosind 1.13.0 în timp am scris acest blog post. Nu uitaţi să descărcaţi şi să adăugaţi fişierul CSS.

Că din modul în care, Următorul pas este de a crea un fel de test de harnaşament şi biţi Qunit de referinţă.  Eu sunt de testare o grămadă de funcţii într-un fişier script denumit "QuizUtil.js", asa ca am creat o pagina HTML numită "QuizUtil_test.html", aşa cum se Arată:

image Figura 2

Aici este codul:

<!DOCTYPE HTML>
<HTML xmlns= "http://www.w3.org/ 1999/xhtml">
<cap>
    <titlul>Test de QuizUtil cu Qunit</titlul>
    <link-ul rel= "foaia de stil" href="../CSS/qunit-1.13.0.CSS" />
    <script-ul tip= text/javascript"" src="QuizUtil.js" date-acoperi></script-ul>
    <script-ul de tip ="text/javascript" src ="qunit-1.13.0.js"></script-ul>
    <script-ul de tip ="text/javascript" src ="blanket.min.js"></script-ul>

    <script-ul>
        Modulul("getIDFromLookup");
        test("QuizUtil getIDFromLookupField", funcţia () {
            var goodValue = "1;#Paul Galvin";

            egal(getIDFromLookupField(goodValue) + 1, 2), "ID-ul de [" + goodValue + "] + 1 ar trebui să fie 2";
            egal(getIDFromLookupField(nedefinit), nedefinit, "Argumentul intrare nedefinit ar trebui să reveni nedefinit rezultatul.");
            egal(getIDFromLookupField(""), nedefinit, "Argumentul intrare gol trebuie să revină o valoare nedefinit.");
            egal(getIDFromLookupField("gobbledigood3-thq;dkvn ada;skfja sdjfbvubvqrubqer0873407t534piutheqw;vn"), nedefinit,"Ar trebui să întotdeauna întoarce o decapotabilă rezultatul la un întreg");
            egal(getIDFromLookupField("2;#unei alte persoane"), "2", "Verificarea [2;#unei alte persoane].");
            egal(getIDFromLookupField("9834524;#valoare lung"), "9834524", "Test de mare valoare.");
            notEqual(getIDFromLookupField("5;#oricine", 6), 6, "O notEqual de testare (5 nu este egal cu 6 pentru acest eşantion: [5;#oricine]");

        });

        Modulul("htmlEscape");
        test("QuizUtil htmlEscape()", funcţia () {
            egal(htmlEscape("<"), "&lt;", "Evadarea la mai puţin de operator ('<')");
            egal(htmlEscape("<clasa div =  "someclass">Un text</div>"), "&lt;clasa div =&quot;someClass&quot;&gt;Un text&lt;/div&gt;", "Şir de testare mai complexe.");
        });

        Modulul("getDateAsCaml");
        test("QuizUtil getDateAsCaml()", funcţia () {
            egal(getDateAsCaml(noi Data("12/31/2013")), "2013-12-31T:00:00:00", "Testarea greu codificate data: [12/31/2013]");
            egal(getDateAsCaml(noi Data("01/05/2014")), "2014-01-05T:00:00:00", "Testarea greu codificate data: [01/05/2014]");
            egal(getDateAsCaml(noi Data("01/31/2014")), "2014-01-31T:00:00:00", "Testarea greu codificate data: [01/31/2014]");
            egal(getTodayAsCaml(), getDateAsCaml(noi Data()), "getTodayAsCaml() ar trebui să egal getDateAsCaml(Noua dată())");
            egal(getDateAsCaml("valoare de prostii"), nedefinit, "Încercaţi să obţineţi la data de o valoare de prostii.");
            egal(getDateAsCaml(nedefinit), nedefinit, "Încercaţi să obţineţi la data de [nedefinit] data.");
        });

        Modulul("getParameterByName");
        test("QuizUtil getParameterByName (din şirul de interogare)", funcţia () {
            egal(getParameterByName(nedefinit), nedefinit, "Încercaţi să obţineţi nedefinit parametru ar trebui să reveni nedefinit.");
            egal(getParameterByName("nu există"), nedefinit, "Încercaţi să obţineţi valoarea parametrului atunci când ştim că parametrul nu exista.");

        });

        Modulul("Cookies");
        test("QuizUtil diverse funcţii de cookie-ul.", funcţia () {
            egal(setCookie("test", "1", -1), getCookieValue("test"), "Ia un cookie seta ar trebui să funcţioneze.");
            egal(setCookie("anycookie", "1", -1), adevărat, "Setarea un gătit valabil trebuie să revină"adevărat".");
            egal(setCookie(numele de "cookie" nebun" !@#$%"%\^&*(()?/><.,", "1", -1), adevărat, "Setarea un nume de rău cookie ar trebui să reveni"falsă".");
            egal(setCookie(nedefinit, "1", -1), nedefinit, "Trecerea nedefinit ca numele cookie-ul.");
            egal(getCookieValue("nu există"), "", "Cookie nu exista test.");
        });

    </script-ul>
</cap>
<corpul>
    <div ID-ul= "qunit"></div>
    <div ID-ul= "qunit de fixare"></div>

</corpul>
</HTML>

Există mai multe lucruri se întâmplă aici:

  1. Codul meu de referinţă (QuizUtil.js)
  2. Corelarea Qunity.js
  3. Definirea unor module (getIDFromLookup, Cookie-urile, şi altele)
  4. Introducerea unei <div> ale căror ID-ul este "qunit".

Apoi, I trage doar această pagină şi veţi obţine ceva de genul asta:

image

Figura 3

Dacă te uiţi în partea de sus, aveţi câteva opţiuni, dintre care două sunt interesante:

  • Ascundere a trecut testele: Destul de evident.  Poate ajuta ochi doar vedea zonele de problemă şi nu o mulţime de dezordine.
  • Modulul: (drop jos): Acest lucru va filtra testele la doar acele grupuri de teste care doriţi.

Pentru testele de sine-câteva Comentarii:

  • Se subînţelege că aveţi nevoie pentru a scrie cod, astfel încât să fie testabile în primul rând.  Utilizând instrumentul poate ajuta pună în aplicare această disciplină. De exemplu, Am avut o funcţie numită "getTodayAsCaml()”.  Acest lucru nu este foarte testabile, deoarece este nevoie de nici un argument de intrare şi să testaţi-l pentru egalitatea de şanse, noi ar trebui să în mod constant actualizare codul de test pentru a reflecta data curentă.  L-am refactored prin adăugarea un parametru de intrare de date, apoi trece la data când vreau data de astăzi în format florin.
  • Cadrul Qunit documente propriile teste şi se pare destul de robust.  Se pot face lucruri simple cum ar fi testarea pentru egalitatea de şanse şi, de asemenea, are suport pentru apeluri de stil ajax (ambele "reală" sau batjocorit folosind dumneavoastră preferat mocker).
  • Trece prin procesul, de asemenea, vă obligă să cred că, prin marginea cazuri – ce se întâmplă cu "nedefinită" sau null este trecut într-o funcţie.  Ea face mort simplu pentru a testa aceste scenarii afară.  Bun îndesat.

Acoperire cu Blanket.js

Blanket.js completează Qunit de urmărire efectiv linii de cod care executa în cursul execută testele.  Aceasta integrează dreptul în Qunit astfel încât, chiar dacă este un întreg separate app, Acesta joacă frumos – se pare chiar ca este un app fără sudură.

Acest lucru este blanket.js în acţiune:

image Figura 4

image

Figura 5

(De fapt trebuie să faceţi clic pe caseta de selectare "Enable acoperire" din partea de sus [a se vedea figura 3] pentru a permite acest lucru.)

Liniile evidențiată în figura 5 nu au fost executate de către oricare din testele mele, aşa că am nevoie pentru a concepe un test care le determina să execute dacă vreau o acoperire completă.

Ia blanket.js de lucru urmând aceşti paşi:

  1. Descarca-l de la http://blanketjs.org/.
  2. Adăugaţi-l la proiect
  3. Actualizare pagina de harnaşament dumneavoastră test (QuizUtil_test.html în cazul meu) după cum urmează:
    1. Codul de referinţă
    2. Decora vă <script-ul> referinţă de genul asta:
    <script-ul tip= text/javascript"" src="QuizUtil.js" date-acoperi></script-ul>

Blanket.js preia atributul "date-capac" şi face magie sale.  Aceasta cârlige în Qunit, actualizări UI pentru a adăuga opţiunea "Enable acoperire" şi voila!

Rezumat (TL; DR)

Utilizaţi Qunit pentru a scrie ţi cazuri de testare.

  • Descarca-l
  • Adăugaţi-l la proiect
  • Scrie o pagină de test pe ham
  • Creează testele
    • Unele dintre codul dumneavoastră să fie testabile Refactor
    • Fii creativ!  Cred că de nebun, Imposibil de scenarii şi de testare-le oricum.

Utilizaţi blanket.js pentru a asigura acoperirea

  • Asiguraţi-vă că Qunit este de lucru
  • Descarca blanket.js şi adăugaţi-l la proiect
  • Adăugaţi-l la încercare Ham pagina:
    • Adauga o trimitere la blanket.js
    • Adauga un atribut "date-acoperi" ul <script-ul> Tag-ul
  • Rulaţi testele Qunit.

Niciodată nu am făcut orice de acest lucru înainte şi a avut unele chestii rudimentare de lucru într-o mână de ore. 

Fericit de testare!

</scop>

undefinedAboneaza-te la blog-ul meu.

Urmaţi-mă pe Twitter, la http://www.twitter.com/pagalvin

Lists.asmx, GetList şi "valoare nu poate fi nul”

Am descoperit astăzi că GetList() metoda în lists.asmx serviciu Web trebuie să fie numit foarte atent sau este predispus să arunce un misterios "Valoare nu poate fi null" excepţie (şi care este presupunând că puteţi obţine trecut chiar mai rău mesajul generic de eroare, "Excepţie de tip" Microsoft.SharePoint.SoapServer.SoapServerException’ a fost aruncat.")  În mod specific, Am constatat că nu pot oferi nici un fel de prefix pe metoda GetList.  Următorul fragment jQuery ilustrează punctul:

image

Dacă faci asta, serviciul web răspunde cu "Valoare nu poate fi null" ca pe acest lautar-furnizate HTTP transcriere:

<?XML version = "1.0" codificare = "utf-8"?>
  <săpun:Plic
     xmlns:săpun ="
http://schemas.xmlsoap.org/SOAP/envelope/"    
     xmlns:XSi = "
http://www.w3.org/ 2001/XMLSchema-exemplu
     xmlns:XSD ="
http://www.w3.org/ 2001/XMLSchema">

  <săpun:Organism>
    <săpun:Vina>
      <faultCode>săpun:Server</faultCode>
      <faultString>
        Excepţie de tip "Microsoft.SharePoint.SoapServer.SoapServerException’ a fost aruncat.
      </faultString>
      <detaliu>
        <errorstring xmlns ="
http://schemas.Microsoft.com/SharePoint/SOAP/">
Valoarea nu poate fi nul.
        </errorstring>
      </detaliu>
    </săpun:Vina>
  </săpun:Organism>
</săpun:Plic>

desigur, tu, probabil, nu ar adăuga că prefixul "s0" pe cont propriu, dar unele instrumente sunt predispuse să facă acest lucru (ca Eclipse).

Acest lucru este tot mai confuz / frustrant deoarece alte metode tolera prefixe.  De exemplu, The GetListCollection metoda nu minte dacă acesta este fost prefixate, chiar şi cu prostii prefixele ca "xyzzy":

image

Aceasta "valoare nu poate fi null" pare destul de comune cu lists.asmx deci sperăm că acest lucru va ajuta pe cineva afară în viitor.

</scop>

Aboneaza-te la blog-ul meu.

Urmaţi-mă pe Twitter, la http://www.twitter.com/pagalvin

Imbricarea la nesfârşit <div> Tag-uri şi jQuery

Acest lucru pare a fi un astfel de subiect de aiurit, Nu sunt sigur că merită cu adevărat blogging-ul despre, dar că niciodată nu a oprit mine înainte, Deci, aici vom merge Zâmbet

Am de lucru un proiect în cazul în care eu sunt trăgând unele date dintr-o căutare, ambalare-l într-un mesaj XML şi apoi că XML este transformat în cele din urmă în HTML prin intermediul XSLT.  Există o mulţime de jQuery implicate, un pic de care implementeaza anumite funcţionalităţi tabbing.  Când faceţi clic pe o filă (chiar, o <div>), jQuery invocă .hide() şi .show() pe diverse divs (pagină iniţială de încărcare descărcări toate conţinut, astfel încât nu există nici o postback în acest caz).

O grămadă de ore în urmă, fila logica de comutare a început să se comporte haotic şi aceasta nu s-ar arăta unul de meu file.  Am în cele din urmă urmărite l până la faptul că internet explorer (cel puțin) crezut că <div> Tag-uri imbricate departe, mult mai profunde decât destinate.Bara de instrumente producător ar arăta:

-<div id = "Tab1Content">
  -<div>
    -<div>
      -<div id = "Tab2Content">
        -<div>
           …………………………
                   </div>  <— în cele din urmă arătând că a fost închis tot drumul în jos aici!

Deci, dacă am făcut-o $("#Tab1Content").ascunde(), Am, de asemenea, s-ar ascunde Fila2 şi ar putea arăta niciodată Fila2 dacă nu arăt, de asemenea, Fila1.  Am copiat şi inserat codul în visual studio şi ea a arătat toate div garnitură până frumos, la fel ca ei ar fi trebuit să faci, în căutarea de genul asta:

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

Am batut capul meu de perete pentru un timp şi am observat că în real HTML codul a fost generatoare de o mulţime de gol <div> Tag-uri, ca:

<corpul>

  <div id = "Tab1Content">

    <div id = "row1" />
    <div id = "rînd2" />

  </div>

  <div id = "Tab2Content">

    <div id = "row1" />
    <div id = "rînd2" />

  </div>

</corpul>

(De mai sus este waaaaaaaaaaaay simplificat.  Gol div Tag-uri sunt complet valide. Unele dintre meu <div> Tag-uri au fost plin de conţinut, dar mult mai multe nu au fost.  Am venit la realizarea că meu <XSL:pentru fiecare> Directivele au fost emit scurt-forma div Tag-uri atunci când xsl:nu pentru fiecare "găseşte orice date.  Am forţat un comentariu HTML în ieşire, ca:

image

 

După ce am făcut-o, div aliniat frumos şi fila mea de comutare a început să lucreze.

Ca întotdeauna, Sper că acest lucru ajută pe cineva într-o priză.

</scop>

Aboneaza-te la blog-ul meu.

Urmaţi-mă pe Twitter, la http://www.twitter.com/pagalvin

O cauză pentru "creatorul această anomalie a făcut nu specificaţi un motiv.”

Am făcut o mulţime de lucru cu SharePoint caută în ultima vreme şi în mod specific clasa KeywordQuery, Proprietăţi şi metode.

Dacă doriţi setul de rezultate în returna rezultate dincolo suspecţii de obicei (a se vedea aici), Adăugaţi la colecţia de SelectedProperties, ca şi în:

myKeywordQuery.SelectProperties.Add("xyzzy");

Multe mulţumiri şi un sfat de la pălărie la Corey Roth şi Acest post de blog-ul extrem de util (http://www.dotnetmafia.com/blogs/dotnettipoftheday/archive/2008/02/19/how-to-use-the-moss-enterprise-search-keywordquery-class.aspx)

În cazul meu, "xyzzy" nu este de fapt o proprietate gestionată.  Când am adăugat la SelectedProperties oricum, SharePoint au aruncat unul de meu preferat vreodată runtime excepţii:

"Creatorul de acest defect nu specifica un motiv."

Îmi place mai ales capitala "R" în motiv.  Acest lucru sună la mine ca echivalentul .NET"Nu am nici o gura, şi eu trebuie să striga.”

</scop>

Aboneaza-te la blog-ul meu.

Urmaţi-mă pe Twitter, la http://www.twitter.com/pagalvin

Referinţă la îndemână: Implicit rezultatele de căutare KeywordQuery

Când vă invoca Execute() metoda pe un KeywordQuery, Aveţi posibilitatea să creaţi un ResultTable bazat pe ResultType.RelevantResults.  Acest fragment de cod ilustrează ce vreau să spun:

ResultTableCollection resultsTableCollection = myKeywordQuery.Execute();

ResultTable searchResultsTable = resultsTableCollection[ResultType.RelevantResults];

Tabelul rezultată va avea următoarele coloane de informații: 

WorkId
Protopopiat
Titlul
Autor
Dimensiune
Calea
Descriere
Scrie
SiteName
CollapsingStatus
HitHighlightedSummary
HitHighlightedProperties
ContentClass
IsDocument
PictureThumbnailURL
ServerRedirectedURL

Am derivat această listă la o SharePoint 2010 mediu, curaj a redacta.  Sperăm că acesta va fi util pentru cineva în viitor.

</scop>

Aboneaza-te la blog-ul meu.

Urmaţi-mă pe Twitter, la http://www.twitter.com/pagalvin

Un motiv pentru: "Nu a reuşit pentru a extrage fişierul cab în soluție”

În timp ce lucrează pe o parte web visual student proiect astăzi, Am făcut o re-org minoră de unele fişiere pentru a fi puse în folderul _layouts ca parte a procesului de implementare. În mod specific, Am redenumit un fişier .js la "TypeAhead.js" la "TypeAhead(vechi).JS"  Am de gând să scoateţi-l cât mai curând succesoarea sa "TypeAhead.js" se dovedeşte corectă.  Parea ca aceasta:

image

Acest lucru imediat cauzat o problemă cu visual studio, atunci când am încercat să disloce proiectului:

Eroare în implementare pas "Adauga soluţie": Imposibil de extras cab dosar în soluție.

Se pare că ar trebui să nu puneţi o paranteză în nume de fişier.  Am scos parens şi care a rezolvat problema.

</scop>

Aboneaza-te la blog-ul meu.

Urmaţi-mă pe Twitter, la http://www.twitter.com/pagalvin