Friday, November 04, 2011

If you still don’t ‘get’ what Governance is

True story: About one year ago I went to Microsoft TechEd in Berlin and attended all types of sessions. I was there to learn about technology, and I somewhat accidentally attended a session on SharePoint governance. I didn’t really know what that was, and frankly I couldn’t have cared less. I am a techie, and this was some sort of new fad that the global companies were all raving about. Some sort of corporate mumbo jumbo that was useless when it came down to doing some real work. Not a single line of code in the entire talk, just a bunch of Visio.

Does that sound familiar? Can you identify yourself in that story? If so, I will try to explain to you why this governance thing is being discussed so much, and why you actually do need to be aware of it, even as a hard core techie.

Let’s talk about traffic. I don’t mean network traffic, I mean the kind most of you get into on a daily basis out in the streets. When you get into your car, or I on my bike, there is a lot that goes on between leaving home and getting to work. First, there are all the roads we need to navigate. Then there is the weather that can cause the road conditions to change. Lastly, there are all those other people out there on the road who are also trying to get from point A to point B. It is fair to say that the traffic on our roads today is a complex system, and no one really has a grasp of the ‘overall plan’ for the day. Somehow we all make it to where we need to go most of the time, and when something does go wrong, it usually degrades in a way that is acceptable. By this I mean that fatal accidents are fairly rare as opposed to fender benders, and fender benders are rarer yet when compared to being late due to congestion.

So why am I on about traffic? Because I think this extremely complex system that is used by a huge number of human beings at the same time could not work if it weren’t for governance. There's that word again. Let’s see what I mean by governance in terms of traffic. Those of you who have driver’s licenses should know a good deal of traffic governance, by that I mean your local traffic laws. Every new driver is taught that red lights mean stop, what a yield sign looks like and what it means, and how fast a vehicle may travel on a given road. These rules are what ensures that we all behave in a given way on the road, and thus don’t run into each other very often. Being human means we don’t always get it right, but that’s another story.

There are other rules that the average driver doesn’t know that are just as vital to the success of our daily drive. What type of road surface is used? What is the minimum radius of a turn on the expressway? These are rules the road engineers need to be aware of.

There are also specific situations that warrant their own set of rules and behaviors. When something does go wrong, the emergency response teams have a very well defined protocol to handle that event, ensuring the best possible outcome for those impacted and the quickest possible return to normal conditions.
Lastly, I want to mention the massive differences in how traffic operates in different locations. Compare rush hour in Bangalore http://www.youtube.com/watch?v=0cdUPOvSXOo with rush hour in Berlin http://www.youtube.com/watch?v=6jUc6dHcbCo and rush hour in Utrecht http://www.youtube.com/watch?v=UlQYP4WN-5w. You immediately see there are some localized differences. Some places drive on the right side of the road, some on the left, and some have dedicated lanes for bike traffic. Some places have a visible order and structure to the driver's behavior while others exhibit what looks like chaos to the outside observer. Nevertheless, each is designed with a single purpose to get everyone from point A to point B as safely and quickly as possible.

So what does all this have to do with SharePoint, and specifically SharePoint governance? As mentioned, the traffic system is very complex. What makes it complex however are not the roads or vehicles but all the individual people that interact with it at any given point in time. Each with a different goal in mind, and each not aware of the needs of the others in the system. What makes it work, is the adherence to the rules and guidelines that belong to that system.

If we compare the road system to SharePoint, we can see that there are many similarities. I would argue that the bits provided by Microsoft on the SharePoint DVD are the equivalent of concrete, asphalt, vehicles and traffic lights. They represent a possibility, or opportunity to create a useful (and complex) system. When we start a new SharePoint project, it is vital that we decide on rules and guidelines with which we will use all the components available to us. We may not even want or need all the components at all places. Just because there are thousands of road signs available to a road designer, doesn’t mean it is useful to use each and every one. How helpful is this scenario?


The first step we need to decide is why we are building our SharePoint system to start with. A road crew generally needs to build a road to connect two places, to improve traffic flow in a congested area, or to upgrade a broken down old road. Our SharePoint project needs to be just as clear in purpose. Replacing an old intranet that doesn’t work anymore, connecting two remote offices so they can share information. Those are very clear and simple reasons that make it easy to understand why we are starting a new project. Saying that we need to “improve collaboration in the enterprise” is simply too vague and would be the equivalent of saying that we need to build a road to “enhance the citizens driving experience”. I’d like to see a city allocate budget to that project.

Once we have a purpose, we need to decide on the rules and guidelines that we will follow so that we can achieve our purpose. There will be different types of rules for different scenarios. Some will be very hard and some quite flexible. Road crews can choose which end of the road to start at, or even which sections to work on at what time. They can't however just decide to route the road through a nature reserve because it makes it easier.

The rules will also not be the same for all organizations. We may have a different set of goals and a different culture. In road terms, the Netherlands sets speed limits that are quite absolute. There are many speed cameras and getting caught gong just a few km/h over will result in a fine. In the Toronto area, going 20 km/h over the limit on the expressway will generally not raise any interest from the police. As a matter of fact, I remember it being somewhat rude to go any slower. Culture has a huge impact on the rules we follow and how.

