Jan 25, 2012

VisualStudio11 and SharePoint Online

Since there already is a good article about the VisualStudio 11 for SharePoint Online solutions and since I myself haven't got around to actually even install the developer preview yet, let me point you to the said article on the Office365 site:

How to: Use Visual Studio 11 to publish solutions to SharePoint Online
http://community.office365.com/en-us/b/office_365_technical_blog/archive/2012/01/11/how-to-use-visual-studio-11-to-publish-solutions-to-sharepoint-online-grid-user-post.aspx

I found it enlightening and thus wanted to share it!

Jan 19, 2012

Creating a Content Type for Custom PageLayouts

Even when you don't use any custom fields on your PageLayouts, and necessary if you do, it is worth its while to create a custom content type (or several, if you need to apply different fields to different PageLayouts) for your PageLayouts for several reasons:

  • custom content type enables grouping the PageLayouts in meaningful groups instead of the Custom group in the PageLayout menu
  • also, for content rollup with CQWP, with custom content type, it is possible to list only the pages that are of the specific content type
  • when using custom fields as well, it is possible to filter the content rollup by the custom field info

Creating the basic Content Type is a quick task. Add a new item to your SharePoint project, of the type Content Type:


Select then "Page Layout" as the base Content Type to inherit from, or one of your existing Content Types:


Edit the Elements.xml; change the Name, Group and Description to your liking.


If you want to create some custom fields for your content types, add the fields to the Elements.xml as Field-elements:


Generate GUIDs for the IDs of the fields.

Then add the field references to the Content Type FieldRefs. After that the Elements.xml should look something like this:


Now, to use this with your PageLayouts, first, set the Content Type of the PageLayout to your custom Content Type in the Elements.xml containing the PageLayout elements by setting the Content Type value and adding a PublishingAssociatedContentType-property with the ContentType ID to the file(s):


If you want to make it easier for the users to fill in the fields, add them to the PageLayout EditPanel:


FieldName gets the GUID ID you generated for the field. 

And maybe some information needs to be visible too, add those fields to the page html as well:


In edit mode, the page looks now like this: 


The Content owner is visible on page (and a bit stylized here):


