Saturday, August 15, 2009

Preparing for SharePoint 2010

I recently installed Windows 7 on my new laptop that I got for work. The ultimate goal is I want a machine where I will be able to run SharePoint 2010 to do local development. The core requirements that everyone has been hearing about for SharePoint 2010 is:

  • 64 bit
  • Server 2008
  • 8GB RAM minimum

These requirements are going to be pretty taxing. A lot of the mid level companies have been able to install SharePoint 2007 and do some effective solutions. They were able to upgrade using their SharePoint 2003 environment or similar infrastructure which they already had. Many times clients have tons of performance problems even with SharePoint 2007 because they did not have sufficient hardware provisioned but that is beside the point. Thinking about it a little deeper, this probably should not be too big of deal given that many organizations have server virtualization and hardware itself continues to drop in price. So getting to this requirement is possible. I am looking forward to finding out why the server requirements changed.

However who this hurts the most are the developers. All Microsoft consultants that I know, that work with SharePoint, use localized virtual environments. This is going to hurt our ability to develop in remote environments significantly. We need to be able to do localized development and then build solution packages which we deploy into integration, quality and production environments.

Luckily I was told that my new laptop can have an additional 4GB added getting me up to 8GB. So my solution will be to add more RAM, Server 2008 virtual machine and set it up as a dual boot since I am running Windows 2007 64 bit as my host operating system. Still this is just going to be a really tough thing for most of us to get around.

Friday, August 14, 2009

K2 blackpearl 483 Patch

K2 has released an important patch build based on their latest build which supports Windows Server 2008 and SQL 2008. This is build 483. In this case, build 483 can be installed on top of either a 4.8210.2.X or 4.8210.3.X.

It is important you get this installed and it should be the last one of these for a little. This was put out because these there were some immediate issued discovered.

Here is the upgrade path.

  • If you have a clean machine with nothing on it and install K2 for the first time. Install 4.8210.3.0. Then install 4.8210.X.483.
  • If you have a machine that has Windows Server 2008. Install 4.8210.3.0. Then install 4.8210.X.483.
  • If you have a machine with 4.8210.2.450. Just install 4.8210.X.483.
  • If you have a machine with 4.8210.2.X, prior to the 4.8210.2.450 build. Install 4.8210.2.450. Then install 4.8210.X.483.
  • If you have a K2 machine prior to 4.8210.2.X (i.e. RTM, SP1, 0803). Install 4.8210.3.0. Then install 4.8210.X.483.

The following are the resolved issues that have been rolled into this build.

Friday, August 7, 2009

K2 blackpearl supports Windows Server and SQL Server 2008

Windows Server 2008 and SQL Server 2008 Supported

K2 blackpearl 4.8210.3.0 has now been released. The importance of this release is that Windows Server 2008 and SQL Server 2008 is now officially supported!!!

Here is a link to see other new features and functionality of this release - http://kb.k2workflow.com/ArticleAttach/K2%20blackpearl%200807%20Feature%20and%20Functionality%20Changes.pdf.

Specifically some notice changes for 4.8210.3.0 are:

  • Out of Office has been cleaned up.
  • No more InfoPath Temporary files. What used to happen is when you click on a worklist item that is for an InfoPath client event, it would generate an InfoPath form in the form library. If the user closed the InfoPath without taking action, the form would remain in the form library. Otherwise, the temporary InfoPath form would be deleted by in the succeeding rules of the activity where the InfoPath client resides. Apparently they did this to support the Out of Office functionality.
  • Improvements for team development with TFS.
  • Debugging issues have been resolved.
  • String Tables and Environments been updated for K2.net 2003 migrations.
  • Some performance improvements for Worklist web part.
  • Plus a tons of other things discussed in the release notes…

Visual Studio 2008 is not supported just yet. I know it had been targeted for this release however it should be out soon.

There are two installers for this release. Basically there is:

  • 4.8210.3.0 – Which will support the installation of K2 blackpearl on Windows Server 2008.
  • 4.8210.2.450 – Is a release to upgrade existing 2.8210.2.X installations.

Both 4.8210.3.0 and 4.8210.2.450 are really the same from a bit perspective. You can only install 4.8210.3.0 on a machine if no K2 is installed or if the machine has K2 blackpearl version prior to 4.8210.2.X.

Both 4.8210.3.0 and 4.8210.2.450 support running on SQL Server 2008.

This past week I upgraded a client to 4.8210.2.450 and it went pretty smooth. They also had MOSS on Server 2008 in the farm but their SharePoint and SQL machines were on Server 2003. We were able to install of their Server 2003 machines to 4.8210.2.450 and then installed 4.8210.3.0 on the MOSS machine which had Sever 2008. We did not get time to fully test it but a configuration like that should work.

Release Issues

IMPORTANT - build 483 was released

Thursday, July 23, 2009

K2 Roles

Introduction to K2 Roles