In SharePoint projects, we will have to determine the rules that work for our organization. Some hard rules will need to be set, such as access rights for instance. More flexible rules may include good practices with respect to metadata use and version control. We also need to determine the rules and guidelines for different target groups and different scenarios. Our end users will not be interested in the rules regarding database maintenance, but our IT department will need to be very aware of these. We also need to consider special cases such as system failures, and the procedures that need to be followed in order to respond to these. In the traffic scenario we can think of the highly organized Emergency Response Teams. In SharePoint we can think of disaster recovery plans. How often do you think the EMTs practice their routine, and how often does your project practice their disaster recovery?

Having determined these rules, we should have a good place to plan our project in terms of specifics. How will we build what is needed and who will be involved. This activity happens on most projects today, but it’s critical to know that this plan should be a derivative of understanding why we are building something, and what the desired behavior with that something is. In road terms, we can plan the best roundabout out there, but we need to know that it’s purpose is to slow down driver’s top speed but at the same time not forcing them to stop completely. If our goal was to purely increase traffic flow, an underpass may have been a better solution.

Once we have a good idea of the rules we think we should be following, we need to create a strategy that will ensure all the people interacting with the system will understand these rules and guidelines. Think how much effort is spent training new drivers. We may find this annoying when we go through it, but ask the average driver if they would prefer that people ‘learn by getting out on the road’ and I think most would think this a terrible idea. There is a reason we have drivers licenses. In the SharePoint project this translates to training. We need to ensure that our users are shown what hey should and shouldn’t do. This includes explaining our general purpose for the existence of the system as well as the specifics of how to perform certain actions. If you only know how to drive the car, you are not yet ready to get out on the road.

Lastly, we need to know how well our system is doing. One of the most famous and successful traffic solutions on the planet are the German motorways, known throughout the world as ‘the Autobahn’. A key ingredient to this complex system is monitoring. There is an entire team constantly monitoring the situation of all the roads in real-time and adjusting the speed conditions etc. to ensure most optimal operation. Our SharePoint projects will generally not have the luxury of such monitoring, but that doesn’t mean we can forget it all together. We need to define measures of success, and keep an eye on our SharePoint solution to see how it is performing. This includes measuring technical data such as bits and bytes but also more human data such as user satisfaction. We can then react to our measurements and tweak the system or the rules and guidelines around the system to improve the overall performance.

So what about Governance? We’ve somehow lost that word in the last few paragraphs. Governance is a collection all the rules and guidelines that get our project from the initial vision to a operating and continuously adapting solution. Governance is everything from the hard rules of how often we perform a backup to the soft guidelines that let our users know which content type they might want to use for a given document. It also includes the rules of the project itself, such as what type of user training do we perform, and how do we measure success. There are many facets to Governance in a SharePoint project and each of them is crucial to the overall success.

I hope you now have some understanding of what this Governance thing is, and why you should care about it regardless of what your role on the SharePoint team. It comes down to you and your team, do you want to build the autobahn, or are you ok with spending a lot of time, money and effort on this:



PLUG: I have to give credit to the SharePoint Information Architecture and Governance Master class since the idea for this blog post originates from discussions during that class and I would not have written this if it wasn’t for that fantastic course. If you want to know more about this topic, I highly recommend attending.

Also thanks to 21 Apps and the work they are doing on Governance in the SharePoint space, awesome work guys, keep it up.

Tuesday, November 01, 2011

Navigation on Public Facing SharePoint Sites

One thing that all sites (SharePoint or not) need is some form of navigation. This is true for all sites, not just public sites. There are plenty of types of navigation elements, but if we stick to public sites, there tend to be the following few types:

  1. Main navigation. This is almost always a horizontal list of links across the top of the page. These links do not change regardless of where on the site the user is. Sometimes each link will have a sub-navigation that is shown using JavaScript when the user hovers over a link.
  2. Contextual navigation. This navigation can manifest itself in many ways, sometimes as a tree view, sometimes as a flat list. In any case, the content of this navigation is usually different per page, or at least per section of the site.
  3. Reverse Navigation (Bread crumb). This is some type of path allowing the user to see where in the site they are, and to navigate back the way they came from.

In SharePoint, we have out of the box elements that provide all three types of navigation mentioned. They may not work exactly how we need them, but they are there for the most part.



