Friday, September 28, 2007

Cool Tool to publish your post: Windows Live Writer

I am now using this tool to publish my posts to Blogger. It's cool and you have lots of add-ins to use, such as "Insert code from visual studio", "Insert maps", etc.
Check out Windows Live Writer Beta 3

Thursday, September 27, 2007

Create and deploy a Web Part solution package

To create and deploy a solution package is never easy. I tried a whole day to figure it out the whole sucessful process and had to do a brunch of solution retraction. Now, I will try to put the whole process in details:

1. Create the web part derived from System.Web.UI.WebControls.WebParts.WebPart

Add Reference System.Web and Microsoft.SharePoint

using System;
using System.Collections.Generic;
using System.Text;
 
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
 
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
 
namespace CusLib
{
 public class CusViewer : System.Web.UI.WebControls.WebParts.WebPart
 {
 public CusViewer()
 {
 this.ExportMode = WebPartExportMode.All;
 }
 
 protected override void Render(HtmlTextWriter writer)
 {
 SPSite site= new SPSite("http://wcm.litwareinc.com");
 SPWeb web = site.OpenWeb();
 SPListCollection collection = web.Lists;
 foreach (SPList list in collection)
 { 
 writer.Write("<table>");
 writer.Write("<tr><td>List Name</td>");
 writer.Write("<td>" + list.Title+ " " + list.ID + "</td></tr>");
 writer.Write("</table>");
 }
 }
 }
}
 

2. Add the following line of code to the end of the AssemblyInfo.cs file to tell the .NET Framework that assemblies that aren't fully trusted can call & execute the Web Part assembly:

[assembly: System.Security.AllowPartiallyTrustedCallers()]

3. package.ddf: defines content and structure in the wsp (solution package) file

.OPTION Explicit
.Set DiskDirectoryTemplate=CDROM
.Set CompressionType=MSZIP
.Set UniqueFiles=Off
.Set Cabinet=On
.Set DiskDirectory1=Package
;**************************************************
manifest.xml

bin\debug\CusViewer.dll

.Set DestinationDir=CusViewerSolution
TEMPLATE\FEATURES\CusViewerSolution\feature.xml
TEMPLATE\FEATURES\CusViewerSolution\elements.xml
TEMPLATE\FEATURES\CusViewerSolution\cusWebPart.webpart

;***End

4. manifest.xml: Defines the list of features, site definitions, resource files, web part files, and assemblies to be included in the solution package. In this case, it defines the location of feature.xml and the safe control line which is going to be put in the web.config file.

<?xml version="1.0" encoding="utf-8" ?>
<Solution SolutionId="F174BCD9-F149-4583-859C-55DE086DD0D7" 
 xmlns="http://schemas.microsoft.com/sharepoint/">
 
 <FeatureManifests>
 <FeatureManifest Location="CusViewerSolution\feature.xml" />
 </FeatureManifests>
 
 <Assemblies>
 <Assembly DeploymentTarget="WebApplication" Location="CusViewer.dll">
 <SafeControls>
 <SafeControl Assembly="CusViewer" Namespace="CusLib" TypeName="*"/>
 </SafeControls>
 </Assembly>
 </Assemblies>
</Solution>
 

5. feature.xml: Defines feature details like the title, scope and the files that support this feature. In this case, the elements and web part definition file location.

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
 Id="490A5E8A-A639-4743-B5AA-D21B485E3C9F"
 Title="Custom Viewer"
 Hidden="FALSE"
 Scope="Site"
 Version="1.0.0.0">
 <ElementManifests>
 <ElementManifest Location="elements.xml" />
 <ElementFile Location="cusWebPart.webpart" />
 </ElementManifests>
</Feature>
 

6. elements.xml: Contains definitions to the feature's elements.

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
 <Module Url="_catalogs/wp" RootWebOnly="TRUE">
 <File Url="cusWebPart.webpart" Type="GhostableInLibrary">
 <Property Name="Group" Value="CusLib" />
 <Property Name="Title" Value="Cus View Web Part" />
 </File>
 </Module>
</Elements>

7. cusWebPart.webpart: web part definition. The 2nd parameter in type name is confusing. It should be the namespace from the source of the Internet. But I check the existing definitions in the web parts library, it uses the assembly name instead. The Title property is useless. SharePoint uses the Title defined in the elements.xml instead.

