Sharepoint Sitedefinitions pt. 2 (List Views)

by Jess Lassen 8. January 2010 08:56

I et tidligere indlæg omkring Sitedefinitions kiggede vi på opbygningen af webtemp.xml og onet.xml filerne, der danner grundlag for de nye custom sitedefinitions.
I dette indlæg kigger jeg mere på <modules> elementet i onet.xml filer og helt konkret på hvordan man customizerer list views.

Et eksempel på et list view i en standard Sharepoint sitedefinition ses på ”Document Workspace” skabelonen.

Selvom det ser ud som en webpart, er det faktisk ikke indsat som webparts i skabelonen, men som et view element, der bliver renderet i en ListViewWebpart.

Kigger man i onet.xml filen i modules elementet ser man følgende:


<View List="$Resources:core,shareddocuments_Folder;" BaseViewID="6" WebPartZoneID="Left" />
<View List="$Resources:core,lists_Folder;/$Resources:core,tasks_Folder;" BaseViewID="7" WebPartZoneID="Left" WebPartOrder="2" />

Attributen “BaseViewID” er den der definerer renderingen af view’et (kolonner, sortering osv.). ID’et er en henvisninger til et View der ligger i liste definitionen (schema.xml).


<View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,All_Documents;" DefaultView="TRUE" MobileView="True" MobileDefaultView="True" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/dlicon.png" Url="Forms/AllItems.aspx"><!-- _locID@DisplayName="camlidDc1" _locComment=" " -->
 <GroupByHeader><HTML><![CDATA[<TBODY id="titl]]></HTML>
   <GetVar Name="GroupByLevelString" /><HTML><![CDATA[" groupString="]]></HTML>
    ...

Hvis man åbner schema.xml filen op til Dokumentbiblioteket, finder man hurtig ud af at ikke gidder at sidder og rode med views i notepad særligt længe. Der findes værktøjer til at gøre dette meget nemmere, f.eks Sharepoint Manager, men dette hjælper ikke på problemet, at views ligger i schema.xml filen og denne må ikke ændres, da den kan blive overskrevet ved opdateringer osv.

Så hvad gør man hvis man gerne vil have en ekstra kolonne, sorteret på en anden måde eller sætte en item limit på viewet? Der er 2 svar på dette spørgsmål. Enten laver du en helt ny listedefintion og laver dine egne views som du kan henvise til i sitedefinitionen eller også efterprocesserer man en standard listedefinition.

Webparten (views renderes som ListViewWebparts) hentes ud og efterprocesseres:


using (SPLimitedWebPartManager manager = web.GetLimitedWebPartManager("Sider/default.aspx", PersonalizationScope.Shared))
{
 foreach (System.Web.UI.WebControls.WebParts.WebPart wp in manager.WebParts)
 {
  if (wp.Title == "Dokumenter" && wp is ListViewWebPart)
  {
   ViewReflector vr = new ViewReflector(wp);
   vr.AddViewFields(new string[] { "DocIcon", "LinkFilenameNoMenu", "Editor", "Modified" });
   vr.AddQuery("<OrderBy><FieldRef Name='Modified' Ascending='FALSE' /></OrderBy>");
   vr.AddRowLimit("10", false);
   vr.Update();
   wp.Title = "Seneste dokumenter";
   manager.SaveChanges(wp);
  }
 }
}

Hvor ViewReflector er følgende klasse (udsnit):


class ViewReflector
{
 private System.Web.UI.WebControls.WebParts.WebPart wp;
 private XmlNode node;
 private SPView spView;

 public ViewReflector(System.Web.UI.WebControls.WebParts.WebPart Webpart)
 {
  wp = Webpart;
  Init();
 }
 
 private void Init()
 {
  System.Reflection.PropertyInfo ViewProp = wp.GetType().GetProperty("View",
  System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

  spView = ViewProp.GetValue(wp, null) as SPView;

  spView.GetType().InvokeMember("EnsureFullBlownXmlDocument",
  System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod,
  null, spView, null, System.Globalization.CultureInfo.CurrentCulture);

  System.Reflection.PropertyInfo NodeProp = spView.GetType().GetProperty("Node",
  System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

  node = NodeProp.GetValue(spView, null) as XmlNode;
 }

 public void AddViewFields(string[] viewFields)
 {
  XmlNode viewNode = node.SelectSingleNode("ViewFields");

  if (viewNode != null)
  {
   viewNode.RemoveAll();
   foreach(string s in viewFields)
   {
    viewNode.AppendChild(GetViewField(viewNode.OwnerDocument, s));
   }
  }
 }
 
 ... (flere metoder)

 public void Update()
 {
  spView.Update();
 }
}

Som man kan se har Microsoft har ikke gjort det nemt for os at customizere views, hvis det ikke gøres gennem GUI eller schema.xml. Men hvor der er vilje, er der vej, - om det så må være den snørklede vej gennem reflection.

ViewReflector.cs (3,12 kb)

Tags: , , ,

Sharepoint Sitedefinitions

by Jess Lassen 9. October 2009 08:02

Sitedefinitions i Sharepoint er, ganske som ordet lyder, en definition af en type site i Sharepoint. Standard site typer i Sharepoint er: Team Site, Document Center, Publishing Site mv. Når man starter nye projekter, kan det ofte være en god ide at udvikle sine egne sitedefinitions som en del af projektet. Det meste af ens funktionalitet ligger alligevel i diverse features og en sitedefinition giver bla. mulighed for at aktiverer disse i forbindelse med oprettelse af sites baseret på sitedefinitionen.

En sitedefinition består af følgende:

Webtemp.xml
Findes i TEMPLATE\LCID\XML. Det er her sharepoint kigger efter hvilket templates der findes. Her findes alle standard templates (teamsite, publishing osv) og det er her at nye templates placeres. Kravet for at sharepoint finder de nye templates er at filen starter med webtemp (f.eks webtempMinTemplate.xml).
Her er et udsnit af en publishing template:


<Template Name="BLANKINTERNET" ID="53">
    <Configuration ID="0" Title="Publishing Site" Hidden="TRUE" ImageUrl="/_layouts/1033/images/IPPT.gif" Description="..." SubWebOnly="TRUE" DisplayCategory="Publishing">
    </Configuration>
    <Configuration ID="1" Title="Press Releases Site" Hidden="TRUE" ImageUrl="/_layouts/1033/images/IPPT.gif" Description="..." SubWebOnly="TRUE" DisplayCategory="Publishing" VisibilityFeatureDependency="F6924D36-2FA8-4f0b-B16D-06B7250180FA">
    </Configuration>
</Template>

Name attribute skal være med store bogstaver og svarer til mappenavnet i TEMPLATE\SiteTemplates folderen. ID attributen på nye templates skal være over 10000.
Læs mere omkring webtemp.xml på http://msdn.microsoft.com/en-us/library/ms447717.aspx

Onet.xml
Der er i denne fil det hårde arbejde sker. Her defineres bla. de konfigurationer som webtemp filen peger på. Det er anbefalet at holde denne fil så simpel som muligt og placere det meste funktionalitet i features. I denne fil kan bla. navigation, list templates, dokument templates og features defineres. De meste funktionalitet i templaten vil ligge i sitefeatures/webfeatures.
Bemærk at udover at definere features i onet.xml kan man oprettet features som aktiveres på baggrund af templates. Dette kaldes feature stapling (hæftning) i Sharepoint.
Læs mere omkring feature stapling på: http://msdn.microsoft.com/en-us/library/bb861862.aspx

Her er et udsnit af en onet.xml fil:


<Configurations>
  ...
  <Configuration ID="0" Name="Default">
    <Lists></Lists>
    <Modules>
      <Module Name="Default" />
    </Modules>
    <SiteFeatures>
      <Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />
      <Feature ID="FDE5D850-671E-4143-950A-87B473922DC7" />
    </SiteFeatures>
    <WebFeatures>
      <Feature ID="00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5" />
      <Feature ID="F41CC668-37E5-4743-B4A8-74D1DB3FD8A4" />
    </WebFeatures>
  </Configuration>

Configuration ID, er det nummer som webtemp filen referrere til. I Site/Web-features defineres de features som ønskes aktiveret og i modules elementet defineres filer der skal provisioneres, når der oprettes nye instanser af templaten.
Læs mere omkring onet.xml på: http://msdn.microsoft.com/en-us/library/ms474369.aspx

Med dette på plads er sitedefinitionen klar og der kan nu oprettes nye sites baseret på den nye template.
Det er ofte nemmest at basere sine sitedefinitions på andre sitedefinitions og tilrette disse efter behov. De indbyggede i sitedefintions i Sharepoint er ikke længere væk end 12 Hive og disse er god reference, når man kaster sig ud i at lave sine egne sitedefinitions.

Tags: ,

Skift ikoner i søgeresultatet

by Jess Lassen 21. July 2009 05:42

Pift dine Sharepoint søgeresultater lidt op med ikoner der passer til indholdstypen.

Sådan gør du:

Opret den metadata du vil teste på i xslt’en i Shared Service Provideren.
Husk at lave en ny crawl efter du har oprettet ny managed property.

Tilret kerneresultat webdelen til at vise ikoner på baggrund af indholdstype.
Tilføj den oprettede Managed Property i Valgte kolonner:

Lav en xslt template der skifter ikon på baggrund af indholdstypen.


<xsl:template name="GetContentType">
 <xsl:param name="ContentType"></xsl:param>
 <xsl:param name="OriginalImageUrl"></xsl:param>
    <xsl:choose>
        <xsl:when test="contains($ContentType,'Medarbejder')"><img align='absmiddle' border='0' src='/_layouts/images/user.png' /></xsl:when>
        <xsl:when test="contains($ContentType,'Nyhed')"><img align='absmiddle' border='0' src='/_layouts/images/newspaper.png' /></xsl:when>
        <xsl:otherwise>
            <img align='absmiddle' border='0' src='{$OriginalImageUrl}' />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Ret i resultat-templaten så den bruger den nyoprettede template.


<!-- This template is called for each result -->
<xsl:template match="Result">

Udskift det gamle billede-tag med et kald til den nyoprettede template (GetContentType):
<img align="absmiddle" src="{imageurl}" border="0" alt="{imageurl/@imageurldescription}" />


<xsl:call-template name="GetContentType">
 <xsl:with-param name="ContentType" select="mycontenttype"/>
 <xsl:with-param name="OriginalImageUrl" select="imageurl"/>
</xsl:call-template>

Resultatet bliver et overskueligt og lækkert søgeresultat.

Tags: , ,

Sharepoint Webservices

by Jess Lassen 17. July 2009 11:17

Engang imellem opstår behovet for at kommunikere med Sharepoint fra en klient applikation eller en anden webapplikation. Hvordan finder man så lige det dokument, den rettighed eller foretager den søgning man har brug for? Sharepoint gemmer indholdet i en database, så en løsning kunne være at tilgå denne direkte og trække data ud heraf. Dette er dog ikke den anbefalede måde at gøre det på, i stedet skal vi kigge på Sharepoint webservices.

En standard Sharepoint installation inkluderer følgende webservices som kan tilgås via http://<site>/_vti_bin/<webservicenavn>

Man må dog engang imellem erkende at de indbyggede webservices ikke altid opfylder ens behov, og så må man lave sin egen Sharepoint webservice. Det fede ved at lave sin egen Sharepoint webservice er at du har adgang til Sharepoints API - så det er ikke meget anderledes end normalt Sharepoint udvikling.

Der er dog følgende forskelle fra almindelige .NET webservices:

Codebehind koden til .asmx filen skal kompileres separat og placeres i GAC’en og .asmx filen skal henvise til denne.

.disco og .wsdl filer skal genereres manuelt med Service Discovery tool (Disco.exe). Derefter skal de omskrives til .aspx filer, så deres indhold kan genereres runtime. Wsdl filen skal endvidere regenereres hver gang du tilføjer nye webmethods i din service, hvilket kan være lidt irriterende.

Sådan laver du din sharepoint webservice:

Opret asmx filen og kompilér asmx code-behind filen.
Referér asmx filen til code-behind filen:

<%@ WebService Language="C#" Class="Service, MyServiceAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8f2dca3c0f2d0131" %>

Opret de statiske .disco og .wsdl filer med Service Discovery tool.
Opret .aspx versioner af .disco og .wsdl filer og kopier indholdet ind i nyoprettede filer. ([service]disco.aspx og [service]wsdl.aspx)

Indsæt følgende i toppen af .aspx siderne:

<%@ Page Language="C#" Inherits="System.Web.UI.Page" %>
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Import Namespace="Microsoft.SharePoint.Utilities" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<% Response.ContentType = "text/xml"; %>

Tilret url'erne i disco.aspx og wsdl.aspx filerne så de understøtter sharepoints virtual path provider.
disco.aspx:

<contractRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request) + "?wsdl"),Response.Output); %>
docRef=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
xmlns="http://schemas.xmlsoap.org/disco/scl/" />
<soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
xmlns:q1="http://tempuri.org/" binding="q1:HelloWorld" xmlns="http://schemas.xmlsoap.org/disco/soap/" />
<soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>
xmlns:q2="http://tempuri.org/" binding="q2:ServiceSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />

wsdl.aspx:

<soap:address location=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> />

Deploy de 3 filer til \Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI

Microsoft har skrevet en udmærket Walkthrough Guide til at lave sin egen Sharepoint webservice. Så hvis man har brug for at udvikle sin egen Sharepoint webservice er denne guide et godt startpunkt. http://msdn.microsoft.com/en-us/library/ms464040.aspx

Tags: ,

Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen

RecentPosts