On projects I was involved in, we never ended up using any of the built in navigation controls. Even thought they have been improved for SharePoint 2010, they still render html that never happened to fit the html we needed for the site. So how did we solve our navigation needs? There are a few options that I have used, I’m sure there are others out there:

  1. Static, hard coded links. This scares the crap out of some people, but I argue there are still plenty of scenarios where hard coded navigation is perfectly acceptable. As an example, take the apple.com website. How often do those links across the top change? Almost never. And when they do change, it is likely due to a very rigorous change management process. This is a case where I would advocate a hard coded solution. On the rare occasion the links change, update the master page.

    Advantage: Best performance, Easy

    Disadvantage: Potential for dead links

  2. Custom navigation controls based on SharePoint navigation providers. Just because the web controls that SharePoint delivers may not suit your needs, the navigation information they contain may be just what you want. In this case, use one of the providers that SharePoint offers. See MSDN on how to get started. http://msdn.microsoft.com/en-us/library/bb897657.aspx

    Advantage: Dynamic, Flexible

    Disadvantage: Can be hard to get right, Usually lots of work

  3. Navigation that has nothing to do with navigation. What do I mean? Show a list of the published pages from the pages library of the current site. That has served us as a viable navigation strategy on a number of sites. Usually best suited for the contextual navigation category. There is a strong potential downside of using this approach. It is very simplistic and doesn’t implement any performance optimizations or security trimming. So if used in an incorrect scenario, it can have nasty side effects. For me this method has generally been useful when there are a number of content pages that need to be shown for a certain category, etc, and if a page was published, it should be visible for everyone.

    Advantage: Relatively easy to build, Dynamic

    Disadvantage: Only suitable for simple cases

  4. Search. Yes, you can use search as a viable navigation method. There are ways that you can prepopulate a search result set and display this as navigation. We used this on a project for a “Related Items” type of navigation.

    Advantage: Very dynamic

    Disadvantage: Depends on good search results, Can’t always know what will be in there
So as usual with SharePoint the right answer for whatever you are doing is “it depends”. I would however stress that whatever your choice of navigation solution for a public site, don’t forget that you are building for the end user and make sure you are sending friendly HTML, etc to the client.

Thursday, October 20, 2011

Build for the end user

I attended a session at the European SharePoint conference today about building public facing websites using SharePoint. I respect the effort that the speakers put into their session and I agree that they had a nice looking web site created. However I strongly disagree with the methods they demonstrated and was disappointed to see these methods demonstrated as good practices.

There were two specific methods that I strongly disagree with demonstrated at the session:

  1. Hiding the ribbon for anonymous users with CSS.

  2. Using web part zones and web parts like the Content Query Web Part on public facing page layouts.

Both of these techniques are a symptom of what I call building for the editor. As developers we often work very closely with the editors when developing the site, and we thus tend to focus on making the site in such a way that the editor has a very easy life. This is not necessarily bad, but it comes at a cost. If we look at the big picture, the ultimate reason for the website being built is to be consumed by the end users. Editors are an important part of the picture, but we should be building the site for the end users. So why would that be different than building for  editors? Simple answer: page weight.

Why care about page weight? The days of large bandwidth and low latency are over (if they were ever here). Many users these days are accessing your site via networks that are not gigabit LAN, but instead are  3G networks or something similar and will notice when your home page is 300kb and sends another 300kb of JavaScript and CSS along. There are real costs attached to this in money, battery life and time spent waiting.

The good news is that there is a solution. In a previous blog post http://jcapka.blogspot.com/2011/08/public-facing-sites-using-sharepoint.html I introduce a webtemplate that includes a very lean masterpage and serves as a good starting point for building public SharePoint sites.

Friday, August 26, 2011

There are comments and then there are comments

The title may be somewhat vague, but in this post I want to alert you to the different type of comments you can use when working with ASP.NET. I have seen too many developers not understand the difference between

<!-- Comment-->
and
<%-- Comment --%>
The first type is an HTML comment which instructs the browser to ignore the contents. The second type is  an ASP.NET comment which instructs the ASP.NET parser to ignore the contents.

This is a very important distinction. The first type of comment means nothing to the ASP.NET parser, and is handled just like any other HTML in the page. That means that if I put something along the lines of:
<!-- <asp:Literal runat="server" Text="joe was here"/> -->
into my web page, the ASP.NET parser will stil parse this and execute the code in that literal. So my HTML will look something like
<!-- joe was here -->
When this becomes very important is at times where a developer thinks they have commented out some controls, but they haven't really, it's just that the output of that control isn't being displayed by the browser.

Imagine a line like:
<!-- <myControls:SomeVerySlowThing runat="server"/> -->
A novice developer may be under the impression that 'SomeVerySlowThing' has been commented out, but in reality, the code for that control is still being run.

Another time this is important is when trying to create lean and efficient HTML. Adding comments to HTML is handy, it is however still content being sent down the wire. If you are trying to make your HTML as lean as possible, use the ASP.NET comments and they will not show up in the end result HTML.

Wednesday, August 24, 2011

Free Brainstorming Session

Are you interested in what SharePoint is and what it could do for your business? XComplica is currently offering a free brainstorming session to help you answer these questions!

Visit www.xcomplica.com/Promo for more details.

Tuesday, August 23, 2011

Public facing sites using SharePoint 2010

This post is the first in a series that will walk you through building public facing sites in SharePoint 2010. I will discuss a method that I use for this process, whether or not it is the best method I leave up to you to decide.
In the past I used site definitions, but I recently decided to switch to the new web template method. In order to save myself and others time in the future, I have created a starter web template for public sites. You can download this at Codeplex: http://xcomplicaps.codeplex.com

I have to thank Mirjam van Olst and Vesa “vesku” Juvonen for their blog posts that were extremely helpful in putting this web template together.

