Showing posts with label SharePoint Branding. Show all posts
Showing posts with label SharePoint Branding. Show all posts

Tuesday, January 31, 2012

Presence with Branded Master Pages

I have heavily used the starter branding master pages (http://startermasterpages.codeplex.com/) for some projects I have done. It was brought to my attention that the Lync presence was not coming through.
After some research I found that if I replaced this:
<script type="text/javascript">
function ProcessImn(){}
function ProcessImnMarkers(){}        
</script>

With this:
<SharePoint:ScriptLink language="javascript" name="init.js" OnDemand="true" runat="server"/>

The presence indicators came back.

Wednesday, January 18, 2012

Custom Web Templates and Activating Features

Introduction
Lately I was messing around with Custom Site and Web Templates with Office 365 and made a few discoveries that I figure I share. Some of it is old, some of it I had to piece together.

Background
I am building a solution in Office 365 using SharePoint Online. I have a site collection with publishing turned on. I created a custom site template and I need to make sure that site (web level) publishing feature is turned on.

Publishing Feature Disables Creating Site Templates
For some reason, when you turn on the publishing feature on a site, the “Save site as a template” is removed from Site Settings. Now I have found some blog posting where people go down into the SharePoint install files and make some changes to fix that. First, probably not the best course of action if you want to make sure you have supportable upgrades (and someone actually documents the change <g>). Second, since I am working with Office 365 that is not even an option, so I need to find a solution that does it the right way.

Another thing I saw people suggest is go to the Save as Template page by typing in “_layouts/savetmpl.aspx”. Do not waste your time with that approach either, it will not work correctly.

My only option is to create my custom site initially without the publishing feature turned on. Then build some solutions to turn on publishing for the site automatically and ensure that the masterpages are set appropriately. The solutions I looked into are:

1. Feature Stapling
2. Modifying the Web Template
3. WebProvisioned Event Handler

Custom Web Template Feature Stapling
The first solution that I investigated was the most obvious; create a Feature Stapler that would activate the site publishing feature.

The first thing I ran into was finding the actual name of the template. Traditionally the name of the site template is usually something like STS#0. However since this is a custom site template where would I get the site template name from? I found some scripts that would help me get the template name. Since I was doing the development on my local machine it was easy for me to run some PowerShell on my development box to test this all out (I did find similar code to run API code against Office 365).

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <FeatureSiteTemplateAssociation Id="94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb" TemplateName="{04FB0801-1DFA-41ED-9B87-06D0FF088F01}#MyCommunityTemplate" />
</Elements>

I create a Feature Stapling feature that looked like this. As you can see there is a GUID#template name format.

Let me save you some though – this is not supported and did not work. Feature Stapling can only be used against the site templates that are OOB the box or deployed down into the hive. You cannot apply do Feature Stapling to a site template created off SharePoint web site.
Modifying the Web Template

The next thing I tried, which is a recommended approach, is to modify the web template. This is a really easy thing to do now with Visual Studio 2010.
In Office 365 I created a web template the way I needed but without publishing turned on. I then went into site settings and created web template like usual. I then went to the Site Collection Solution Gallery, downloaded the WSP, and opened it in Visual Studio 2010 (using an Import SharePoint Solution Package project).
In the project, there will be a module called “Web templates” and you will find a file called “ONet.xml”. Open this file and you will see <SiteFeatures> and <WebFeatures>.
<SiteFeatures> correspond to the site collection and the following features should already be in the web template because you will have publishing turned on at the site collection level.

<!--PublishingPrerequisites Feature-->
<Feature ID="{a392da98-270b-4e85-9769-04c0fde267aa}" Name="FeatureDefinition/a392da98-270b-4e85-9769-04c0fde267aa" />
<!--PublishingResources Feature-->
<Feature ID="{aebc918d-b20f-4a11-a1db-9ed84d79c87e}" Name="FeatureDefinition/aebc918d-b20f-4a11-a1db-9ed84d79c87e" />
<!--PublishingLayouts Feature-->
<Feature ID="{d3f51be2-38a8-4e44-ba84-940d35be1566}" Name="FeatureDefinition/d3f51be2-38a8-4e44-ba84-940d35be1566" />
<!--PublishingSite Feature-->
<Feature ID="{f6924d36-2fa8-4f0b-b16d-06b7250180fa}" Name="FeatureDefinition/f6924d36-2fa8-4f0b-b16d-06b7250180fa" />

Why are there four when you only turn on one publishing feature for the site collection through the SharePoint UI? The one with f6924d36-2fa8-4f0b-b16d-06b7250180fa is actually the main one, but the other three are supporting, hidden ones. There is not action for you, just brought this up because I thought is it interesting.

Now this is what you do need to do. Go to the <WebFeatures> and add the following two features.

Add the Publishing Web after the MetaDataNav:
<!--MetaDataNav Feature-->
<Feature ID="{7201d6a4-a5d3-49a1-8c19-19c4bac6e668}" Name="FeatureDefinition/7201d6a4-a5d3-49a1-8c19-19c4bac6e668" SourceVersion="14.0.0.0" />
<!--PublishingWeb Feature-->
<Feature ID="{94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb}" Name="FeatureDefinition/94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb" SourceVersion="14.0.0.0" />

Add the Publishing Feature after the GridList:
<!--GridList Feature-->
<Feature ID="{00bfea71-3a1d-41d3-a0ee-651d11570120}" Name="FeatureDefinition/00bfea71-3a1d-41d3-a0ee-651d11570120" SourceVersion="1.0.0.0" />
<!--Publishing Feature-->
<Feature ID="{22a9ef51-737b-4ff2-9346-694633fe4416}" Name="FeatureDefinition/22a9ef51-737b-4ff2-9346-694633fe4416" SourceVersion="14.0.0.0" />

This worked great and was really clean.

The next thing I needed do was make sure the master pages are set appropriately. Even though I turned on publishing, it does not mean that the mast pages will be set correctly. The solution is again very simple.

I created a new Feature in Visual Studio 2010 to the web template solution I already had open and set the scope for Web. I then added an event handler to the new Feature. Then in the FeatureActivated event handler I added the following code:
using (SPWeb web = (SPWeb)properties.Feature.Parent)
{              
    web.MasterUrl = web.ParentWeb.MasterUrl;
    web.AllProperties["__InheritsMasterUrl"] = "True";
    web.CustomMasterUrl = web.ParentWeb.CustomMasterUrl;
    web.AllProperties["__InheritsCustomMasterUrl"] = "True";
               
    web.Update();
}

Then I selected the new Feature, clicked on the manifest and copied the GUID for the Feature ID. I then subsequently added that Feature ID into the bottom of the <WebFeatures> section in the ONet.xml file.
Now when this custom web template is provisioned, this code will be executed to set the master page appropriately.
Web Provisioned Event
Another totally different option to consider is use the new SharePoint 2010 WebProvisioned Event Handler. This event handler is available in the SharePoint Sandbox and can run in Office 365. This solution is very simple:
  • Create a new SharePoint 2010 solution in Visual Studio.  
  • Add an Event Handler. 
  • Then add the following code.
public override void WebProvisioned(SPWebEventProperties properties)
{
    base.WebProvisioned(properties);

    using (SPWeb web = (SPWeb)properties.Web)
    {
        Guid sitePublishing = new Guid("94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb");

        web.AllowUnsafeUpdates = true;

        web.Features.Add(sitePublishing, true);
               
        web.MasterUrl = web.ParentWeb.MasterUrl;
        web.AllProperties["__InheritsMasterUrl"] = "True";
        web.CustomMasterUrl = web.ParentWeb.CustomMasterUrl;
        web.AllProperties["__InheritsCustomMasterUrl"] = "True";
               
        web.Update();
    }

}

There are some advantages to this solution. First it is really simple. Second this code will be executed for ANY site that is provisioned. So if you need to always make sure that publishing is turned on for any site that is provisioned and that the master pages are always the same, this may actually be a better solution. Otherwise you will have to do what I previously described for every web template.

Conclusions

This was a really interesting little exercise that I went through and though it would be interesting to share. Hopefully you will see that there are options based on the business requirements you want to support. This is by no means the only options you have available either.

References

Things that I found along the way:

Saturday, May 21, 2011

Customizing Content Query Web Parts

Content Query Web Parts

I have to say the game has changed with content query web parts. When trying to work with them in SharePoint 2007 you ended up having to do a ton of work just so a custom field from a content type. Now it really very simple to go in and start working with content query web parts all inside of SharePoint Designer. In this example I am going to:

  • Create a content query web part that is going to show me the most popular articles that are related to an article that I created.
  • I will do some “conditional formatting” to display a confidentiality warning to the user based on the metadata associated to the article.

Approach

As I alluded creating your own xsl for content query web parts is much easier with SharePoint Designer 2010. To access and modify the style sheets select All Files in the Navigation. Then drill down to Style Library >> XSL Style Sheets. There are three style sheets that come out of the box ContentQuery.xsl, Header.xsl and ItemStyle.xsl. The one you will need to work with the most of the time is ItemStyle.xsl.

clip_image002

Next question you may have is how to create new xsl entries for the content query web part? Well I have found the simplest approach is pretty simple.

  • I open up ItemStyle.xsl.
  • I copy ones of the existing xsl templates. Specifically, I copy a full <xsl:template> and add it to the very bottom.
  • Then you need to modify the template tag and replace XXX values <xsl:template name="XXX" match="Row[@Style='XXX']" mode="itemstyle">. It is important that both values are identical. As well, they need to be unique to the xsl file.

That’s it. I am not going to give a full lesson here on all the cool things you can do once you are in there. I leave that up to you as a creative solution developer.

When doing this write up I refined my thoughts a little bit on how to do content query web parts. Specifically I think it is not best to the ItemStyle.xsl directly. Why? Well when you make a change to the ItemStyle.xsl (as I outlined above) you will get a warning saying “Saving your changes will customize this page so that is no longer based on the site definition. Do you want to continue?”

clip_image003

So you make this change you are customizing (unghosting) the ItemStyle.xsl which may not always be the best thing if you are planning for an Upgrade. YES YOU SHOULD BE THINKING ABOUT THE NEXT VERSION OF SHAREPOINT! Look at the forest; not the tree in front of you. Customized pages had to be dealt with when upgrading from SharePoint 2003 to 2007 as well as SharePoint 2007 to 2010. My response officially is it always “depends” but I try to avoid customizing (unghosting) as much as I can.

Knowing this I believe a best practice will be to create your own content query web parts that point to a custom ItemStyle.xsl file. Then your customizations will be managed separately and will not interfere with upgrades to OOB features. The solution is so easy as well; it is a no brainer. Let me walk through it.

  • First I took the existing ItemStyle.xsl in SharePoint Designer and copy pasted it within the same directory. I named it ItemStyle_BrandingBlog.xsl.
  • Next I went into it and stripped out all of the existing <xsl:template> tags and all the content within them. If those need to be used, I will use the OOB content query web part. Then saved it.
  • Next I just added an out of the box content query web part onto a web part page.
  • I made zero changes to the content query web part and exported the web part configuration. I saved the file locally. I named it Content_Query_Branding_Blog.webpart.
  • Next I opened the Content_Query_Branding_Blog.webpart (which is nothing more than a XML configuration file for the content query web part).
  • I modified the ItemXslLink to point to my new ItemStyle_BrandingBlog.xsl. <property name="ItemXslLink" type="string">/Style Library/XSL Style Sheets/ItemStyle_BrandingBlog.xsl</property>
  • I modified the Title to <property name="Title" type="string">Branding Blog Content Query</property>
  • Next I went to Site Settings >> Web Parts Gallery >> and then upload the Content_Query_Branding_Blog.webpart.

Done.

Now you have created your own XSL style sheet and you have created a content query web part configuration that uses that style sheet. We will later automate this as part of a WSP deployment.

Now let’s jump into the configuration of the two web parts that I need to create for my technology article publishing page.

Related Articles Content Query Web Part

As you may recall I need to support the ability show related technology articles. So I want to query for all articles that are related to the one being viewed.

Step 1 – Create the XSL for Content Query Web Part

The first thing I need to do is create a view of data that will show the following:

  • The title of the article
  • The rating of the article
  • The last modified date
  • The first 300 characters from the article

To accomplish I wrote the following xsl in the ItemStyle_BrandingBlog.xsl that I created in the previous step. I did all of this in SharePoint Designer 2010.

<xsl:stylesheet 
version="1.0"
exclude-result-prefixes="x d xsl msxsl cmswrt"
xmlns:x="http://www.w3.org/2001/XMLSchema"
xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
xmlns:cmswrt="http://schemas.microsoft.com/WebParts/v3/Publishing/runtime"
xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:param name="ItemsHaveStreams">
<xsl:value-of select="'False'" />
</xsl:param>
<xsl:variable name="OnClickTargetAttribute" select="string('javascript:this.target=&quot;_blank&quot;')" />
<xsl:variable name="ImageWidth" />
<xsl:variable name="ImageHeight" />
<xsl:template name="TitleDateAndRatings" match="Row[@Style='TitleDateAndRatings']" mode="itemstyle">
<xsl:variable name="SafeLinkUrl">
<xsl:call-template name="OuterTemplate.GetSafeLink">
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="DisplayTitle">
<xsl:call-template name="OuterTemplate.GetTitle">
<xsl:with-param name="Title" select="@Title"/>
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<div>
<xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
<table>
<tr>
<td width="500px" colspan="3">
<hr />
</td>
</tr>
<tr>
<td width="300px">
<a href="{$SafeLinkUrl}" title="" >
<xsl:if test="$ItemsHaveStreams = 'True'">
<xsl:attribute name="onclick">
<xsl:value-of select="@OnClickForWebRendering"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="$ItemsHaveStreams != 'True' and @OpenInNewWindow = 'True'">
<xsl:attribute name="onclick">
<xsl:value-of disable-output-escaping="yes" select="$OnClickTargetAttribute"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="$DisplayTitle"/>
</a>
</td>
<td nowrap="nowrap" width="100px">
<xsl:if test="@Ratings &gt;= 4.75">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_5" alt="Current average rating is 5 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &gt;= 4.25 and @Ratings &lt; 4.75">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_4_5" alt="Current average rating is 4.5 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &gt;= 3.75 and @Ratings &lt; 4.25">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_4" alt="Current average rating is 4 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &gt;= 3.25 and @Ratings &lt; 3.75">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_3_5" alt="Current average rating is 3.5 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &gt;= 2.75 and @Ratings &lt; 3.25">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_3" alt="Current average rating is 3 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &gt;= 2.25 and @Ratings &lt; 2.75">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_2_5" alt="Current average rating is 2.5 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &gt;= 1.75 and @Ratings &lt; 2.25">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_2" alt="Current average rating is 2 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &gt;= 1.25 and @Ratings &lt; 1.75">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_1_5" alt="Current average rating is 1.5 stars." /></a>
</span>
</xsl:if>
<xsl:if test="@Ratings &lt; 1.25">
<span>
<a class="ms-currentRating"><img src="/_layouts/Images/Ratings.png" class="ms-rating_1" alt="Current average rating is 1 star." /></a>
</span>
</xsl:if>
</td>
<td nowrap="nowrap" width="100px">
<xsl:value-of select="ddwrt:FormatDateTime(string(@Date), 1033, 'M/d/yyy h:mm tt')" />
</td>
</tr>
<tr>
<td colspan="3" width="500px">
<xsl:value-of select="substring(@Description, 1, 300)" disable-output-escaping="yes" />...
</td>
</tr>
</table>
</div>
</xsl:template>
</xsl:stylesheet>


Let me discuss several of things I did to accomplishing this:




  • First I created a little HTML table that will control the format of the data. Then I started to add in fields.


  • The link title is printed here - <xsl:value-of select="$DisplayTitle"/> I simply took an example from the out of the box ItemStyle.xsl.


  • Next I needed to print the star ratings. I would have never figured this out until I found this article by accident - blog. This smart person showed how to do it and I just had to make a few minor changes for myself. Basically it looks at the rating value tied to the page rating. Then using styles it will print the appropriate star image.


  • Next I needed to print the last modified date. Here is the code that accomplished that <xsl:value-of select="ddwrt:FormatDateTime(string(@Date), 1033, 'M/d/yyy h:mm tt')" />. One thing to note is I had to add this namespace to the main xsl tag xmlns:ddwrt=http://schemas.microsoft.com/WebParts/v2/DataView/runtime. If you forget to do this, you will get errors.


  • Finally print the description I used the following line of code - <xsl:value-of select="substring(@Description, 1, 300)" disable-output-escaping="yes" />. In it I only print the first 300 characters. Plus I using the disable-output-escaping attributed to remove the embedded HTML in the article.



Step 2 – Test It



I saved my work and the next thing I did was test it to make sure the formatting looked good. To accomplish this I just went to a web part page. Here is a view of it with some test data in there. You can see I am getting the article title, start rating, a nicely formatted date and the article content. Now I just need to configure this into my Page Layout.



clip_image002[5]



Step 3 – Add and Configure the Content Query Web Part to the Page Layout



The last step is to configure this web part into the page layout. When I do this, now every page provisioned using this layout will have this web part pre-configured. What I did was:




  • Go back to my page layout.


  • Added a new row for Related Articles.


  • Open up the split view.


  • Then I will select Insert tab on the ribbon.


  • Then select the web part I deployed in the previous section.



clip_image004



Next I right click on the web part and select Web Part Properties which will open the same web part configuration panel I would use in the SharePoint UI.



clip_image006



I make the following configurations to the content query web part.



First I set up the query, pretty basics stuff. I set it to go against the pages library and only retrieve the Technology Article type.



clip_image007



Next I set up the Filters for the query. I only want to get articles that match on both technology and keywords. I also want to make sure to not get the same article.



For both the Technology and Enterprise Keywords I use [PageFieldValue:XXX] to retrieve metadata values from the article as part of the query. I will also note that if you have values in the URL querystring, you can use [PageQueryString:XXX] to access those values to use in the Filters.



To ensure I do not have the article itself appear in the query, I exclude it by the Title of the article which is a unique value for me.



clip_image008



Next I set it up to sort by star ratings.



Then in the Styles section I select TitleAndDateRatings style I created in ItemStyle_BrandingBlog.xsl.



clip_image009



The last part of the configuration is to set up the fields in the Technology Article to feed into the TitleAndDateRatings style.



clip_image010



I also set the Chrome to None to hide the web part header.



Now that is done I have the below results. I provisioned a Technology Article page, set the Technology and Keywords value. When I saved the article, the content query web part I pre-configured into the page layout will now be visible.



clip_image012



One important note it is not possible to change the configuration of the web part in the provisioned web page (like above). So if I went to edit the web page, I would not have the ability to edit the web part. If you want to support changing the web part configuration after page provisioning you will need to add a web part zone into the page layout and then put the web part into that zone. This can all be done in SharePoint Designer.



Just remember if you put a web part zone into the page layout, this will allow users to put in web parts in an ad-hoc fashion. So there is a real trade-off you have to consider. In my case, I actually used a web part zone at first, I trained users, and they still did not listen and started to add their own web parts. I ended up removing all the web part zones from the page layouts. This becomes pretty important in a real controlled publishing scenario.



Another note you should be aware of is if you make a change to the web part configuration in the page layout those configurations will not be pushed into provisioned pages either. This behavior is different that adding new fields or changing the presentation of the page layout which will change provisioned pages. This behavior makes sense and is expected; though all is not lost. If you really need to make a web part configuration change to all the provisioned pages, you can write some code to iterate through the pages and web parts to make changes. That is beyond the scope of my article but the SharePoint API supports it.



Confidentiality Web Part



The next thing I wanted to accomplish is create some sort of simple solution where I could visually indicate to the user that the data on the article is confidential. The environment I am deploying to does not have Sandbox Solutions enabled so writing a web part was not an option. To accomplish this, I was able to write a content query web part style.



Please note that this solution is not really secure. Page level security can be implemented but still users can accidently copy and paste content and email the information by accident. Web pages cannot be locked down with Information Rights management either. So a user can still copy and paste the information and email. The only real way to ensure this information is not sent out is to create a document library, configure information rights management in that library, load content into that library and then reference a link to the locked down content from the publishing page.



Step 1 – Create the XSL for Content Query Web Part



I followed the same steps and created a template in ItemStyle_BrandingBlog.xsl. The logic of this one is pretty simple. I basically have an If statement that checks to see what level of confidentiality the article has and then show visual indicator.




    <xsl:template name="Confidential" match="Row[@Style='Confidential']" mode="itemstyle">
<div>
<table width="100%" height="50px">
<tr>
<xsl:if test="@Conf = 'Confidential'">
<td style="background-color:red; color:black; text-align:center; font-size:large"><xsl:value-of select="@Conf" /> </td>
</xsl:if>
<xsl:if test="@Conf = 'NDA'">
<td style="background-color:yellow; color:black; text-align:center; font-size:large"><xsl:value-of select="@Conf" /></td>
</xsl:if>
</tr>
</table>
</div>
</xsl:template>


Step 2 – Test It



Then I test it with the web page I already configured.



Step 3 – Add and Configure the Content Query Web Part to the Page Layout



Then just like the last time, I opened the page layout in SharePoint designer and inserted the web part into the top of the page. I right clicked the web part and selected web part properties.



I set it query for the Technology Article type.



clip_image001



For the parameters I set it to only find articles based on the unique title.



clip_image002



For the presentation I set it to use the new Confidential style.



clip_image003[5]



I then provisioned a page, set the confidentiality and I had the following result. As you can see a big red banner is displayed to the user indicating that the content on this page should be created as confidential.



clip_image005



Conclusions



This pretty much concludes my exploration into creating custom content query web parts with SharePoint Designer 2010. I do recognize that if the queries for data become more complex, I recommend creating custom web parts and use LINQ to SharePoint to get out the data and present it. However I really like this solution because I was able to accomplish this without having to write a ton of complex code.



Next



We are going to explore how to redeploy this entire solution using Visual Studio.

Creating a Page Layout

Page Layouts

The next thing you will need to do as part of any major web content management project is create Page Layouts. Again, I am not going to provide a robust definition on what a Page Layout is because it is pretty well defined in books and on MSDN. What I am going to do in this example is create a simple content type and then create a page layout for the content type.

In this example I am going to create a Technology Article Page which will inherit from the out of the box Article Page. I will am going to add a couple custom fields to this content type like Confidentiality and Technology. I will later use these to do some fun stuff with content query web parts.

1 – Create a Content Type

Like I said the first thing I am going to do is create a content type based on the Article Page content type and add some of my own fields. For both Confidentiality and Technology, I am going to use the managed metadata service and term storm.

So first I created some terms:

clip_image001[4]

Then I created my new Technology Article content type which inherits from Article Page. Below is a screenshot of the new content type.

clip_image003[4]

Then you I created Confidentiality and Technology columns using the managed metadata. I also added the Enterprise Keywords column which allows for folksonomy tagging to be applied to my article. As well I have added Rating (0-5). Here is a screenshot of all the columns.

clip_image005[4]

2 – Create Page Layout

To create a new Page Layout:

  • Open SharePoint Designer 2010 and go to Page Layouts.
  • In the ribbon select new Page Layout.
  • Select the Technology Article content type. I will subsequently be taken to a page where I will be editing the page in advanced mode.

Now all I need to do is start adding in controls and HTML to build up the page layout. As you can see below, I have turned on the split view and the branding from the master page is being applied. Towards the bottom of the split view you notice the PlaceHolderMain outlined in light purple. That is where all the modifications will be made. You may not recall but this corresponds back to the Master Page. So when a page is rendered in SharePoint, both the Master Page and Page Layout are merged together to create the web page that is ultimately rendered.

clip_image007[4]

Within this screen I was able to compose a web page using the fields I have available to me from my content type. Here is the resulting screen that I created. Looks pretty basic but I have pulled in some core data fields, I am displaying managed metadata, and I am displaying the rating for the article.

clip_image009[4]

Here is a view of that same article in edit mode.

clip_image011[4]

Now to achieve this I did have to do several things in SharePoint Designer 2010.

clip_image013[4]

The process for creating the page was simple. First I created a HTML layout with some CSS embedded page layout to control the presentation. I put in a HTML table and then started dragging and dropping fields into the table. Now there are a couple little things you should know.

Metadata fields will not work when you drop them in. You need to add the following to the top of the page which will then allow the managed metadata fields to render on the page layout.

<%@ Register Tagprefix="Taxonomy" Namespace="Microsoft.SharePoint.Taxonomy" Assembly="Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>


The Rating (0-5) control will not work either unless the following is registered at the very of the page layout.




<%@ Register Tagprefix="SharePointPortalControls" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>


To display the created and modified date you will need to again add the following registration to the top of the page layout.




<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>


Lastly you may have noticed that the big wave logo is missing from this page layout. This is because I made a decision that the wave branding was taking up too much real-estate for an article. A little trick I did was adding some CSS to the page layout to hide it. I like this approach because I really want this logo to be part of the master page but just for this particular page layout I do not want to display it.




<asp:Content ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server">
<style type="text/css">
#logo { display: none; }
</style>
</asp:Content>


Page Layout Code



The following is the resulting code I created for the page layout.




<%@ Page language="C#"   Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" meta:progid="SharePoint.WebPartPage.Document" meta:webpartpageexpansion="full" %>
<%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Taxonomy" Namespace="Microsoft.SharePoint.Taxonomy" Assembly="Microsoft.SharePoint.Taxonomy, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePointPortalControls" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.SharePoint.Portal, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<asp:Content ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server">
<style type="text/css">
#logo {
display: none;
}
.TechArticleTitle {
font-weight:bold;
vertical-align:top;
width: 10%;
padding-right: 10px;
padding-left: 10px;
}
.TechArticleValue {
vertical-align:top;
}
</style>
</asp:Content>

<asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
Technology Article -
<SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server"/>
</asp:Content>
<asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">

<table>
<tr>
<td class="TechArticleTitle">Title:</td>
<td class="TechArticleValue">
<SharePointWebControls:TextField FieldName="fa564e0f-0c70-4ab9-b863-0177e6ddd247" runat="server"></SharePointWebControls:TextField>
</td>
<td class="TechArticleTitle">Modified:</td>
<td class="TechArticleValue" nowrap>
<SharePoint:FieldValue FieldName="Modified" runat="server" id="modified" ControlMode="display"/>
</td>
</tr>
<tr>
<td></td>
<td class="TechArticleValue" nowrap>
<SharePointPortalControls:AverageRatingFieldControl FieldName="5a14d1ab-1513-48c7-97b3-657a5ba6c742" runat="server"></SharePointPortalControls:AverageRatingFieldControl>
</td>
<td class="TechArticleTitle">Created:</td>
<td class="TechArticleValue" nowrap>
<SharePoint:FieldValue FieldName="Created" runat="server" id="created" ControlMode="display"/>
</td>
</tr>
<tr>
<td class="TechArticleTitle">Confidentiality:</td>
<td class="TechArticleValue" colspan="3">
<Taxonomy:TaxonomyFieldControl FieldName="a472e313-fd5f-4423-89b3-bdd721461eac" runat="server"></Taxonomy:TaxonomyFieldControl>
</td>
</tr>
<tr>
<td class="TechArticleTitle">Technology:</td>
<td class="TechArticleValue" colspan="3">
<Taxonomy:TaxonomyFieldControl FieldName="9129feba-3b4a-4dd7-82cc-0822730d16c8" runat="server"></Taxonomy:TaxonomyFieldControl>
</td>
</tr>
<tr>
<td class="TechArticleTitle">Keywords:</td>
<td class="TechArticleValue" colspan="3">
<Taxonomy:TaxonomyFieldControl FieldName="23f27201-bee3-471e-b2e7-b64fd8b7ca38" runat="server"></Taxonomy:TaxonomyFieldControl>
</td>
</tr>
<tr>
<td class="TechArticleTitle">Article:</td>
<td class="TechArticleValue" colspan="4">
<PublishingWebControls:RichHtmlField FieldName="f55c4d88-1f2e-4ad9-aaa8-819af4ee7ee8" runat="server"></PublishingWebControls:RichHtmlField>
</td>
</tr>
</table>
</asp:Content>