<?xml version="1.0" encoding="utf-8" ?>
<webParts>
 <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
 <metaData>
 <type name="CusLib.CusViewer, CusViewer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
 <importErrorMessage>Error importing the Web Part.</importErrorMessage>
 </metaData>
 <data>
 <properties>
 <property name="Title" type="string">Custom Viewer Web Part</property>
 </properties>
 </data>
 </webPart>
</webParts>

8. build.targets: Defines the makecab details which includes the location of ddf file and where to put the wsp file.

<?xml version="1.0" encoding="utf-8" ?>
<Project DefaultTargets="BuildSharePointPackage" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Target Name="BuildSharePointPackage">
 <Copy SourceFiles="$(TargetPath)" DestinationFolder="bin" ContinueOnError="false"/>
 <Exec Command="makecab.exe /F package.ddf /D CabinetNameTemplate=$(TargetName).wsp" />
 </Target>
</Project>

9. unload the project and edit the project property. Add the following code at the bottom. It tells the project the location of build.targets and which target to call.

 <Import Project="build.targets" />
 <Target Name="AfterBuild">
 <CallTarget Targets="BuildSharePointPackage" />
 </Target>
 

10. build the solution and you will find the CusViewer.wsp generated under Package folder

11. add the solution package to SharePoint:

stsadm -o addsolution -filename C:\DevProjects\CusViewer\CusViewer\Package\CusViewer.wsp

12. open SharePoint 3.0 Central Administration. goto Central Administration > Operations > Solution Management to deploy the solution.

13. open the portal you want to use this web part. click Site Actions > Site Settings > Modify All Site Settings > Site Collection Features. Activate the web part solution with the Title defined in the feature.xml

14. edit a page and add the web part with the group and title defined in the elements.xml

15. if for somehow the web part solution package is not working properly and you want to redeploy it, you will need to do the following:

  • delete the web part in the web parts library
  • deactivate the feature in features library
  • detract the solution in central administration
  • remove the solution
  • follow the steps starting from #10

16. If you want to places the files in the file system other than in the DB, you will need to define it in the package.ddf file and remove them from feature.xml and elements.xml.

Reference:
  Development Tools and Techniques for Working with Code in Windows SharePoint Services 3.0
  Creating a Solution Package in Windows SharePoint Services 3.0
  Anatomy of a SharePoint WSS v3 Feature Project in Visual Studio 2005

Tuesday, September 25, 2007

Create a custom policy file

Copied from MOSS 2007 and Code Access Security

The Microsoft one is pretty outdated: Microsoft Windows SharePoint Services and Code Access Security

1. Go to the following location on the server:

LocalDrive:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG

2. Make a copy of wss_minimaltrust.config and rename it wss_customtrust.config.
3. Open wss_customtrust.config file using any text editor.
4. Under the <SecurityClasses> element, add a reference to the SharePointPermissions class as follows:

<SecurityClass Name="SharePointPermission" Description="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c." />

5. Search for the <PermissionSet> tag where the name attribute equals ASP.NET. If you couldn't find that <PermissionSet> tag, locate the one that has SPRestricted in the name attribute.
6. Copy the entire tag and all of its children, and paste a copy of it immediately below the one you copied.
7. Change the name of the PermissionSet element from ASP.NET (or SPRestricted) to CustomTrust.

Before:

<PermissionSet class="NamedPermissionSet" version="1" Name="SPRestricted">

After:

<PermissionSet class="NamedPermissionSet" version="1" Name="CustomTrust">

8. Add the following <IPermission> node to the <PermissionSet> element where the name attribute equals CustomTrust:

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

Therefore, the resulting customized <PermissionSet> will look as follows:

<PermissionSet class="NamedPermissionSet" version="1" Name="CustomTrust">

<IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />

<IPermission class="SecurityPermission" version="1" Flags="Execution" />

<IPermission class="WebPartPermission" version="1" Connections="True" />

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

9. Once you define the customized element, you must create a code group to specify when the CLR should apply the permission set. (For details, see the original Microsoft article). Locate <CodeGroup> tag where the class attribute equals FirstMatchCodeGroup and copy following CodeGroup immediately below it:

<CodeGroup class="UnionCodeGroup"
version="1"
PermissionSetName="CustomTrust">
<IMembershipCondition class="UrlMembershipCondition"
version="1"
Url="$AppDirUrl$/bin/*" />
</CodeGroup>