K2 Roles are a way to create re-usable groups of users that can be used across processes. For instance you could create a K2 Role called Accounting Managers and that K2 Role can be used in a K2 Destination Rule. They are similar to an AD Group or a SharePoint Group but a little different. One added advantage of using K2 Roles will be kept in sync with tasks created for users to action. So what does that mean? Basically when you do not use a K2 Role and assign a specific user account to a destination rule that account will tied to the slot that is created at run time. Once the slot is created for that destination user it cannot be changed unless the user or administrator delegates the task. However if the you use a K2 Role, users that are in of the Accounting Managers K2 Role, will have immediate access to the worklist item slot (based on the refresh interval). So this is good thing to use if you anticipate that users who can potentially be assigned a task may change often.

I highly recommend reading this whitepaper - http://k2underground.com/files/folders/technical_product_documents/entry20948.aspx. It explains what is a K2 Role in detail.

Here are some of my notes on K2 Roles:

  • Destination Rules are required to compile a client side event. They can be set to Static user: user dynamically, AD Group, XML list, K2 Role, SmartObject, etc.
  • K2 Roles are a role is a common group that is defined within K2 that can be re-used across K2 processes. K2 Roles can be made of from accounts in AD or a custom repository like in SmartObject.
  • Slots determine how many Worklist items can be Open for an Activity. As soon as a user clicks on a Worklist item, the status immediately changes from Available to Open and 1 Activity Slot is occupied. The number of Slots can be limited to a specific number or a slot can be created for each destination. Slots control how users will work with data. Configuration of the destination rules directly determine how many slots are created.
  • Succeeding rules by default will evaluate the outcomes of actions along with the Slots that are created to determine if the Activity is allowed to go to the next Activity in the process.
  • By default all destination rules are set to "plan just once". A slot will be created for each user and a Worklist items is created however only one activity instance is created. Any time a user is added to a K2 Role it should appear on their worklist based on interval.
  • Plan per Destination supports parallel processing as multiple activity instances will be created for each user. "All at once" allows all users to access the worklist item. One at a time" only allows one user at a time to access the item.
  • Plan per Slot use for an IPC event or call out to an external system.
  • Cached K2 Roles - By default, a single slot will be created for each Role. By default, on a 10 minute interval, the Role and its users will be refreshed with that slot. This can be configured in each K2 process that is deployed by using the K2 Workspace. If you select, "Resolve all roles and groups to users", changes to the K2 role will not be reflected but using the "Keep roles synchronized" checkbox will keep in sync on interval.
  • Dynamic Roles can only be used with "Plan just once" or "Plan per destination" where Roles do not resolve to users. Dynamic roles are on-demand. This means the K2 Role is refreshed when dynamic roles are defined and every time worklists are opened which contain items that use the role. This ensures that new users in a K2 Role will see the worklist item immediately and users removed from K2 Role will have permission blocked.

Getting User who Actioned

When using K2 Roles I have run into situations that have tripped me up a couple times. Let's say I have a client side event (InfoPath) and I want to perform custom code after the InfoPath event. Specifically, I need to know who was the user who actioned the event. To do this you need to execute the following code:

public static string GetActionUser(ActivityInstance activityInstance) {
//Loop over the activity slots to see who was the user who
//actioned the worklist item.
foreach (Slot slot in K2.ActivityInstanceDestionation.ActivityInstance.WorklistSlots) {
if (slot.Status == ActInstSlotStatus.Completed) {
return slot.User.Name;
}
}
return "";
}

What this does is loop over the slots, checks which slot was completed and by whom. You cannot go directly to the ActivityInstanceDestionation because the K2 Role was assigned as the destination user. However slots will be created dynamically for each user in the K2 Role based on the refresh interval.

Email All users in K2 Role

In many situations, I have needed to email all of the users in a K2 Role. One solution to do this without having to write any custom code would be to go to the advanced destination rules of an activity where an Email Event has been added. Select Plan per Destination All at Once. Then select Resolve All Roles to users. Then in the Email Event select send the email to the Destination User checkbox. I would only recommend doing this in an Email Event that is in its own Activity. Do not do this in the same activity where you have a client side event, like an InfoPath event. What this will do is not allow the K2 Role to be dynamic refreshed defeating the purpose of all the stuff we just talked about.

Another approach would be to use the following code to build a string of email addresses that are in the K2 Role. Then set the email string into an activity level field. Then use activity level field in the Email Event wizard. You can see in the code I have an AD SmartObject with a method called GetDetails that I use to get the user's email address.


using SourceCode.Security.UserRoleManager.Management;
using SourceCode.SmartObjects.Client;
public static string GetEmailsInRole(string conn, string roleName){
string emailAddress = "";
conn = conn.Replace(" ", "");
UserRoleManager roleManager = null;
SmartObjectClientServer server = null;

try {
//Create Manager
roleManager = new UserRoleManager();
roleManager.CreateConnection();
roleManager.Connection.Open(conn);

//Get Role
Role role = roleManager.GetRole(roleName);

//SmartObject server reference
server = new SmartObjectClientServer();
server.CreateConnection();
server.Connection.Open(conn);

//Get Person Definition
SmartObject person = server.GetSmartObject("Person");
person.MethodToExecute = "GetDetails";

foreach (RoleItem item in role.Include) {
//Now get the email from the smartobject
person.Properties["ADID"].Value = item.Name.Replace("K2:", "");
server.ExecuteScalar(person);

emailAddress += person.Properties["Email"].Value +";";
}

//remove last semi-colon
emailAddress = emailAddress.Substring(0, emailAddress.Length - 1);
}
catch (Exception ex) {
}
Finally {
if (roleManager.Connection != null) {
roleManager.Connection.Close();
}

if (server.Connection != null) {
server.Connection.Close();
}
}

return emailAddress;
}
}