http://www.sharepointchick.com/archive/2011/02/10/using-web-templates-to-create-site-collections.aspx

http://blogs.msdn.com/b/vesku/archive/2010/10/14/sharepoint-2010-and-web-templates.aspx

In this post, I will walk through the components in this web template, and how you can get started using it. Later posts will build on this one.

If you haven’t already, you may want to download the solution from Codeplex, and open it in Visual Studio.
Disclaimer: The solution is meant to be used on a development machine running SharePoint 2010. I also have the CKS Development tools installed and urge you to do the same.

You will see that it is a relatively small and simple solution containing one project. The project consists of a number of components, and we will go through each one.



Web Template (XComplicaPublicStarter)
There are two files that define the web template. There is the onet.xml file and the Elements.xml file. The Elements.xml file tells SharePoint about the web template and the onet.xml file defines the components of the web template. This means that any changes to the information about the web template, such as its name, description and display category should be changed in the element.xml file. This is similar to the webtemp_zzz.xml file for site definitions. The onet.xml file is a very stripped down version of the onet.xml used by the Publishing Portal site definition (BLANKINTERNET#53). Everything has been removed except for one configuration, and this configuration contains nothing except site level features and web level features. The features are the same as for the Publishing Portal, except there is one extra added at site scope and web scope, and these add the custom components we will be discussing later in the article. Two changes have been made to the web scoped publishing feature. The master page has been changed to a custom master page, and simple publishing has been turned on.

Three Features
There are three features as part of this project, one for farm scope, one for site scope and one for web scope.

The farm scoped feature has only one component, and that is the web template just discussed. It ensures that you can create a site collection based on this web template.

The site scoped feature contains elements that are global to the site collection as listed below. These will each be discussed in detail later:

• Master pages
• Page layouts
• Site columns
• Content types
• Global branding files

The web scoped feature contains elements that apply to the web itself and these will also be discussed in detail later:

• Content type binding
• Home Page
• Property Bag Setter

The web scoped feature also includes an event receiver. This event receiver enables anonymous access to the web. Since this is a public facing site, it is handy to have anonymous access automatically enabled on deployment.

Master pages
In the modules section, you will find a module called master pages. There are two master pages here, one is the very well known starter master page by Randy Drisgill, _starter_publishing.master.

http://blog.drisgill.com/2010/02/microsofts-sharepoint-2010-starter.html

The other master page, xcps_blank.master, is a stripped down version of Randy’s master page. This master page is what I use as a starter master page, and it has very little visible content. In this page I have commented out or removed as much of the html as possible, and I placed those placeholders that I could not remove into hidden panels. This technique is nothing new, I just took it further than others. There are only two content placeholders that are left in the visible portion of the page, the PlaceHolderMain and the PlaceHolderPageTitle. I assume these will be used on most if not all public facing sites.

I have also added a few links to content in the head section of the master page, since I assume every site these days will include at least one css file, one javascript and likely a favicon. These three branding files are located in the branding module and are meant to be changed when creating a new site.

I also add a reference to jQuery, but note that this is a reference to the CDN version of jQuery. There is no need to host this file locally.

As you develop your site, you will likely want to use one of the other placeholders or other components that are currently hidden. This is perfectly fine, just cut and paste them from the hidden panels into the appropriate location.

Note that I have also removed the ASP.NET form tag. I don’t see a need for it in a clean public facing site, but if you do find yourself needing it, feel free to add it back. There is a great article on how to make web parts work without the form tag on Waldek’s blog.

http://blog.mastykarz.nl/web-parts-in-content-with-master-pages-without-the-form-tag-no-problem/

Page Layouts
There is currently only one page layout in the project, and that is for the home page. It is very simple since this layout will differ for every site. I have added some very basic components in the PlaceHolderMain just to demonstrate how content can be rendered. There is a standard SharePoint Webcontrol for rendering html and there is a custom control that I developed for rendering Publishing Images. SharePoint provides a control called RichImageField http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.publishing.webcontrols.richimagefield.aspx that is meant for this, but I find it renders too much extra html around the image. I therefore created a simple server side control that renders just the img tag and some core attributes. You can see (and change) the code for this in the ServerControls folder of the project.

Site Columns (Fields)
Most public facing sites will contain at least a few different types of pages. These different types of pages should be represented by a number of content types, and content types are composed of fields. The StarterFields element contains one file which defines three site columns. One is a simple numeric site column used for ordering pages and the other two are Publishing site columns used to hold the html and image that the home page renders. You will add fields to this file, or create a separate element for your fields as you need them.

Content Types
Two content types are defined in the project. The generic content type is meant as a base type for all pages. It inherits from the built-in Page content type and it contains any fields that are common to all pages in the site. As it is, it contains one field which is the Sort Order. I find that a common request from authors somewhere down the line is to be able to order pages in some custom order, and so I always ensure this field is in all page content types.

The other content type is for the home page. It inherits from the generic content type and contains two fields as a sample. These are the Main Image and Body Text fields. Any site you build from this template will likely have different needs, so this will change. Note that I strongly advise using a separate content type and page layout for the home page and not share these with other pages. The home page of any site tends to be a very special page that evolves and changes in a different fashion from the rest of the site.

Global branding files
Every public facing site will need some custom CSS, JavaScript and probably a favicon. I have created a module to contain these files, and they are deployed into the Style Library. There are a number of discussions out there regarding the use of the Style Library, read Andrew Connell’s article for a good introduction.

http://msdn.microsoft.com/en-us/library/dd221375.aspx

Note that I have referenced the CSS, JavaScript and favicon files in the master page.

Content Type binding
Every web that has the publishing features enabled has a Pages library. If we want to be able to create pages based on the content types we define, we need to bind these content types to that Pages library. There is an element file in the Content Types folder that takes care of this, just remember to add a reference in that file to any new content types that you create.

Home Page
The home page is an instantiation of the home page layout, the home page content type and some actual content. The home page module is where this is all put together. The aspx page itself just has a reference telling SharePoint to use a page layout, this is the same for every instance of a publishing page. The interesting stuff is in the elements file, which defines the properties of the page, as well as the location (Pages List) that the page should be deployed to. Notice that the properties include the page layout, the content type, but also properties like Title, Body Text, etc. Also note that the MainImage property has been specified and contains a link to an image from teh style library. That image is provisioned as part of the branding module. In a different post I will show how to provision actual content into image libraries. For most pages we would allow authors to add the content, but for some pages as well as for test purposes it can be useful to prefill some content in.

Property Bag Setter
Due to the way web templates work, there is no way to know what web template was applied once the provisioning of the site is finished. It is therefore best practice to add a property in the web’s property bag in order to store this information. See the links above about web templates for more info on this.

Getting it all working
Now that you’ve had a full tour of the project, you should be able to create a site based on this template. You first need to specify a Site URL in the project properties so that it points to a valid SharePoint URL. What is somewhat annoying here is that we will be creating a new site collection based on this web template, but there already needs to be a site collection at the Site URL you specify. I often just start by creating a blank site at that URL, since I know I will be deleting it right after deployment. There are some PowerShell shortcuts you can also take, but I’ll leave those for another time.

Once your project has deployed, go to central administration and open up the page for creating site collections. You should see a new tab, and in that tab the Public Starter template.

Before you create a new site collection, I suggest you delete the blank site that you needed to deploy the project. This is up to you, but if you do so, you can create your new site collection at the root URL.
From this point, it is the same as creating any out-of-the box site collection. Once the process completes, you should be greeted with a new site based on the components discussed. Just for fun, look at the source and the page weight of your new site, and compare this to the regular SharePoint publishing template.

Conclusion
In this article I walked through the different pieces that make up the XComplica Public Starter web template. The purpose of the template is to create a clean starting point for creating lean and clean HTML sites using SharePoint. In future articles I will expand on how to create different types of pages, how to implement custom html into this template and other topics.

Tuesday, August 16, 2011

SPSTC Slides

I spoke at SharePoint Saturday The Conference and as promised, here are the slides for both sessions and the transcript of the powershell presentation.

I also promised the code for the branded site, I will clean this up and post on codeplex in the near future. I will also write some articles on the process of creating such a site, so keep an eye on this blog.

Slides of Branded Site talk
Slides of Powershell talk
Transcript of Powershell talk

Wednesday, July 06, 2011

Speaking at SharePoint Saturday the Conference

I am excited to say that I'll be speaking at the SharePoint Saturday Conference in DC August 11-13 2011. I will be presenting two sessions, both very hands on and demo oriented.

Building a Fully Branded SharePoint Website will focus on how a SharePoint developer implements a public facing website from HTML delivered by a design agency. This is a scenario I have done many times and have learned a lot of lessons the hard way doing this. I want to share the process as well as many of the pitfalls and best practices I have learned over the years. I'm going to try and build the site from scratch in the session, a bit of a challenge.

Practical Powershell for SharePoint is a session I delivered once for our DIWUG user group and got great feedback on, so I thought I'd share it with some more people. The session assumes the audience to have some Powershell experience and quickly dives into a number of scenarios that demonstrate some useful and clever ways of making your life easier by using Powershell. Those who have had the of working with me will know that "Use Powershell" has been one of my favorite answers to many problems over the years. Powershell has only been on the SharePoint main stage since the release of 2010 but I've been using it for years now, and I want to share some of the more unusual and inspring ways I have found of leveraging the tool.

Hope to see you at the conference!

Friday, May 20, 2011

Deploying a Document Library including content using a Feature

Recently I needed to deploy a SharePoint document library as a feature, but with some documents already in it. In my case it was because of demo content, the customer wanted to do some training and needed a pre-filled document library. I can see this useful in other times however, such as including templates for documents, etc.

The solution for this is not difficult, but since I could not find any instructions online for this I thought I'd write a post.

In short, you need to create a feature that includes two components. A list instance based on a document library and then a module with the documents that you want to add to your library. The module has to point to your newly created library and all is well.

Let's walk through this. Start up Visual Studio and create a new empty SharePoint project. You can choose to use a sandbox solution, this code works just fine in both sandbox and farm modes.


Next add a new item, of type list instance.



Choose 'Document Library' as the base type, and make sure to clean up the display name and URL. I personally hate the defaults that Visual Studio creates for these.


Next add another new item to your project, this time of type module.


Delete the sample file from the module, and add the documents that you want to automatically be part of the feature rollout. I copy the files using windows explorer to the appropriate place and the use the "show all documents"button in Visual Studio to include them in the project


Once you have added all the required files and removed the sample file from your module, the elements.xml file of the module should look something like:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="DemoDocumentContent">
  <File Path="DemoDocumentContent\demo1.docx" Url="DemoDocumentContent/demo1.docx" />
</Module>
</Elements>

This needs to be modified so that the documents end up in the new library you are creating. First open up the elements.xml file of the list instance you created, and copy the Url attribute.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance Title="Demo Documents"
                OnQuickLaunch="TRUE"
                TemplateType="101"
                FeatureId="00bfea71-e717-4e80-aa17-d0c71b360101"
                Url="Lists/DemoDocuments"
                Description="">
  </ListInstance>
</Elements>


Now paste that Url attribute in the Module element of the elements.xml file for the module. Then remove all but the filename form any Url attributes of individual file elements in that file.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="DemoDocumentContent" Url="Lists/DemoDocuments">
  <File Path="DemoDocumentContent\demo1.docx" Url="demo1.docx" />
</Module>
</Elements>

The next step is to add the Type="GhostableInLibrary" attribute, otherwise your files will not be visible in the browser.

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="DemoDocumentContent" Url="Lists/DemoDocuments">
  <File Path="DemoDocumentContent\demo1.docx" Url="demo1.docx" Type="GhostableInLibrary" />
</Module>
</Elements>

Lastly you should rename the feature that Visual Studio created for you by default, fill in a Display name and optionally a description and ensure that the List instance and Module elements are included in the feature.


When you deploy this solution to a SharePoint site, it will create a document library with the documents in it, as desired.

In case you are working on a similar situation as I was and are creating this for demo purposes, there is one last very useful piece. That is cleanup. I have added a feature event receiver to my solution that deletes the document library when the feature is deactivated. This ensures that the person delivering the training can very quickly recreate the document library with the initial content by deactivating and reactivating the feature. The code needed for this is:

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            //Delete the demo list with all content
            if (properties.Feature.Parent is SPWeb)
            {
                SPWeb web = (SPWeb)properties.Feature.Parent;
                SPList list = web.GetList("/Lists/DemoDocuments");
                web.Lists.Delete(list.ID);
            }
        }