Conclusions



With that I hope that I have demonstrated how quick and easy it is to create some page layouts with data coming off my content types. I really think this is just such an awesome way and easy way to do web content management.



In the next part of this series I am going to further extend this page layout with content query web parts.



Next



We are going to explore content query web parts and how to integrate them with the page layout we just created.

Branding SharePoint 2010 Search

Search Template

Another thing you will quickly run into is when doing your custom branding is the Search Centers will not show your branding. In this case, I have FAST installed on my development machine. So I went ahead and created a FAST Search center and I had the following.

First thing you may try is go to the Site Actions >> Site Settings >> Site Features and turn on Publishing just like you did for other sub sites. But doing this will not make the FAST site show your custom branding.

clip_image002

Then when you go look at the Site Settings >> Master Pages you will notice that Site Master Page is set to minimal.master. You can try to try to set it to use your custom master page by selecting “Inherit site master page from the parent site”.

clip_image004

However you will get is a screen that looks like the following. Yes your branding came through but where is the search box?

clip_image006

You can do a lot more reading on the topic on why the search text box did not appear. At the end of the day the Search Center templates were coded to work best with the minimal.master template. Recently I took the approach of trying to make a copy of minimal.master and then apply my HTML template to it. It was a lot of work and I could not get it perfect. However this brilliant guy wrote a blog about this - http://blog.drisgill.com/2010/09/converting-custom-sharepoint-2010.html

I followed his steps exactly. I made a copy of my master page, applied all the changes specified in the blog and I got the following results in five minutes. With that I now have a perfectly branded FAST search center site.

clip_image008

clip_image010

Next

Next we are going to work on creating some custom page layouts to be deployed with this master page.