Wednesday, July 1, 2009

K2 Process Deployment Dependencies

There have been some recent questions to me about K2 process deployment dependencies. I wrote the chapter in the book which focused really on how to deploy a K2 process or SmartObject from one environment to another. It discussed the relationship between environments and the StringTable, MSBuild and deployment dependencies you need to consider. However there are some elements to a K2 process deployment that you still must consider which can be taken for granted.

Remember that most everything you configure in the K2 Workspace must be re-configured in your destination environment. Let me clarify this:

  • K2 Roles – Roles within K2 are created on the K2 Workspace, they are not defined as part of the K2 process. The K2 process will reference them; and if they are not there, you will get a deployment error when deploying from one environment to another. There is a K2 blackmarket projects that can help with this - http://www.k2underground.com/k2/ProjectHome.aspx?ProjectID=57 and http://www.k2underground.com/k2/ProjectHome.aspx?ProjectID=107
  • Environments – This is a tricky one to explain and recommend that you read the book. When doing a process K2 process, values in the destination Environment will set into the StringTable. So the K2 Development server will have values in the Environments and when a process is deployed to a K2 Production server the StringTable will be populated. However the K2 Production Server will not have values populated its Environment Settings in the K2 Workspace. Environment Settings are unique to the server. This can be a challenge if developers have localized development environments and they need to share kprx files. The developer will need to create the Environment settings for their localized environment.
  • Working Hours – Will again need to be reconfigured in each environment manually as they are not part of the process definition; they are just referenced.
  • Permission (Server and Process) – It is obvious that K2 server permissions will need to be reconfigured on each server. However remember that the Process permissions will again need to be re-configured on each sever the process is deployed to. It is not part of the process definition.
  • Error Profiles – Those will need to be reconfigured on each K2 server. You may be creating profiles by process definition.
  • SmartObject Services – This is discussed in the book but worth mentioning again. SmartObject Services like the SmartBox and AD are deployed in every K2 server as part of the install. However other custom SmartObject services are not and this can cause a wrinkle in your deployment. In the K2 book, there is a section devoted to GUID in a SmartObject (Pages 323 to 325). This is a must read. Here are some K2 blackmarket projects to help with this - http://www.k2underground.com/k2/ProjectHome.aspx?ProjectID=71 and http://www.k2underground.com/k2/ProjectHome.aspx?ProjectID=25

You still also need to consider all other applications and components that must be deployed before you deploy your K2 process. For instance:

  • SQL Databases
  • Web Services
  • SharePoint Lists, Document Libraries, Form Libraries
  • Content Types
  • Custom Site Templates
  • Custom SharePoint Features
  • Custom Web Parts
  • ASP.net pages
  • SharePoint Sites and Pages
  • Etc.

The list can go on. So when doing a deployment, you really need to map out all dependencies of the entire solution and ensure that you deploy everything in the right order.

K2 User Group July 2009

There will be a cool User Group this month on K2 and doing custom reporting with SSRS and PerformancePoint – looking forward to it.


------------------------

Hello Everyone,

Phillip Knight from Merit Energy will be hosting the K2 user group meetings at Merit Energy, located at 13727 Noel Road, 2nd Floor Conference room, Tower 2, Dallas, Texas 75240. Parking information is included in the linked map below. Remote attendance information is included at the bottom of this message.

Link to map: http://www.meritenergy.com/content/MeritMap.pdf. Reminder: Merit Energy is on the 5th floor, but the meeting will be held in a 2nd floor conference room. Once off the elevator, go to the reception area and we will bring you back to the conference room.

Please RSVP to me via email
whether you are attending via live meeting or if you will be attending in person (so that we can plan for the number of people to order food for).

Check out the K2 Underground site and our user group at http://k2underground.com/k2/InterestGroupHome.aspx?IntGroupID=11. We are posting webexes/live meetings from our meetings at this site.

08/11/2009 11am – 1pm
09/8/2009 11am – 1pm
10/13/2009 11am – 1pm
11/10/2009 11am – 1pm
12/8/2009 11am – 1pm

Meeting Agenda:
11-11:15 Networking/Refreshments
11:15-11:30 Announcements/Intros of New people
11:30-11:45 Tips & Tricks
11:45-12:45 Technical Presentation
12:45-1:00 Meeting Wrapup

The Announcements section of the meeting will include any information regarding K2 upcoming events and user group events as well as brief introductions of our presenter and refreshment provider.