So to summarize, it is very easy to build a feature (which can run in the sandbox) that creates a document library including some default documents already in the library. The feature should be web scoped, include a list instance element and a module element with all the necessary content files. By changing the url parameter in the module we can ensure that the documents are placed in the new document library.

Sunday, May 08, 2011

Great Motorcycle Ride

Disclaimer: Not a SharePoint post


Mel and I took a fantastic ride on the motorbike today. For anyone in the Amsterdam area who rides motorcycles, here is a great trip:


View Larger Map

Thursday, April 28, 2011

XComplica SharePoint 2010 Usage File Analyzer

At my last DIWUG talk I mentioned that the Web Analytics functionality in SharePoint 2010 begins with the WssTracing service creating .usage files in the 14\LOGS folder. These files are in some nice binary format and it would sometimes be nice if we could open these up for debugging purposes.

So I cracked open reflector today and had a look at the code MS uses to import these files. A day later, and I created a little tool that reads these files and lets you have a look into them.

You can download the XComplica SharePoint 2010 Usage File Analyzer for free, and I am willing to share the (messy) source code if anyone wants. All at your own risk of course, this is just something I threw together in one day.

UPDATE: The code is now on Codeplex

It's quite self explanatory, grab a copy of the .usage file you are interested in, open it with the tool and you will see all the entries is a nice table. The fist column is clickable and shows the details of each row, since there are seven types of usage entries that the files contain. Simple but effective

