Friday 16 December 2011

Put another tool in the old kit bag and smile…

I thought I would compile a list of a few of my favourite free SharePoint development tools this week, ideal stocking fillers for your favourite SharePoint developer; if you have any other suggestions then I would be eager to hear them.

Visual Studio 2010 SharePoint Power Tools
The current iteration doesn’t contain a great deal of tools but the ones it does have are great. If Compile time verification of Sandbox solutions is not enough it also provides the ability to include Visual Web Parts in your sandbox.

SharePoint Log Viewer
If it’s worth knowing it’s in the SharePoint ULS logs. Trying to analyse these logs in Notepad or via FindStr can be an exercise in pain. The SharePoint Log Viewer can be found in CodePlex and makes checking your solutions straight-forward, just place a filter on Area and your done.

NotePad++
Everybody has their favourite editor, mine was notepad for many years, however times change and now I swear by NotePad++. This nice editor pretty much does it all while providing a clean colour coded interface.

.NET Reflector 6
The ultimate tool for assisting you override those pesky SharePoint classes. The free version 6 is a little tricky to get hold of now but surely such a useful tool is worth a few quid.

SharePoint CAML Viewer
I have to confess that I wrote my own CAML viewer / creator some years ago however this tool is almost as good.

Defraggler
Keep your development environment running in tip top condition by defragging regularly. This tool allows you to see which files are the worst offenders and defag a file at a time.

These are just a few of the tools that I use on a day by day basis, I haven’t included all my own custom tools and PowerShell scripts such as WarmUp, SharePointVersion and DevDashboard toggler.

Well I’m off to wring the neck of the Christmas goose, mull my wine and steam my figgy pudding so to everybody out there have a very good Christmas and an excellent New Year (assuming we’re still here).

Wednesday 7 December 2011

Reporting Services with SharePoint Integration

I have been using Reporting Services with SharePoint since 2004 and always believed this was a match made in heaven. After not looking at it for a few months I completely forgot about how to configure the permissions for the SharePoint Document Library which is beautifully documented on the Microsoft site (of course).

The main permission that foxed me was how to enable Subscribe on the Actions menu. To enable this add “Manage Alerts” to the permission level of your users / group.

Wednesday 30 November 2011

Put an end to NaN and other tips

When you are using InfoPath you will often come across fields being rendered as ‘NaN’ (Not a Number). This usually occurs when a repeating element does not exist.
I have seen a number of ‘solutions’ to this problem so I thought I would add my two penny worth:
If you convert the number to a string then you cannot get the ‘NaN’ error. Finally you may want to do something with the number so prefix it with a zero:
concat(‘0’,string(<element>))
The number always defaults to zero and you may use round, floor max with the warm feeling that NaN will no longer make an unwanted appearance.

... and what about another tip? The other day I was trying to put a validator on a multi-line textbox to restrict the number of characters, I have done this before but for the life of me I could not remember how I did it. Dutifully I added the regular expression which of course failed, after some puzzling I remembered you can simply use string-length(expression) > 255. Regular expressions in InfoPath should always be a last resort.

Wednesday 16 November 2011

Give a bit of feedback

Ever had a InfoPath Form Services form with a simple Submit and Close mechanism but wanted to give the user that little bit more ? Wouldn’t be great if we could display a status message to the user ? Well you could create a separate form view to display a confirmation message or we could just display a SharePoint status message like the one below…

image

By using a custom link to launch the InfoPath form and including a query string within our source message we can trigger a status message within a content editor web part.

Just add a content editor web part to the page and add a little JavaScript magic:

   1:  <script type="text/javascript">
   2:   
   3:    var l = window.location.href;
   4:    l = l.replace('?','&');
   5:    var p = l.split('&');
   6:    
   7:    for(var i in p)
   8:      if (p[i].indexOf("status=") >= 0)
   9:      {
  10:        var values = p[i].split('=');      
  11:        var value = values[1];
  12:   
  13:        if (value=='ok')
  14:        {
  15:           ExecuteOrDelayUntilScriptLoaded(ShowStatusInfo, "sp.js");
  16:        }
  17:      }
  18:   
  19:     function ShowStatusInfo()
  20:     {
  21:        msg = SP.UI.Status.addStatus("Expense Form", "<img src='/_Layouts/Images/mewa_info.gif' align='absmiddle'> <font color='#AA0000'>Your expense claim was submitted successfully</font>", true);
  22:        SP.UI.Status.setStatusPriColor(msg, "yellow");
  23:     }
  24:   
  25:  </script>

 

 