The membership condition for this new code group is based on URL membership and the URL points to the bin directory. The permissions will be applied to all the assemblies in the bin directory of the current application. You can also use strong name membership but then the permissions will be applied only to one assembly. For example, if I have written a web service and I wanted to assign permissions to my assembly only, I would use strong name membership. Copy following code immediately below the <CodeGroup> tag where the class attribute equals FirstMatchCodeGroup, if you want to use strong name membership:

<CodeGroup class="UnionCodeGroup"
version="1"
PermissionSetName="CustomTrust">
<IMembershipCondition class="StrongNameMembershipCondition"
version="1"
PublicKeyBlob="0x0024000004800000940000000602000000
2400005253413100040000010001004"
Name="UploadService" />
</CodeGroup>

Replace PublicKeyBlob value with your own value and change the name of the assembly in the Name attribute. Name attribute contains the name of the assembly. To retrieve the public key blob for an assembly, use the secutil.exe tool. Please note that publickeyblob is different from publickeytoken. Secutil.exe is located in the following folder:

LocalDrive:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin

To retrieve the public key blob for your assembly, either copy the secutil.exe tool to the folder that contains your assembly else provide exact path to the assembly in the command, and run the tool as follows:

secutil.exe -hex -s UploadService.dll > blob.txt

UploadService.dll is the name of the assembly. This command will create a text file named blob.txt. Open blob.txt and copy the public key and paste it in the publickeyblob attribute.
10. Save and close the file. The policy file is ready to use.
11. Open the web.config file for the virtual server where you have deployed your component and add the following <trustlevel> tag to the SecurityPolicy element:
<trustLevel name="WSS_Custom" policyFile="LocalDrive:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\config\wss_customtrust.config" />

Virtual Directories for web applications are located in the following folder:

LocalDrive:\Inetpub\wwwroot\wss\VirtualDirectories

Suppose I want to deploy my web service in the web application configured at port 17316. The URL of that application would be http://localhost:17316 and its virtual directory will be:

LocalDrive:\Inetpub\wwwroot\wss\VirtualDirectories\17315

Create a bin folder in this path and copy your assembly to the bin folder. The web.config for this virtual server will be located in the following folder:

LocalDrive:\Inetpub\wwwroot\wss\VirtualDirectories\17315

In the web.config file, change the <trust> tag so that it refers to the newly defined trust level.

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

12. Save and close the web.config file.
13. Restart IIS to apply the custom policy to the specified virtual server.

Create a WebPart in MOSS 2007

Build the Web Part derived from ASP.NET 2.0 Detail reason from Andrew Connell: "The official recommendation is to use the ASP.NET 2.0 WebPart class in System.Web.UI.WebControls.WebParts. Don't use the SharePoint WebPart class unless you have a specific reason (which is usually for backwards compatibility)."

I tried the instructions from Developing and Deploying Custom Web Parts for SharePoint Portal 2007. But it never worked to show the web part up on the new web parts page. Then it took me a long time to figure it out why. It's because of the assembly name "NewWebPart". I don't know why this name caused the problem. But after I changed it to "CusCalendar" with the namespace "CusLib", it's showing up in the new web parts list.

Two articles on the MSDN site are very helpful:
Walkthrough: Creating a Basic Web Part
and
Walkthrough: Creating a Basic SharePoint Web Part

Now I get through with trust level WSS_Medium. Next, I will try creating a new trust policy file.

Thursday, September 20, 2007

My blog is finally here

I have my own blog now!!! Yeah!!!

I am not preparing for the Sharepoint test:

Exam 70-541: Microsoft Windows SharePoint Services 3.0 - Application Development
When you pass this exam, you earn credit toward the following certifications: MCTS: Microsoft Windows SharePoint Services 3.0: Application Development.

Exam 70-542: Microsoft Office SharePoint Server 2007 - Application Development
When you pass this exam, you earn credit toward the following certifications: MCTS: Microsoft Office SharePoint Server 2007: Application Development.

Exams are always good to push you to learn something, that's why I am thinking of taking those two exams. The good thing is I am now working on a Sharepoint WCM project which I can have some hands-on experience. And about two months ago I was trained in Sharepoint. So, that's a good start. I am having something to work on now and my wife won't complain that I am too addicted to games.