(Page content from http://slipsum.com, my favorite Lorem Ipsum.)

Jan 18, 2012

Setting MasterPages to Sites Automatically

I have addressed this topic before in the article Automatize MasterPages in SiteDefinitions, but taking a little bit different viewpoint here, let's take a look at how to achieve this without custom Site Definitions. There are cases where custom Site Definitions are needed, of course, and in those cases, the feature stapling as described in the other article might be the way to go. Might be, I say, for it still isn't necessarily the best way, or needed, if the master pages are otherwise automatized throughout the Site Collection, as I will describe in this article.

For instructions on creating the basic custom UI solution, see Creating a Custom UI Solution for SharePoint.

With the masterpages done and other elements in order as well, it is time to deploy the solution. The solution contains a feature, and the activation of this feature will add the MasterPages and possible PageLayouts in the MasterPage Gallery of the SiteCollection, but unless we have a feature receiver to go with the feature, the rest is manual work.

To better understand the different MasterPages and their behavior on different types of sites, see About SharePoint 2010 MasterPages.

The first step for MasterPage automatization is to create a feature receiver that sets the MasterPages for the sites when feature is activated. Note, that if the feature is scoped as Web, it needs to be activated on each site separately. If it is scoped as Site, it is activated only once for the Site Collection and sets only the MasterPages of existing sites.

Add a feature receiver to the feature by right-clicking the feature > Add Event Receiver. Uncomment the FeatureActivated and FeatureDeactivated methods. For the FeatureActivated, insert the following code:


Note, that the MasterUrl sets the System Master and the CustomMasterUrl sets the Site Master. Foundation sites do not use the CustomMasterUrl at all, but it doesn't matter that it is set on those sites too.

For the deactivation method, copy-paste the same code, but change the MasterPages to e.g. v4.master and nightandday.master.

If we want to take this one step further, we can do some site identifying and set different MasterPages for different sites by their ID. E.g. the search site needs its own MasterPage, so we could add some code to the feature receiver so that it sets the search sites to use the custom search master, or if there is none, to keep using the default minimal.master:


You can check other site IDs e.g. in this article: Know the site template used for the SharePoint site.

Update your deactivation method likewise.

The feature receiver takes us as far as taking care of the existing sites. Next, let's take care of the new ones. Add an Event Receiver in your project:


Select Web Events, A site was provisioned:


Replace the default content of the method by the following code:


If you didn't use any ID-specific MasterPage settings in the feature receiver, you can disregard the if-else here too.

Creating a Custom UI Solution for SharePoint

To create a custom UI solution for SharePoint 2010, create a new project in VisualStudio2010, using the project template Empty SharePoint Project. Remebmer to set the Framework to 3.5!


Next steps are to the SharePoint SiteCollection you are using for testing, and to choose between Farm or Sandbox solution. I usually use the Farm Solution unless Sandboxing is required, because I prefer the Layouts folder for the stylesheets and images over the Style Library of an individual SiteCollection. Sandbox solution does not have access to the Layouts folder.

After the project has been created, add the mapping of the Layouts folder if you are creating a Farm solution:


or add a new module with the name StyleLibrary if you are creating a Sandbox solution:


Mapping the Layouts folder automatically creates a folder for your custom stylesheets etc. Inside this folder, create another one, Images.


The StyleLibrary module needs the same, so create a folder for your custom stylesheets, and one for the Images too. Also, delete the Sample.txt file from the module, it is not needed. 

Add a stylesheet to the UI.Assets folder, New Item > Style Sheet from the Web category:


If you are using the StyleLibrary, you need to check your Elements.xml now. The Module-node should look something like this:

Module Name="StyleLibrary" Url="style library"
File Path="StyleLibrary\Showcase.UI.Assets\SandboxSC.core.css" Url="StyleLibrary/Showcase.UI.Assets/SandboxSC.core.css"

When you add images in the Images folder, check your Elements.xml file if using the StyleLibrary. There should be a new File-element for each image, e.g.

File Path="StyleLibrary\Showcase.UI.Assets\Images\Logo.gif" Url="StyleLibrary/Showcase.UI.Assets/Images/Logo.gif"

Next let's add the MasterPages module. If you have installed the CKSDev tools, you can add a new CKSDev MasterPage (in this case, see more about using the CKSDev Starter Master Page), or add a new empty Module and name it MasterPages, in a similar way as the StyleLibrary module was added. Again, delete the Sample.txt file.

Add a starter MasterPage file to the module. You can use any OOB SharePoint MasterPage as a starting point (download a copy from the MasterPages Gallery), but I highly recommend to start with the a starter MasterPage from the Starter MasterPages by Randy Drisgill. There are starter files for publishing sites and foundation sites, pick the correct one for the correct purpose. 

To better understand the usage and inheritance of SharePoint 2010 MasterPages, see About SharePoint 2010 MasterPages.

After adding the first MasterPage, rename it if needed and then edit the Elements.xml file:


First thing to do with the newly added MasterPage is to create (or change) the custom CSS reference. In the starter MasterPages, this is ready for you:


When using the StyleLibrary, the reference would be like this:


Last thing before initial testing of the solution is to prepare our feature. Two things: rename it and set the scope. First rename the feature in the solution explorer, then double-click it to set the title and the scope:
  • Web, if the feature should be activated separately on each site - good for cases where not all sites need the same UI assets, or you want to activate the UI by using feature stapling with custom site templates
  • Site, if the feature should be used for the whole SiteCollection - only one activation required, for efficient use, create also a feature receiver and an event receiver for when sites are created

The base for the branding solution has now been laid.and the solution is ready to be tested. Right-click on the project name in the solution explorer and click Deploy. This both deploys the solution and activates the feature. When deploy is done, go to your site and set the MasterPage for the site - and start working with it! 

Since I do not use SharePoint Designer for any UI customizing, I need to deploy, re-deploy and so forth, the solution as I make changes. My method is to deploy the initial solution, as it is, and then start working with the sites in Firefox, using Firebug to try out the css when necessary before writing it in the css file. And of course the MasterPage needs a whole lot of html! The easiest way to apply changes to the SharePoint site after the initial deploy, is to use the Quick Deploy tool of the CKSDev tools.

When it is time to add PageLayouts, add a new module like with MasterPages. Download a copy of the most suitable OOB PageLayout from the MasterPages Gallery, and add the file to the module. Edit the Elements.xml; for one PageLayout should look something like this:


For information on creating a feature receiver and event receiver for a UI solution, see Setting MasterPages to Sites Automatically.

Quirks of the CKSDev Tools when Working with MasterPages

The CKSDev tools are a splendid toolset for SharePoint 2010 development. As I mostly create branding solutions, I use the Quick Deploy (Copy to SharePoint root) command for a quick and easy deploy without the tiresome iisresets and resulting reload delays etc. that come with the real deploy.


Most of the time this works perfectly, but in some cases I have noticed that it for some reason cannot update the MasterPage and PageLaouts files, but still works for the stylesheets and images. 

The other tool that comes in handy for me, mostly, is the Starter Master Page module. Mostly, I say, for this has a couple of issues. First, though, the reasons I still often prefer to use it for MasterPages rather than an empty module are
  • the included starter.master (by Randy Drisgill)
  • the better form of the Elements.xml, that is, it contains all the necessary properties for MasterPages ready made
  • most of the time the cranky VisualStudio html intellisense for MasterPages works with a bigger probability than when adding MasterPages in an empty module
The quircks are related to this feature not being a proper SharePoint module, but was designed for one MasterPage only and thus
  • you either need to create a new StarterMasterPage "module" with its own Elements.xml file for each new MasterPage
  • or you need to do a bit of manual work
The manual work required:
  1. the name you give the MasterPage when creating it as a new item, names both the "module" and the MasterPage file. E.g. if you name it MasterPages, then rename the MasterPage file and then you need to change the name of the file in the Elements.xml
  2. if you add new MasterPage files to the "module", you need to add it to the Elements.xml file yourself (this is easily done by copy-pasting) and set the Deployment Type property for it as ElementFile

About SharePoint 2010 MasterPages

I seem to have dropped bits and pieces of information, here and there, on the MasterPages in SharePoint 2010 and where and how they are and ought to be used when creating a custom UI solution. Time for a summary, here's a few words about the MasterPage usage and inheritance.
  1. There are two different MasterPage settings: the site MasterPage and the system MasterPage
    • Site MasterPage is used by publishing sites
    • System MasterPage is used by foundation sites and e.g. list views also on publishing sites
  2. The two above can be the same, or they can be different, e.g. if the publishing sites have no or a custom left navigation (or the publishing site version of the left navigation), the list views and foundation sites need a master with the quicklaunch navigation
  3. If there is a special MasterPage for the TopLevelSite (e.g. intranet front page), which often is the case (when it is not sufficient to simply hide elements from a special front page PageLayout), set this one first, and then you will need to set the MasterPage separately for each second level site because of the inheritance behavior described below
  4. While all other sites are fine with these one or two masters, the search site needs its own, for by default it uses the minimal.master, so we need to have a custom MasterPage derived from the minimal.master in order to show all elements on the page as should be
  5. About the inheritance:
    • Publishing sites automatically inherit the MasterPage from its parent site
    • When the Publishing feature is turned on for a foundation site, it too inherits the (system) master of its parent site
  6. When activating the custom UI feature with a MasterPage-setting feature receiver, the MasterPages will be set for all existing foundation sites, but not the ones created after this
  7. The MasterPages are referenced in a feature receiver or event receiver as
    • Site Master : CustomMasterUrl
    • System Master: MasterUrl
As to how to create a custom UI solution, see Creating a Custom UI Solution for SharePoint
and for instructions on creating a feature receiver and event receiver for masterpages, see Setting MasterPages to Sites Automatically.

Jan 4, 2012

Building a Custom ContentQueryWebPart

Since I have just gone through building my first custom CQWP for a publishing site collection, step by step, thought I'd share some notes on it. It's basically really not too complicated, but it does have a few quirks to go with it.

ContentQueryWebPart uses two main xsl-files:
  • the ItemStyles.xsl for item templates
  • the contentquerymain.xsl for the outer templates
Most often what you would be interested in customizing, is the ItemStyles.xsl which is located in the Site Collection Style Library, in the XSL Style Sheets folder. This provides the templates for items in the query result, enabling you to e.g. add fields to show, alter the order of fields and add additional html and style classes to item templates. This, of course, requires knowledge of xsl, how deep depends on what you are trying to do.

The first thought might be "ok, I'll open the ItemStyles.xsl to SharePointDesigner and edit it". I say no, you don't. You open the ItemStyles.xsl to SharePoint Designer and copy all its content and paste it to an xsl file in VisualStudio. But wait! We're not that far along yet, so let's back up a bit.

Yes, the correct way to do this is to create a VisualStudio 2010 project and package it as a wsp solution package. So start by creating an Empty SharePoint (2010) Project (remember to check that your Framework is set to 3.5). 


Type a site to use as test site and select the solution type (either one is ok, sandbox or farm). Add a module (Add > New item) in the project:


Delete the Sample.txt file and add a new item to the module:


Note, the item added is xslt-file (from Data category), remember to change the file type to xsl, e.g. CustomItemStyles.xsl.

Open the Elements.xml file of the module and edit the module information by adding the Style Library as the Url for the module and XSL Style Sheets folder as the Url of the item:


Now it is time to locate the original ItemStyles.xsl and open it for editing in SharePointDesigner. There is no need to check it out since there is no need to edit it, simply copy the contents of the file and paste them to the xsl file just created in VisualStudio. VisualStudio will notify (as an error) that the named template OuterTemplate-etc. does not exist, but don't mind this. The OuterTemplates are defined in the contentquerymain.xsl, which will be available for the custom CQWP without needing to copy it to the project.

Now what we ought to do, is select one of the existing templates as the basis for the custom one - this saves a whole lot of work. So if you're not sure which is a good starting place, insert a CQWP on your site and try out the different OOB templates. Then locate the template you want to modify, copy the complete template tag and paste it on the xsl sheet as a new template tag. Modify it as you like - you can move the divs around and create your own (remember to assign a class for your div!), but be mindful to maintain the schema and general structure of the template!

Now, the item template being done, it is time to add the webpart in the project. The OOB CQWP does not know how to use the custom xsl and there is no way to implement it, so we need to create our custom CQWP as well. Add a SharePoint webpart item in the project:


You don't need the webpart's .cs-file, so you can delete that. Then open the browser again, add a new CQWP on a page and export the webpart without setting any properties. Once saved on your disc, open the webpart file and copy and paste its contents to the webpart file in VisualStudio, replacing the default content created by VS.

Change the title of your webpart:


Then locate the properties ItemXslLink and ItemStyle and set them to point to the custom xsl:


Yes, that's right: no slash between ~sitecollection and Style Library.

Furthermore, if you want to make things neat, you might want to change the category in which the webpart is found on the site. The deafult is Custom, but you can change it by opening the Elements.xml file of the webpart and typing your own group name:


Ok, now we're almost done. The last thing to deal with is the features. Adding the module created a feature and adding the webpart created another one. There is no need for two features, so you can delete the other one. The clue is to delete the right one. Double click on each feature to see its properties. The first one only contains the styles module, the second one shows both modules (although you need to add the styles module to the feature items). Delete the first one, and add the styles module to the other one. 

Also, you might want to rename the feature. One thing is to rename the feature in the feature properties and the other to rename the feature file in the solution explorer (right-click the feature > Rename). You might want to do both.


The final thing to do, is add a feature event receiver. Why? Because for some reason at least a publishing site collection otherwise refuses to let the custom CQWP use the custom xsl file, informing that it is not trusted. So this feature receiver corrects this problem by specifically assigning the sitecollection url for the webpart.

Right click your feature and add an Event Receiver to it. Open the event receiver for editing, uncomment the FeatureActivated method and add the following code to the method, changing the wp.File.Name value to your own webpart name.


(Thanks for the feature receiver goes to our coder, couldn't have come up with it myself!)

Note that you need to add the using statements for System.Linq and System.Text.

You're solution tree should now look like something this:



Now you are ready to package, deploy and test the webpart! 

Tip: If you need to do this more than once, which usually is the case, the easiest way to make it happen is to copy-paste the original xsl and webpart files to your disc drive (or such). Then you don't need to always do the same opening and copying all over again.