Launch the page with a query string including &status=ok and hey presto you have a happy user.


Of course the close button will also display the same message but I leave that as an exercise for the reader…

Saturday 12 November 2011

User Conflict & InfoPath

Conflict? Users love InfoPath ! Well they don’t if their changes get overwritten by another user who opened and edited the form at the same time. What we need is some conflict resolution.
Conflict resolution comes in three flavours: None, Optimistic and Pessimistic:
  • None, nothing, nada, zilch – this is the default conflict resolution that InfoPath Form Services provides out of the box. One user’s changes will simply overwrite another's.
  • Optimistic resolution optimistically presumes that no-one would have the audacity to edit and change the form while another is editing it. Before saving the form it checks to ensure the form timestamps match and if they don’t breaks the bad news to user that it cannot save their changes. This is the default mechanism used by SharePoint lists.
  • Pessimistic resolution takes no chances and locks the form as soon as the user opens it for edit. While this may sound like the obvious answer to our problem it does come with a few issues such as managing the locking. For example, imagine user A opens a form for editing and a lock is put in place. User A suddenly realises it is past 5pm, they close the lid on the laptop and leave work looking forward to their two week skiing holiday. Oops our form is now locked for two weeks. SharePoint implements this mechanism through Check In / Check Out.
So which mechanism should I choose ? If there is only one user editing the forms then no conflict resolution is required. If the form is not substantial or is rarely updated then optimistic should be sufficient. Large or heavily edited forms should take the pessimistic route.

Implementing Optimistic Locking within InfoPath

This is relatively straightforward create a SharePoint library data connection to retrieve the current item’s metadata (include data for the active form only) including the the modified date and who modified it. When the form is opened retrieve the information and store it within the Main data source. On submit query your data source and check the dates match, if they don’t break the news to the user, possibly on another view.

Pessimistic Locking

This is slightly more complicated.
Step 1: On opening the form we need to check that the form has not been checked out to another user, if available we can then present the user with an Edit button (we don’t want to check out the form just for a user wanting a quick look). If checked out to another user we can display a message to the user and disable or hide the edit button.
Step 2: With the form checked out the user can edit their form with confidence. The form could be automatically checked in on Submit or you could provide a Check In button so they can close the form and come back to it.
This can all be achieved without code thanks to the foresight of those chaps and chapesses that implemented the SharePoint web services. You will need to create three data connections:
  • FormInfo : The same connection you created for optimistic locking to acquire the Checked Out To property and the name / title of the form.
  • CheckOut : Add a data connection to the SOAP web service http://<site collection>/_vti_bin/lists.asmx?WSDL and select the CheckOutFile method. The method takes three parameters: PageUrl – the URL to the form; CheckOutToLocal – false; LastModified – this can be left blank.
  • CheckIn : Add a data connection to the SOAP web service http://<site collection>/_vti_bin/lists.asmx?WSDL and select the CheckInFile method. The method takes three parameters: PageUrl – the URL to the form; Comment – Automatic Check Out; CheckInType – 1 (see link).

Add some rules

  • Add a Form Load rule to query the FormInfo data connection and set the query field PageUrl for the CheckIn and Check Out data connections.
  • Add a formatting rule to hide a section containing the checked out message if the FormInfo Checked Out To, Person count = 0 or the Checked Out To, Person, Account contains the current user.
  • For the edit button we simply need to add an action to query the Check Out data connection.
  • For the Submit or Check In button we add an action to query the Check In data connection.
That’s it… Well you may want to add a few more rules and potentially some security checks such as checking the SharePoint group the user belongs to (see this excellent article) or getting more information on the user using our old friend the userProfileService.

Note: Since SharePoint 2010 Service Pack 1 there may be issues with performing the above where Claims based security is enabled.

Monday 31 October 2011

Filtering the InfoPath 2010 Multiple-Selection List Box

So you want to have a Multiple Selection List Box on a form that displays values from a secondary data-source but want to store the value ids within the main data source. No problem.

Now just the selected values need to be displayed. Just filter the main data source values with a lookup right – wrong! This is not compatible with InfoPath Form Services. In order to achieve this you must add the secondary data source as a repeating section. Add a calculated field within this for the display value with conditional formatting to only display the values that occur within the main data source. This works !?

image