Nice surprise in my mailbox

I was awarded the Microsoft Community Contributor Award yesterday for the time I have spent in the forums. Thanks MS and whoever else may be responsible. I like new flair for my blog. Not quite at 37 pieces but working on it. :)

Thursday, April 14, 2011

Speaking at DIWUG

I will be speaking at our local user group (DIWUG) on the 26th of April. I will be talking about the built in Web Analytics in SharePoint 2010. For more info see the agenda. Should be a fun talk, I'll do my best to make it entertaining.

If there is anything specific you want to see/hear, leave a comment or get me on twitter @jcapka

Wednesday, March 16, 2011

Copying Managed Metadata between site collections with code

I was recently writing an event handler on a list that was suposed to copy the contents of a list item form one site collection to another. The code was fairly simple except that the Managed Metadata columns would not copy.

My first attempt was to simply copy the value of the taxonomy field from one list item to another, this worked for all the other fields in question, so why not?

//targetItem and sourceItem are SPListItem type
targetItem["metaColumn"] = sourceItem["metaColumn"];

This didn't work. I then did a quick search and found (somewhere that I can't find now to give credit) that I had to use the SetFieldValue method of the TaxonomyField class to assign the value. Ok, so my next attempt was:

TaxonomyFieldValue value = (TaxonomyFieldValue)sourceItem["metaColumn"];
TaxonomyField taxTargetField = (TaxonomyField)targetItem.Fields.GetFieldByInternalName("metaColumn");
taxTargetField.SetFieldValue(targetItem, value);