The Tips & Tricks Presentation is when we as members can pose questions to each other on projects that we are working on and having difficulty with. It is also a time when if we have learned something that we feel will be helpful to others, we can share it with the group. Bring yours to share/ask.

Meeting Presentation & Company & Sponsor:

Jonathan King will be presenting an array of ideas on how to approach custom reporting in both K2 blackpearl and K2 blackpoint. He will be demonstrating a number of custom reports developed using SSRS upon both standard K2 process information and SmartObject information as well as how to develop Process Maps in Microsoft PerformancePoint.

K2 blackpoint, a subset of K2 blackpearl features, provides unparalleled capabilities and affordability. It also offers an upgrade path so that organizations can grow their investment and add complexity over time, if needed.

For more information, go to http://www.blackpoint.k2.com.

The K2 platform is for delivering process-driven applications that improve business efficiency. Visual tools make it easy for anyone to assemble reusable objects into applications that use workflow and line-of-business information.

K2-based solutions are deployed by a growing number of the global Fortune 100. K2 is a division of SourceCode Technology Holdings, Inc. based in Redmond, Washington, and has offices all over the world.

For more information, contact Joe Bocardo at joeb@k2.com.

Meeting Presenter:

Jonathan King is the K2 Technical Specialist for Europe and is responsible for promoting the K2 suite of products with prospects, customer, partners and the broader K2 community. Jonathan has been working with K2 products for the past five years the last three of which have been directly for K2 out of their European head office in London. Jonathan is available at jonno@k2.com.

For Virtual Attendees:

Note: please keep your phone on mute until you are ready to speak.

Audio Information

Telephone conferencing
Choose one of the following:

Start Live Meeting client, and then in Voice & Video pane under Join Audio options, click Call Me. The conferencing service will call you at the number you specify. (Recommended)

Use the information below to connect:
Toll: +1 (719) 867-1571

Toll-free: +1 (877) 860-3058

Participant code: 914421

First Time Users:

To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:

Copy this address and paste it into your web browser:

1. Copy this address and paste it into your web browser:
https://www.livemeeting.com/cc/scna/join?id=KRQ226&role=attend

2. Or Copy and paste the required information:

Location: https://www.livemeeting.com/cc/scna1

Meeting ID: KRQ226

Entry Code: NO Entry code for attendees

If you would like to provide refreshments at an upcoming meeting or present at an upcoming meeting, please contact me.

Let me know if you have any questions prior to the meeting.

The next meeting announcement will be sent out next Tuesday.

Thanks,

Have a great day!

Patti Albracht

Wednesday, June 3, 2009

Deploy Web Part as Feature with CAS

Introduction


I had started writing this blog over a year and half ago but I had hirer priority things come up. I still find that a lot SharePoint developers have challenges understanding how to deploy web parts. Specifically CAS, GAC vs bin, rely on CodePlex tools, etc. are a common issue.

As a SharePoint consultant I have seen many struggle with web parts. The issue is not usually with the development of a web parts. There are lots of blogs and books written that show how to develop web parts but the biggest issue I have seen is correctly deploying of web parts. More specifically:

  • Creating web part deployment solutions
  • Deploying web parts as a feature
  • Deploying the web parts in a secure fashion

With Visual Studio 2005, there was a plug-in that developers used to quickly deploy web parts out to a SharePoint environment however there was no control over the deployment package or the deployment process. This plug-in was great for development environments because it allowed developers to quickly deploy and iteratively debug web parts however developers would continue to use this deployment for production deployments. This caused many issues with the control, configuration and change management issues down the road.


With Visual Studio 2008, there is better tooling has been incorporated into Visual Studio by Microsoft for the creation of SharePoint web part projects.


Other tools have been created to help with the authoring WSP deployment files such as WSP Builder. This tool works pretty well but knowing how a WSP solution file is created is equally important. What I have seen is that developers become so dependent on tools such as these, they do not have an understanding of how web parts actually work.

Still the biggest issue we see with deployment is developers run into challenges with deployments of their web parts and they quickly do the following:


  • They raise the trust level on their SharePoint environments to either Medium or Full.
  • They deploy the web part DLL directly to the GAC.

Both are unacceptable solutions especially when this is a production environment (Intranet or not). What makes this worse is many forums, blogs, etc. usually state to do as such and do not outline the consequences. As well, I have not seen any truly good end to end discussions of this topic.


In this blog I will take a deep dive into how a web part should be properly deployed. The web part that will be developed will be inconsequential ("Hello World" example) because the focus will be on deployment. I will specifically focus on:


  • Deploying a web part as a Feature.
  • Deploying to web bin directory.
  • Code Access Security (CAS).

A lot of this information will become moot because we are expecting the next release of Visual Studio to fix a lot of these gaps and provide all the tooling to build SharePoint deployment packages end-to-end.


The first part of this blog is going to discuss how to create a web part feature and properly deploy it. The interesting stuff about properly setting up CAS will later on. However I believe it is important to understand the entire picture before we jump into CAS with web parts.


Creating a Web Part Project