To check that the ID is within the main data source: Count how many nodes exist within the main data source exist with the same ID as the one being displayed, if it is less than one then don’t display i.e.

count(xdXDocument:get-DOM()/my:myForm/my:MainList/my:mainItems[. = current()/d:ID]) < 1

Spell Check within InfoPath 2010 Browser Forms

One thing I have never understood is the lack of a spell check facility within InfoPath Form Services forms. SharePoint has a spell checking web service which can be viewed at “_vti_bin/SpellCheck.asmx” so why can this not be used ?

Well it can and here’s how:

Override a list form into an InfoPath form via the Customise form options:

image

Once saved select the Form Web Parts and edit the New Form as follows: Add a Content Editor Web Part to the top; edit the HTML and add the following:

   1:  <script language="javascript" src="/_layouts/1033/SpellCheckEntirePage.js?rev=zYQ05cOj5Dk74UkTZzEIRw%3D%3D" type="text/javascript"></script>
   2:  <script language="javascript" type="text/javascript">
   3:     function CheckSpelling()
   4:     {
   5:        SpellCheckEntirePage('/_vti_bin/SpellCheck.asmx', '/_layouts/SpellChecker.aspx');      
   6:     }
   7:  </script>
   8:   
   9:  <a onclick="CheckSpelling();" href="javascript:"><img alt="Spell Check" src="_layouts/1033/images/RTE2SPCHK.GIF" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px"/></a>
  10:   

The form spell check relies on the SpellCheckEntirePage JavaScript file so this must first be included. All that is left to do is call it.

Save and close the page and now should end up with something that looks as follows:

Untitled

Press the spell check button and the form is spell checked. Should you not want to spell check a specific field then you will need to exclude the controls first by setting the attribute excludeFromSpellCheck to true.

It would be nice to package this into a feature for the Ribbon but I will leave this as an exercise for the reader.

Wednesday 5 October 2011

XSLT List View Web Part (XLV)

XLV is the default List view technology in SharePoint 2010 replacing the XSLT LVWP used within 2007. Within XLV the data is generated directly from the ViewXML providing us with a consistent way of formatting the results. More information can be found on the SharePoint Team Blog and on MSDN.

To format a web part, edit the web part and expand the Miscellaneous property section, you will notice an XSL Link property. This allows us to override the default formatting by entering a path to an alternate XSL transform file.

To illustrate, upload the following XML to a folder in the Style Library of your site collection with the name “xlvAll.xsl”. Now add a task web part to your home page and set the XSL Link property to point to the file. The web part should render the raw ViewXml, this is a great starting point for formatting the results.

   1:  <?xml version="1.0" encoding="UTF-8"?>
   2:  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   3:  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
   4:      <xsl:template match="/">
   5:          <xmp>
   6:              <xsl:copy-of select="*"/>
   7:          </xmp>
   8:      </xsl:template>
   9:  </xsl:stylesheet>

So lets format the results of the web part, upload the following XML to the same Style Library folder with the name “xlvTask.xsl”. Update the XSL Link property to point to the file.


   1:  <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office">    
   2:      <xsl:template match="/">
   3:          <table class="ms-listviewtable" cellspacing="0" cellpadding="1" width="100%" border="0">     
   4:              <thead>
   5:                  <th class="ms-vh2">Title</th>
   6:                  <th class="ms-vh2">Status</th>
   7:                  <th class="ms-vh2">Percent Complete</th>
   8:              </thead>      
   9:              <xsl:apply-templates />
  10:          </table>
  11:      </xsl:template>
  12:   
  13:      <xsl:template match="Row">
  14:          <tr>
  15:              <td> 
  16:                  <xsl:value-of select="@Title"/> 
  17:              </td> 
  18:              <td> 
  19:                  <xsl:value-of select="@Status"/> 
  20:              </td> 
  21:              <td> 
  22:                  <xsl:value-of select="@PercentComplete"/> 
  23:              </td> 
  24:          </tr>
  25:      </xsl:template>
  26:      
  27:  </xsl:stylesheet>

This should give you something resembling the image below:


image