This didn't work either. I suspect this would have worked if the two list items were in the same site collection.

The next attempt actually worked, and it went like this:

 TaxonomyField taxTargetField = (TaxonomyField)targetItem.Fields.GetFieldByInternalName("metaColumn");

TaxonomySession taxonomySession = new TaxonomySession(targetItem.Web.Site);
TermStore termStore = taxonomySession.TermStores["ManagedMetadataService"];

taxTargetField.SetFieldValue(targetItem, termStore.GetTerm(new Guid((sourceItem["metaColumn"] as TaxonomyFieldValue).TermGuid)));

The main point to notice here is that I had to create a new reference to the term, using the context of the target site. So it seems that setting the value of a taxonomy field requires using a Term or TaxonomyFieldValue that is fetched out of a TaxonomySession from the same site as the field itself.

Thursday, March 10, 2011

Why I think ViewState is EVIL

The infamous ASP.NET ViewState has been with us for a long time now, and yet I often get the feeling that most developers have no idea how it really works. Over the years, I have told the following story to a number of developers, and while there are a number of articles on the web about this, I still keep seeing code that makes me cringe too often. Perhaps my post can add to the various articles and cause a critical mass that will once and for all put an end to ViewState. Or perhaps not. :)

Enough rant, let's dive into the tech stuff. Take the code below, seems fairly common right? It should, I copied this from MSDN.

private void Page_Load(object sender, System.EventArgs e)
{
   if (!Page.IsPostBack) 
   {
      // Put user code here to initialize the data source 
      // (such as filling a dataset)
      DataGrid1.DataBind();
   }
}

Let's look at this code in detail. This is the page load event, it fires fairly early in the ASP.NET page life cycle, and it fires every time the page is loaded. This event includes a comment that suggests we need to add some code here to initialize data, but since that code can be expensive to run, it is cleverly wrapped in a condition that ensures it is only run the first time that page is loaded. The idea is sound, why go to the database for the same data over and over again right?

Let's think about this a little more. When the page is loaded after a post back, the data needed for the datagrid is not fetched from the database, and the databind event is not called. (It can be called from an event handler, but not necessarily). So where does the data for the datagrid come from? In most solutions that use this type of code, that place is the ViewState. It is the most 'out-of-box' way to get a datagrid to work, and thus this code is quite prominent.

Ok, so is there a problem? Yes, and a large one. First off, what is the ViewState really? Despite what many developers believe, it is not a magical property bag that makes your life easier, it is just a hidden input field in the html rendered to the client. Do a view-source on any asp.net web forms site and you'll find something like the following, except I cut out a lot of the VALUE:

<input id="__VIEWSTATE" name="__VIEWSTATE" type="hidden" value="/wEPD....2Lk=" />

The VALUE that I cut, is actually an encoded version of all the data needed for the various controls that are set to use the ViewState.

Let me repeat something at this point. The ViewState is a hidden input field in the html rendered to the client. For those who think about performance, you should be realizing a problem. For all the rest of us, I present a picture:


In this crude diagram you see the web server, the database server and the client which for illustration purposes I made a smart phone accessing your website. The connection between the web server and the database is drawn to be a fat pipe of wire, since they typically sit in the same data center that you have influence over. The connection between the web server and the phone is a 3G connection.

What the code that we see at the beginning of this article does is as follows. The first time the phone request our site, the web server gets the data for the datagrid from the database server over the big fat pipe, generates the HTML including the ViewState and sends it down to the phone. That means that the data for the datagrid is not being sent to the client just once, but twice since once copy is in plaintext and the other copy is encoded in the ViewState. Worse yet, when the client decides to post back to the page for some reason, the web server needs the client to post the ViewState data back so that it can render the new HTML. This is really important to understand. Instead of getting the data for the datagrid from the database using a big fat pipe of a connection, we are getting it off a phone over a 3G connection. This is the worst place I can think of to be caching data. Again, instead of using a fast wired local connection to a fast database, we are fetching that data over a 3G connection from a slow smartphone.

Now that you understand what is going on, here are some other not so small issues to consider.

1) The ViewState is encoded. This means that every time the page is sent and received, it has to encode and decode the ViewState. It may not seem like much but I have seen this bring a server down at a large financial institution.

2) In the current world of mobile internet, users do not appreciate when we send them large pages because we are using their phone or tablel as a data caching solution. First of all the pages are slow, and second, not everyone has an unlimited internet contract so extra kbs count!

So what can you do? Turn off the ViewState. Guess what, you can get most of your website to work without it. There are some features of some ASP.NET controls that do need the ViewState but not that many. Personally I don't use those features and find alternatives. Still, most of ASP.NET works just fine without ViewState, but you do need to put a little extra work into it.