In this first project I am going to create a basic web part project using no accelerator tools.


  • Create a C# code library project which I named WSSDistillery.Deploy.WebPart.
  • Add a references to Microsoft.SharePoint and System.Web.
  • In the AssemblyInfo.cs you will need to add [assembly: System.Security.AllowPartiallyTrustedCallers]. This will allow SharePoint to call the web part contained within dll.
  • Go into the properties of the project and sign the assembly.
  • Renamed Class1.cs to something else. I renamed it to SimplePart.cs.
  • Add an XML file called manifest.xml.
  • Add a file called WSP.ddf.
  • Add the following three folders. First "TEMPLATE", then beneath it "FEATURES", then beneath it "WSSDistillery.Deploy.WebPart".
  • Under the "WSSDistillery.Deploy.WebPart" folder add the following files elements.xml, Feature.xml and WSSDistillery.Deploy.WebPart.SimplePart.webpart.

It is pretty simple to throw together even without all of these tools out there. The final solution should look like:






I will go into further detail about each file and what goes into them. Some initial notes are:


  • It is common practice to create a hierarchy of folders in the Visual Studio project based on the folder hierarchy of files in the 12 Hive (\\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES).
  • I named the folder "WSSDistillery.Deploy.WebPart" because this is the folder that will be deployed into SharePoint. I put the namespace into the name of the folder to lower the chances of a name conflict for other SharePoint Features that may be created over time.
  • Even though the assembly has been signed, it will not be deployed to the GAC.

Creating the Web Part


I mentioned before, this will not be a lesson on how to develop a web part. As such, this web part is going to be a simple implementation; Hello World for now. I will add some code later which will require it to have a CAS policy.

public class SimplePart : System.Web.UI.WebControls.WebParts.WebPart
{
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);

writer.WriteLine("Hello World");
}

}

Get DLL Strong Name


Might as well go ahead and get this now, because this will be needed in several places. Open the Visual Studio command prompt and run the following command:


  • Sn –Tp [path]\[dll name]
  • sn -Tp "C:\WSSDistillery\Deploy\WSSDistillery.Deploy\WSSDistillery.Deploy.WebPart\bin\Debug\WSSDistillery.Deploy.WebPart.dll"

Two values will be generated. The first is a Public Key which is really long, go ahead and get that. The second is a Public Key Token which will be used in several places. These will be used in some of the files that will be created next.


Webpart File


I know "WSSDistillery.Deploy.WebPart.SimplePart.webpart" is a long filename. Again, it is good practice to have the namespace in the name of the file to ensure there are no name conflicts down the line during your web part deployments. This file will be deployed into the Web Part Gallery within a site collection. This file has a reference to the DLL that has the web part code. As well, the Data XML elements contain the text that a user will see when adding a to a web part page within SharePoint. A good description here of what the web part is required for the users of SharePoint.

<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="WSSDistillery.Deploy.WebPart.SimplePart, WSSDistillery.Deploy.WebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=aa9a1a08fbf22452" />
<importErrorMessage>Cannot import WSSDistillery.Deploy.WebPart.SimplePart</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Simple Web Part</property>
<property name="Description" type="string">This is a very simple web part for demonstrating deployments.</property>
</properties>
</data>
</webPart>
</webParts>

elements.xml File


This file will be responsible for deploying the WSSDistillery.Deploy.WebPart.SimplePart.webpart file to the Web Part gallery in the site collection.

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="WebParts" List="113" Url="_catalogs/wp">
<File Url="WSSDistillery.Deploy.WebPart.SimplePart.webpart" Type="GhostableInLibrary" />
</Module>
</Elements>

Feature.xml File


This is a standard SharePoint Feature file. There are references to both elements.xml and WSSDistillery.Deploy.WebPart.SimplePart.webpart files ion the ElementManifests.

<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="8CD4DE2E-353E-40e1-A2AB-8004F6E8AA5F"
Title="Simple Web Part"
Description="This is a very simple web part for demonstrating deployments."
Version="1.0.0.0"
Scope="Site"
Hidden="FALSE"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml" />
<ElementFile Location="WSSDistillery.Deploy.WebPart.SimplePart.webpart"/>
</ElementManifests>
</Feature>

manifest.xml File


This file contains the instructions that will be used by SharePoint to deploy the solution across the SharePoint farm. First, the FeatureManifest element has the location for where the Feature.xml file is. You can deploy many SharePoint Features using a single deployment package; in this example we are only deploying one.


Second the Assemblies element controls where the dll with the web part will be deployed. Notice the DeploymentTarget attribute is set to WebApplication. When this web part is deployed, SharePoint will create a folder called "WSSDistillery.Deploy.WebPart" on every web front end (WFE) web server. This folder will be created within the bin directory of IIS for the SharePoint web application. Within that new folder will be the WSSDistillery.Deploy.WebPart.dll file. The result it the dll is now deployed to the "bin" directory instead of the GAC. For many reason this is the most secure methodology for deploying a web part. Most notably dll will only be accessible to the SharePoint web site and not other applications can use it.