While being able to override the formatting of the web part is useful it is not always appropriate, sometimes we just need to format a couple of columns, this is where the new format comes into its own. The XSL below will override the status and the percent complete fields to display them graphically within the existing web part and the best bit is that we can re-use this across multiple web parts.


   1:  <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal" xmlns:o="urn:schemas-microsoft-com:office:office">
   2:      <xsl:include href="/_layouts/xsl/main.xsl"/>
   3:      <xsl:include href="/_layouts/xsl/internal.xsl"/> 
   4:   
   5:      <xsl:template name="FieldRef_body.Status" match="FieldRef[@Name='Status']" mode="body">
   6:          <xsl:param name="thisNode" select="."/>
   7:              <xsl:choose>
   8:                  <xsl:when test="$thisNode/@*[name()=current()/@Name] = 'Completed'">
   9:                      <img src="/_layouts/images/IMNON.png" alt="Status: {$thisNode/@Status}"/>
  10:                  </xsl:when>
  11:                  <xsl:when test="$thisNode/@*[name()=current()/@Name] = 'In Progress'">
  12:                      <img src="/_layouts/images/IMNIDLE.png" alt="Status: {$thisNode/@Status}"/>
  13:                  </xsl:when>
  14:                  <xsl:otherwise>
  15:                      <img src="/_layouts/images/IMNBUSY.png" alt="Status: {$thisNode/@Status}"/>
  16:                  </xsl:otherwise>
  17:              </xsl:choose>
  18:      </xsl:template>
  19:      
  20:      <xsl:template name="FieldRef_Number_body.PercentComplete" ddwrt:dvt_mode="body" match="FieldRef[@Name='PercentComplete']" mode="Number_body" ddwrt:ghost="" xmlns:ddwrt2="urn:frontpage:internal">
  21:          <xsl:param name="thisNode" select="."/>
  22:          <div style="position:relative;width:100%;height:15px;background-color:red;color:white;">                         
  23:              <div>
  24:                  <xsl:attribute name='style'>height:15px;background-color:green;width:<xsl:value-of select="translate($thisNode/@PercentComplete,' %','')"/>%</xsl:attribute>
  25:              </div>                        
  26:              <div style="position:absolute;top:0;left:0;text-align:center;width:100%"><xsl:value-of select="$thisNode/@PercentComplete"/></div>
  27:          </div>
  28:      </xsl:template>
  29:  </xsl:stylesheet>

This results in the following:image


I should mention that you of course can open SharePoint Designer and format the web parts on the page however this is not always appropriate.

Wednesday 28 September 2011

Dialogs Become Shy following Site Restore

I came across this following restoring a site collection the other day. When I selected an event item I received the message “The website declined to show this webpage” (see image below) – how rude !

image

The event item in question contains managed metadata. As we all know managed metadata is synchronised to a hidden list within the site collection aptly named: “TaxonomyHiddenList”. This list does not inherit permissions thus the security for the list was invalid which explained the curt response from the dialog framework.

I resolved the issue as follows:

Navigate to <sitecollection>Lists/TaxonomyHiddenList/ and follow the following six easy steps:

  1. Navigate to the "Pemissions for this list"
  2. Select Inherit Permissions
  3. Select Stop Inheriting Permissions
  4. Add Authenticated Users (NTAUTHORITY\Authenticated Users) with Read permissions
  5. Update the System account (SHAREPOINT\system) to have Full Control
  6. Remove all other users

Tuesday 27 September 2011

Bulk Deleting Site Collections

This is not for the faint hearted. The other day I was testing the creation of a few hundred site collections under a managed path; this went well until I came to the point of deleting them and performing another test, the UI is definitely not the way to go.

For your delectation please find below a one line power-shell command to bulk delete number prefixed site collections under a managed path:

Get-SPSite | Where {$_.url -match http://web/sites/[0-9]} | Remove-SPSite -Confirm:$false

Use at your own risk…

Filtering Log Files

I spend a good portion of my time examining SharePoint log files. While it is possible to reduce this time by using the excellent SharePoint Log Viewer it doesn’t give you the power that the old Unix Grep command gives. There is a similar command within Windows you will be glad to hear called FindStr.

FindStr searches for patterns of text in files using regular expressions. Here are a few real world examples:

Example 1 - create a text file of all lines that contain the string ​”Warning:” in the file myLog.txt

FindStr /L “Warning:” myLog.txt > warnings.txt

Example 2 - create a text file of all lines that contain the string ​”Warning:” in all text files recursively

FindStr /L /S ​”Warning:” *.txt > warnings.txt

Example 3 - create a text file of all lines that contain the regular expression all lines that contains ERROR and Object and output to a text file.

FindStr /R .*ERROR.*Object.* myLog.txt > errors.txt

Thursday 8 September 2011

SharePoint Designer 2007 Workflow – Configuring the default Task List

When creating a workflow within SharePoint Designer you will note that unlike the out of the box workflows it does not prompt you for the default tasks list.
To configure the Task list:
  1. Navigate to the task list you wish to use, select Settings, List Settings; Right click on Audience targeting settings or Information management policy settings and select Properties. Copy the list GUID from the address URL e.g. {b8b415e2-89fa-40cb-a598-85eec0cd6271}
  2. Navigate to the Workflow folder in SharePoint Designer and expand it
  3. Double click on the <workflow name>.xoml.wfconfig.xml file, locate the Association TaskListID and replace with default GUID with the new task list GUID from step 1.
  4. Save and republish the workflow
For more information on SharePoint Designer 2007 workflows see the Microsoft site.

Example of wfconfig.xml file:

<WorkflowConfig>
    <Template
        BaseID="{99CCD0B6-D5BC-46E4-A6C7-3054C2157FCE}"
        DocLibID="{6FA134EA-846D-46BD-8F2A-246D103A5A01}"
        XomlHref="Workflows/Test Workflow/Test Workflow.xoml"
        XomlVersion="V7.0"
    >
    </Template>
    <Association
        ListID="{FB7C61AA-3F15-4914-A965-C6F24ED2FD7F}"
        TaskListID="{b8b415e2-89fa-40cb-a598-85eec0cd6271}"
        StartManually="true"
    >
    </Association>
    <ContentTypes>
    </ContentTypes>
    <Initiation URL="Workflows/Test Workflow/Test Workflow.aspx">
        <Fields/>
        <Parameters></Parameters>
    </Initiation>
</WorkflowConfig>

Saturday 27 August 2011

Microsoft InfoPath : Electronic Forms for the Business

I’ve been using InfoPath since 2004 and am continually amazed at how many businesses have never heard of it, or have it but have never considered using it. The thing is, you have probably used it without knowing it; have you ever completed a Document Information Panel in Word or a workflow form in SharePoint?

Microsoft InfoPath is part of the Microsoft Office family, providing a facility to design, distribute and complete electronic forms within your business. The current iteration of Office (Office 2010 Professional Plus) offers InfoPath as two products: InfoPath Designer 2010 and InfoPath Filler 2010.

Why migrate your company forms from Word and Excel format to InfoPath ?
  • InfoPath forms can be published on the desktop, via Email or to the Intranet, Extranet or Internet.
  • The forms can contain validation and business logic far above what can be achieved in Word and Excel without writing a line of code.
  • Instances of the form are stored in XML format which can be easily integrated into your back office systems.

Publishing forms

InfoPath offers a design once use everywhere approach. Forms may be published to the network, via email / Outlook, Microsoft Forms Server, SharePoint 2007, SharePoint 2010, or Office 365.
Please note that for browser based completion of your forms within SharePoint a SharePoint Enterprise CAL will be required.

Client based Forms may be completed via the InfoPath Filler 2010 application or embedded within Office or a Windows forms application via the InfoPath form control. InfoPath is integrated into most Office applications in the form of the Document Information Panel. In Outlook 2007+ forms may may be viewed as emails.

Form Design
Forms may be designed within the InfoPath Designer application which provides the same Office user interface most users are familiar with. The designing of forms is aimed at the Knowledge worker and after a little training is fairly easy to get to grips with. Controls may be dragged into position where validation and business rules may be applied in an intuitive manner. The form can connect to multiple data-sources but is most at home connecting to web services.

InfoPath is designed around the XML paradigm. Instances of the form are stored as XML files which makes post processing very easy. The form templates are stored in XSN format. This is a CAB format file which contains a mixture of XSL files (for each form page view) and XML to define the form business logic and data-sources.

Managed code may be added to the forms via installing the optional VSTA (Visual Studio Tools for Applications) module from the Office CD/ISO. Personally I consider this a last option when designing InfoPath forms preferring instead to put this logic into reusable web services wherever possible.

Conclusion
If you have never looked at using InfoPath then I hope this brief introduction may inspire you to check it out. I must however finish with a word of warning, as with any product please plan carefully before deploying InfoPath to the Enterprise (I will try and cover this in a future post).

Operation is not valid due to the current state of the object

When your perfectly good SharePoint web service or elevated delegate throws this error it could ruin your day. The cause of the error lies deep inside the SharePoint object model which uses the current SharePoint context assuming all is well with it. I have got around this issue in the past by temporarily wiping the HTTP context after which all is well:

   1:  HttpContext ctx = HttpContext.Current;
   2:  HttpContext.Current = null;
   3:   
   4:  try
   5:  {
   6:      // TODO:your code
   7:  }
   8:  finally
   9:  {
  10:      HttpContext.Current = ctx;
  11:  }

This has always worked for me although recently I spied another approach on Kristian Kjær blog which also works well; the choice is yours.

Permission to RIDE (part 2)

Last week I discussed how to clone permissions across site collections. Setting permissions is no good unless you apply them to a group or library, luckily performing this is fairly straightforward.

   1:  SyncUtils.PermissionGroupSetRole(web, "Super Member Group", "Blog Editor");

calling the routine below:

   1:  public Boolean PermissionGroupSetRole(SPWeb web, String groupName, String roleName)
   2:  {
   3:      Boolean groupSet = false;
   4:   
   5:      try
   6:      {
   7:          SPRoleDefinition role = PermissionRoleExists(web, roleName);
   8:          if (role == null) throw new ApplicationException("Role missing");
   9:   
  10:          foreach (SPRoleAssignment ra in web.RoleAssignments)
  11:              if (ra.Member.Name == groupName)
  12:              {
  13:                  ra.RoleDefinitionBindings.RemoveAll();
  14:                  ra.RoleDefinitionBindings.Add(role);
  15:                  ra.Update();
  16:                  groupSet = true;
  17:                  break;
  18:              }
  19:      }
  20:      catch (Exception ex)
  21:      {
  22:          logErr = String.Format("PermissionGroupSetRole: {0}", ex.ToString());
  23:      }
  24:   
  25:      return groupSet;
  26:  }

Monday 22 August 2011

Permission to RIDE

When working with solutions that contain many site collections managing security can be a bit of a pain. One technique that I like to use is to define all the permission roles within the root site collection and replicate these to the child site collections on creation (assuming you are creating it from a custom template).

Creating the permission within the root site collection.
The easiest way to define a new permission role is to copy an existing one via the UI; open the Contributor permission role and select the copy option to create your new permission role, let’s call it ‘Blog Editor’. For the new role choose the user permissions i.e. Read, Insert, Delete or Edit and save the role.

Cloning the permission role
To get the ‘Blog Editor’ permission role programmatically from the root site:

   1:  SPRoleDefinition role = web.RoleDefinitions['Blog Editor'];

Now let’s copy the role to the new site collection. I have chosen to elevate the permission to the application pool in the case below:

   1:  SPSecurity.RunWithElevatedPrivileges(delegate()
   2:  {
   3:      using (SPSite site = new SPSite(webUrl + "/" + siteUrl))
   4:      {
   5:          using (SPWeb web = site.OpenWeb())
   6:          {
   7:              web.AllowUnsafeUpdates = true;
   8:              PermissionRoleClone(web, role.Name, role.Description, role);
   9:          }
  10:      }
  11:  });

The clone permissions routine checks if the role already exists and then simply adds the copy from the root site with a new name and description:

   1:  public SPRoleDefinition PermissionRoleClone(SPWeb web, String roleName, String roleDescription, SPRoleDefinition sourceRole)
   2:  {
   3:      SPRoleDefinition newRole = null;
   4:   
   5:      try
   6:      {
   7:          newRole = PermissionRoleExists(web, roleName);
   8:   
   9:          if (newRole == null)
  10:          {
  11:              newRole = new SPRoleDefinition(sourceRole);
  12:              newRole.Name = roleName;
  13:              newRole.Description = roleDescription;
  14:              web.RoleDefinitions.Add(newRole);
  15:              web.Update();
  16:          }
  17:      }
  18:      catch (Exception ex)
  19:      {
  20:          logErr = String.Format("PermissionRoleClone:{0}",ex.ToString());
  21:      }
  22:   
  23:      return newRole;
  24:  }

To find if the role already exists within the target site collection:

   1:  public SPRoleDefinition PermissionRoleExists(SPWeb web, String roleName)
   2:  {
   3:      SPRoleDefinition matchRole = null;
   4:   
   5:      foreach (SPRoleDefinition role in web.RoleDefinitions)
   6:          if (role.Name == roleName)
   7:          {
   8:              matchRole = role;
   9:              break;
  10:          }
  11:   
  12:      return matchRole;
  13:  }

Now the permission role can be assigned to your site security groups, libraries and lists, I will cover this in part 2 of this post.