Start by reading an article like this one detailing how ViewState works, and always question where your data comes from.
http://msdn.microsoft.com/en-us/library/ms972976.aspx#viewstate_topic8

Thursday, February 10, 2011

ASP MVC and SharePoint 2010

Ever since ASP MVC came out, I have been a huge fan. I love how MVC embraces the web instead of abstracting it like web forms do. Being a SharePoint guy however, I am currently stuck with web forms. Now I have to admit that web forms work great for an intranet data oriented solution, and this is also where SharePoint has a lot of strength. I however tend to focus on internet facing web sites where MVC is far superior in my opinion.

It should come as no surprise that I have been wondering how to use MVC in SharePoint, and have tried a few things. There are a number of people who have done the same:

http://sharepointmvc.codeplex.com/
http://vspug.com/mbailey/files/2010/04/Using-ASP.NET-MVC-2-with-Sharepoint-Publishing.pdf

and all are good efforts.

Still, the efforts above all seem like fitting a square peg in a round hole. Not exactly elegant at all times, at least that is my feeling.

So I took another approach at this and think it works quite well. The key, the SharePoint client object model. Yeah, it's that simple. Let me walk you through it.

First, let's fire up Visual Studio and create a new MVC 2 project and make sure to choose .NET 3.5 in the framework drop down.
NOT MVC 3! This is because SharePoint runs on .NET 3.5 so we are currently stuck MVC 2 and no Razor :(




Go though the wizard, create your app with or without a test project (as you wish) and get your MVC app running. Nothing new here.

Now open up the Index view of the home controller, and ensure that the MainContent placeholder content looks like the following:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%= Html.Encode(ViewData["Message"]) %></h2>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
    </p>
    <img src="<%=ViewData["image"] %>" alt="" />
</asp:Content>

All this does is add an image tag that we will populate from the ViewData. For the rest it is the same as was generated by default.

Now open up the Home controller and go to the Index action. Here we will add code to talk to SharePoint with the Client object model, and pull out some data.

The code (this code is purely for illustrating a point, it is NOT production quality):

public ActionResult Index()
        {
            // get the client context
            ClientContext clientContext = new ClientContext("http://yoursharepointsite.local");

            // get the web reference
            Web site = clientContext.Web;
            clientContext.Load(site);
       
            // get the pages list reference
            List pages = site.Lists.GetByTitle("Pages");
            clientContext.Load(pages);
 
            // get the item with ID 1
            ListItem page = pages.GetItemById(1);
            clientContext.Load(page);
            clientContext.ExecuteQuery();

            // fish out the property PublishingPageImage
            string image = (string)page["PublishingPageImage"];
            
            // do some string magic to get the URL out of the property value
            int start = image.IndexOf("src=\"")+5;
            string imageUrl = image.Substring(start);
            int end = imageUrl.IndexOf("\"");
            imageUrl = imageUrl.Substring(0, end);
            imageUrl = string.Format("{0}{1}", sourceSite, imageUrl);

            // set the viewdata properties from the page item values
            ViewData["Message"] = string.Format("Title: {0}", site.Title);
            ViewData["Image"] = imageUrl;

            return View();
        }

Let's walk through it:

First we create a client context from a sharepoint site. This particular code is going to a stie at http://yoursharepointsite.local, you need to change this. I should also point out that the SharePoint site at that URL is a standard SharePoint Publishing Portal.

Next we get a reference to the root web, and then to a list called 'Pages' which should be familiar to anyone using SharePoint.

Then we get the first item in that list, just using the ID.

Since this is a standard Publishing Portal, we know that the content type this page uses has a field named 'PublishingPageImage' so we get the string value in this field. This value is the entire img tag which we don't necessarily want so we use a but of string magic to get just the value of the src element.

Lastly we populate some ViewData properties with values we got from the list item.

The magic happens when we run the MVC application. And I mean just run with F5 form Visual Studio. If all is well, you will see the following:


Recognize that image? And the title of my SharePoint site is 'Demo'. That you will have to believe. :)

Now let me point out something. Note the URL in the browser. This site is not running as part of SharePoint, it is not even on the same server! It is running on the built in Visual Studio web server, so it could run pretty much anywhere. As long as the user who is running this code has access to the items on the SharePoint site, this MVC site can run wherever. So in case of an internet site, Just make sure you have your SharePoint site set up for anonymous access, and your MVC site will work just fine.

This is an extremely simple demo example, just to get you started. Having thought about this for a bit, I think I would NOT enable anonymous access on my SharePoint site, and use a nice model in MVC to access SP as a specific user that is meant just for this purpose. This would involve some type of image handler so that images could be accessed by anonymous users, but that is not too hard to create. This approach combined with good caching could allow me to have an MVC site with content coming from SharePoint, but without the end user ever coming in contact with SharePoint. Another blog post perhaps....

Hope this gets your imagination going on how we can get lean and clean HTML and still use SharePoint as a place to store and manage all the content which it is great for.