Finally the SafeControls element contains instructions that will modify the web.config file of the SharePoint web application. Specifically it will add the web part as a safe control so that it can be used within SharePoint.

<Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="052C7D59-7DCF-4782-93B4-51C3F6DECF3B">
<FeatureManifests>
<FeatureManifest Location="WSSDistillery.Deploy.WebPart\Feature.xml"/>
</FeatureManifests>
<Assemblies>
<Assembly Location="WSSDistillery.Deploy.WebPart\WSSDistillery.Deploy.WebPart.dll" DeploymentTarget="WebApplication" >
<SafeControls>
<SafeControl Assembly="WSSDistillery.Deploy.WebPart.SimplePart, WSSDistillery.Deploy.WebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=aa9a1a08fbf22452"
Namespace="WSSDistillery.Deploy.WebPart"
Safe="True"
TypeName="*"/>
</SafeControls>
</Assembly>
</Assemblies>
</Solution>

WSP.ddf File


Last file to be created is the ddf file. It is really not that hard to get the hang of:

  • Create a name for the *.wsp file that will be created.
  • Create a destination for the where the file will be created.
  • Get the manifest.xml file.
  • Create a folder within the wsp called WSSDistillery.Deploy.WebPart. Special note, this folder must correspond to the paths to the assembly and feature files that were created within the manifest.xml.
  • Reference the dll, elements.xml, Feature.xml and WSSDistillery.Deploy.WebPart.SimplePart.webpart files.
.OPTION Explicit
.Set CabinetNameTemplate="WSSDistillery.Deploy.WebPart.wsp"
.Set DiskDirectory1="C:\WSSDistillery\Deploy\WSSDistillery.Deploy"

manifest.xml

.Set DestinationDir="WSSDistillery.Deploy.WebPart"

%outputDir%WSSDistillery.Deploy.WebPart.dll
TEMPLATE\FEATURES\WSSDistillery.Deploy.WebPart\elements.xml
TEMPLATE\FEATURES\WSSDistillery.Deploy.WebPart\Feature.xml
TEMPLATE\FEATURES\WSSDistillery.Deploy.WebPart\WSSDistillery.Deploy.WebPart.SimplePart.webpart

.Delete outputDir
To create the WSP file, go the project properties and add the following commands to the Post Build Events.

cd $(ProjectDir)
MakeCAB /D outputDir=$(OutDir) /f "WSP.ddf"

Now build the project and the WSSDistillery.Deploy.WebPart.wsp should be created in the C:\WSSDistillery\Deploy\WSSDistillery.Deploy folder.


Deploying the Web Part Files


The great thing about creating a WSP file is that you can now use the stsadm command line to deploy your SharePoint Feature. In this case, my Feature is a web part. I personally believe that if you cannot deploy a complete solution using a SharePoint Feature, you should reconsider your deployment approach. Deployment into your production environments should be a controlled, repeatable and automated.

The following commands need to be run to deploy the solution to SharePoint.


stsadm.exe -o addsolution -filename C:\WSSDistillery\Deploy\WSSDistillery.Deploy\WSSDistillery.Deploy.WebPart.wsp


stsadm.exe -o deploysolution -name WSSDistillery.Deploy.WebPart.wsp -url http://mossserver:28921 -immediate -force

stsadm.exe -o execadmsvcjobs

Note that the URL to the web application is specified in the deploysolution command. The is necessary because the Feature.xml is a scope of Site.


As a result running these commands the following changes occurred:

  • In C:\Inetpub\wwwroot\wss\VirtualDirectories\XXXX\bin\ a folder called WSSDistillery.Deploy.WebPart will be created and the WSSDistillery.Deploy.WebPart.dll has been deployed there.
  • In C:\Inetpub\wwwroot\wss\VirtualDirectories\XXXX\ web.config the WSSDistillery.Deploy.WebPart entry has been added to the SafeControls tag.
  • In C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES and new folder called WSSDistillery.Deploy.WebPart was created and elements.xml, Feature.xml and WSSDistillery.Deploy.WebPart.SimplePart.webpart will be in that folder.

I point this out because it is important to know all the changes that have occurred to your SharePoint environment based on the WSP solution deployment. As well, you will need to verify your deployment to ensure that everything was put in the right place – especially if this is a production deployment.

Activating the Web Part Feature


The next step is we need to activate the Feature with the following commands:

stsadm.exe -o installfeature -filename WSSDistillery.Deploy.WebPart\Feature.xml -force

stsadm.exe -o activatefeature -filename WSSDistillery.Deploy.WebPart\Feature.xml -url http://mossserver:28921 –force


The results are:

  • If you go to http://mossserver:28921/_layouts/ManageFeatures.aspx?Scope=Site in the Site Collection Features you will see the "Simple Web Part" Feature activated.
  • If you go to http://mossserver:28921/_catalogs/wp/Forms/AllItems.aspx you will see the WSSDistillery.Deploy.WebPart.SimplePart.webpart in the Web Part Gallery.
  • You will find the web part in the Miscellaneous group when adding the Simple Web Part to a web part page.

That is it! I know it seems like a lot – but it is really important that you know how all this is working under the hood regardless of what accelerator tool is being used to deploy your web part.


SharePoint and CAS Background


Before diving into how to configure a web part to work with CAS, let us get an understanding of how it works within SharePoint. I will try to make this as simple as can be. By default, whenever a new web application is created within SharePoint, if you go to the web.config you will find the following tag:

<trust level=" WSS_Minimal" originUrl="" />

This basically means that your SharePoint site is running under minimal trust. If you ever come to a SharePoint site that is not running minimal or WSS_Custom (I will explain shortly) there should be major concerns. If for any reason this has been switched to FULL – this would be cause for alarm and not acceptable for any reason. Most SharePoint solutions can be deployed under minimal trust.

In the web.config file, there are elements called trustLevel. By default there will be WSS_Medium and WSS_Minimal. The policyFile attribute shows where this policy file resides within the 12 hive. Let us look at the WSS_Minimal in \\12\config\wss_minimaltrust.config. Please note that these files should not be change for any reason!!!


In the WSS_Minimal you will see that the following libraries are trusted:


  • System.Security.Policy.AllMembershipCondition
  • System.Web.AspNetHostingPermission
  • System.Security.Policy.FirstMatchCodeGroup
  • System.Security.NamedPermissionSet
  • System.Security.Permissions.SecurityPermission
  • System.Security.Policy.StrongNameMembershipCondition
  • System.Security.Policy.UnionCodeGroup
  • System.Security.Policy.UrlMembershipCondition
  • Microsoft.SharePoint.Security.WebPartPermission
  • System.Security.Policy.ZoneMembershipCondition

The first thing you will notice is that you do not have permissions to the SharePoint itself, basically you cannot open something like a SPWeb object with these permission levels. All you basically have permissions to do is some basic .NET code and you cannot do anything integrated with SharePoint, databases, the file system, etc.


Now let us look at the WSS_Medium file. In addition to the ones above, the following have been included:

  • System.Net.DnsPermission
  • System.Security.Permissions.EnvironmentPermission
  • System.Security.Permissions.FileIOPermission
  • System.Security.Permissions.IsolatedStorageFilePermission
  • System.Drawing.Printing.PrintingPermission
  • Microsoft.SharePoint.Security.SharePointPermission
  • System.Net.Mail.SmtpPermission
  • System.Data.SqlClient.SqlClientPermission
  • System.Security.Permissions.UIPermission
  • System.Net.WebPermission

As you can see running under medium level trust now you have the ability to run SharePoint calls but it opened up several other things like FileIO, Smtp and SQL. Now many might think that is harmless to change the permission level to Medium but think about that for a moment. What this basically means is if you change the web.config file from minimal to medium just so you can run a SharePoint API command, you now open up all these things throughout the entire SharePoint web application. So now malicious code could be uploaded into your SharePoint site, and use the permissions levels to do harm or access resources that they should not have access to!!!


This is unacceptable when there is the ability within SharePoint to be granular. I have seen too many people say, change the permission level to Medium. The real solution is to use CAS policies within your maninfest.xml give your web part the proper permissions to execute code. In the manifest.xml file you have the ability to create CAS policies that specific to the web part dll only. If the web part only needs to have access to the SharePoint API, we can create a policy stating that WSSDistillery.Deploy.WebPart.dll can only run Microsoft.SharePoint.Security.SharePointPermission and nothing else. This is highly secure and ensures that no other resources are inadvertently opened.

Modify Simple Web Part


Now let us modify the web part to use an object for which it does not have permission to when running under minimal trust. In this case, lets change the Simple Web Part to reference SPContext.Current.Web. In the code below, I simply want to modify the web part to show a list of sub sites below the current site.

public class SimplePart : System.Web.UI.WebControls.WebParts.WebPart
{
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);

try
{
StringBuilder webUrls = new StringBuilder();

using (SPWeb currentWeb = SPContext.Current.Web)
{
foreach (SPWeb web in currentWeb.Webs)
{
webUrls.AppendFormat("<a href=\"{0}\">{1}</a><br>", web.Url, web.Title);
web.Dispose();
}
}

writer.WriteLine(webUrls.ToString());
}
catch (Exception ex)
{
writer.WriteLine(ex.Message);
}
}

}

If the code were to be redeployed as is, you will receive the following error.


The "SimplePart" Web Part appears to be causing a problem. Request for the permission of type 'Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' failed.


Many new SharePoint developers will see this as a harmless code and get frustrated that this has been locked down. Well this is because SharePoint wants to make sure that things are secure and controlled which is not a big deal; you must always account for security in your implementations.


In the next few steps I will give you a more detailed understanding of how CAS works and how your SharePoint environment will be changed as a result of adding the CAS instructions. In my opinion is very important to know how this works.


PermCalc Tool


There is a tool called PermCalc.exe which we will use to help us generate the CAS permissions. I had suggestion to try to use as a way to quickly figure out permissions for a web part. After playing with it for several hours and putting a lot of thought into it, I could not come up with a simple best practice on how to use this for the "everyday" developer.


I was able to get it to generate permission sets which will be discussed shortly, however it did not make things any easier. This is because if you do run this against your web part it will not give you any suggestions on how to add SharePointPermissions like what we had to do above. The only way was to decorate the class, constructor or methods with the following:


[SharePointPermission(SecurityAction.Demand, Unrestricted=true)]

Then if you run the PermCalc tool it would generate the correct IPermission.


So you pretty much have to anticipate the errors; which is not a bad thing either. Really, I think the approach I will explain below is easier and you do not need to add in these decorations to give your web parts these permissions to get them to work in a secure fashion.


Adding CAS

To resolve the issue we need to add CAS instructions to the deployment.

First let's go to the wss_minimaltrust.config file that is \\12\config\. You will see a PermissionSet named SPRestricted. Copy this into your manifest XML file.

<PermissionSet   class="NamedPermissionSet" version="1" Name="SPRestricted">
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="WebPartPermission" version="1" Connections="True" />
</PermissionSet>

Now all I need to do is add an IPermission for SharePoint. Next I opened the wss_mediumtrust.config in \\12\config\. In there under the SPRestricted you will find this

<IPermission class="SharePointPermission" version="1" ObjectModel="True" />

Now the class SharePointPermission is not part of the minimal trust file, so what you do is change this to be:

<IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" version="1" ObjectModel="True" />

All you need to do is scroll up to the SecurityClasses node within the wss_mediumtrust.config.


Done. You can do this for other things like SQL, IO, DNS, etc. permission.


This is how the final modified manifest.xml file will look like.

<Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="052C7D59-7DCF-4782-93B4-51C3F6DECF3B">
<FeatureManifests>
<FeatureManifest Location="WSSDistillery.Deploy.WebPart\Feature.xml"/>
</FeatureManifests>
<Assemblies>
<Assembly Location="WSSDistillery.Deploy.WebPart\WSSDistillery.Deploy.WebPart.dll" DeploymentTarget="WebApplication" >
<SafeControls>
<SafeControl Assembly="WSSDistillery.Deploy.WebPart.SimplePart, WSSDistillery.Deploy.WebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=aa9a1a08fbf22452"
Namespace="WSSDistillery.Deploy.WebPart"
Safe="True"
TypeName="*"/>
</SafeControls>
</Assembly>
</Assemblies>
<CodeAccessSecurity>
<PolicyItem>
<Assemblies>
<Assembly PublicKeyBlob="00240000048000009400000006020000002400005253413100040000010001
00ad51a9cdfbe7db0a0f6d16a257d874a19993707b1bb0e873bda1c18c5b1592e24070f57b637
e0be2b00790fd67bc3e0c61205af5c0e5753780f257acb2c0b4b4830e23ace37be05c7ab52478
2731f85786d7648e6e14a99a83dc474081d5cf5e1fc1b20da22fc3b5a94b44ad3903aa8f081cc
0508e71b5606927824114f2ecd1"
/>
</Assemblies>
<PermissionSet class="NamedPermissionSet" Name="WSSDistillery.Deploy.WebPart" version="1" Description="WSSDistillery.Deploy.WebPart">
<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="WebPartPermission" version="1" Connections="True" />
<IPermission version="1" class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" ObjectModel="True" />
</PermissionSet>
</PolicyItem>
</CodeAccessSecurity>
</Solution>

Notice the following changes:

  • A new CodeAccessSercurity node has been added.
  • Within it you see the new permission sets.
  • Noticed that I renamed the PermissionSet to match the name of my webpart dll.
  • As well, you see an assemblies node. Notice that I use the PublicKeyBlob which is a value I got from the sn command line earlier when generating a strong file name. Since I am deploying to the bin, this seems to be the only way I can the permissions to pick up. Every time I try to reference the DLL name it does not work.

Deployment of Web Part with CAS


We can deploy the web part in the same fashion as earlier however, add -allowCasPolicies switch to the stsadm.exe -o deploysolution command line, otherwise you will get an error during the deployment.


Affects of the CAS Deployment


Here is how your SharePoint environment changed as a result of this. Go to the web.config file for the SharePoint site. First you will see that the truest level has changed to WSS_Custom. You will that a new treustLevel node has as well been created called WSS_Custom. You will see that SharePoint took the WSS_Minimal file and then created a new file from it. When you go to this new file in the \\12\config\, you will see the permission set that was added to the manifest.xml file has been added here.

Why is this Important


This is all very important from a security perspective:

  • First the web part is deployed to the SharePoint meaning it is only accessible to SharePoint and is not in the GAC. Deploying to the GAC makes the library accessible to any application running on that server.
  • Second only the web part deployed has permissions to SharePoint resources. No other future web parts can tap into resources that is should not have access to. In this case, our custom web part has access to SharePoint Object model and nothing else.

Closing


Again, I know this may seem like a lot of work given all of the CodePlex tools but still having a fundamental understanding of how this all works under the hood is extremely important.


References