Вы находитесь на странице: 1из 47

Page 1 of 47

Getting started with SharePoint 2007 Web Parts


By Gavin Sinai

Four important aspects of SharePoint 2007 Web Part development

Introduction
Writing SharePoint Web Parts is one of the best ways to customize the SharePoint platform. Web Parts
combine the power of ASP.NET with the flexibility of Web Part Pages. This article is intended to help you
get going quickly with Web Part development.
We briefly cover four topics in Web Part development:
• Setting up the Visual Studio SharePoint development environment.
• Creating and rendering ASP.NET controls in Web Parts
• Accessing SharePoint data using the Microsoft.SharePoint namespace
• Using the settings API so that admin users can configure and manage web parts in production.
Background
Knowledge of SharePoint, ASP.NET and Visual Studio is required.
Creating the Visual Studio SharePoint development environment
In this section the steps to setup your development are covered. If you already have a working dev
environment then you can safely skip this section.
In order to follow these steps you will need Visual Studio 2005 (.NET 2.0) or later. You will also need
network access to a Windows 2003/8 server with SharePoint 2007 (WSS or MOSS) - SharePoint does not
run on XP or Vista. I usually use a Windows 2003 Virtual PC with .NET 3.5 and Windows SharePoint
Services 3.0. One can also install Visual Studio 2005/8 on the development server.
We assume you have administration rights on your SharePoint server and also administration rights in
your target SharePoint web application.
The steps to setting up your Visual Studio Web Part development environment are as follows:
1. In Visual Studio, create a new class library

Page 1 of 47
Page 2 of 47

2. Add a reference to System.Web

3. In this step we create a simple Web Part that prints "Hello World!" to the screen. A Web Part is a
class that inherits from the WebPart class in System.Web.UI.WebControls.WebParts. In order to
control the rendering of the Web Part one overrides the Render method. An HtmlTextWriter
instance is passed into the Render method and can then be used to write markup to the page
output. The code below is an example of this:
4. using System;
5. using System.Collections.Generic;
6. using System.Text;
7.
8. using System.Web;
9. using System.Web.UI;
10.using System.Web.UI.WebControls;
11.using System.Web.UI.WebControls.WebParts;
12.
13.namespace ExampleWebPartLibrary
14. {
15. public class MyWebPart : WebPart
16. {
17.
18. protected override void Render(HtmlTextWriter writer)
19. {
20. writer.Write("Hello World!");
21. }
22.
23. }
}
24.Using Visual Studio or another suitable tool, give your class library a strong name key and get the
full name of your assembly. You can get the fullname by using "gacutil /l" in the Visual Studio
Command Prompt or by using Lutz Roeder's .NET reflector.
25.In your class library properties, set the build output path to the bin directory of your SharePoint
development web application. I usually share the directory on my development server as
"\\SharePointDev\wss_bin" and use this directory as my build output directory. In Windows
SharePoint Services 3.0 the bin directory is usually of the form
"C:\Inetpub\wwwroot\wss\VirtualDirectories\[Port Num]\bin" and I share this directory as
"wss_bin".
Page 2 of 47
Page 3 of 47

26.Add the code statements using System.Security; and [assembly: AllowPartiallyTrustedCallers] to


your AssemblyInfo.cs file.
27. Ensure that your class library builds and that Visual Studio places the DLL in the expected
location on the server
28.In the web.config file on your target server, you need to add the assembly as a safe control. You
can copy one of the existing safe control entries and fill that in with the details of your assembly.
You will need the full name of the assembly to complete this step.
29.<SafeControl
30. Assembly="ExampleWebPartLibrary, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=db485f68ad2dc0c5"
31. Namespace="ExampleWebPartLibrary"
TypeName="*" Safe="True" AllowRemoteDesigner="True" />
32.You can now add the web part library to your SharePoint site. To do this, log in as an
administrator and go to the settings page. Click on "Web Part Gallery" under the "Galleries"
section. Click "New" and you should see your web part in a list. Select your web part and click
"populate gallery".

33. You can give your web part a friendly title and control its permissions using the edit button in the
web part gallery. I have chosen to call the Web Part "My Web Part".

Page 3 of 47
Page 4 of 47

34. Finally you can add the web part to a web part page and you should see the web part's hard coded
"Hello World!" message.
If your build target is set to the SharePoint bin directory as per step 5 in the list above, then you won't
have to redeploy when you want to test changes. Each time the class library is rebuilt, you can test the
latest version of your Web Part by refreshing your Web Part page.
You also do not need to repeat the above steps whenever you add a new web part to the library. Each time
you add a new web part to the library you simply need to "Populate Gallery" with your new web part.
Remote debugging can be used to debug the Web Part. We won't go into that here; the MSDN library has
an article about this.
Using ASP.NET controls in your web part
In Web Part development you don't have the luxury of Visual Studio's code generation for ASP.NET. You
have to declare, initialise, configure and render the controls yourself in the correct phases of the Web Part
life cycle. In this example we will create a button and a label and use the button press event to change the
label text.
Controls should be declared as member variables and then initialised and configured within an override of
the CreateChildControls method. I usually create a separate method to setup each control and then invoke
that method from CreateChildControls. It is important to add the created controls to the list of Web Part
controls. If a control is not added to this list then it's events won't be raised on post back.
private Button btnDemo;

private void createBtnDemo()


{
btnDemo = new Button();
btnDemo.Text = "Click me";
btnDemo.Click += new EventHandler(btnDemo_Click);

// This line of code is required to trigger the click event


Controls.Add(btnDemo);
}

protected override void CreateChildControls()


{
base.CreateChildControls();
createBtnDemo();
createLblHelloWorld();
}
The controls are rendered inside the Render method override. This method can be used to layout the web
part it's controls. The HtmlTextWriter has many useful methods to help out, including WriteBreak() which
writes a "<br />".
protected override void Render(HtmlTextWriter writer)
{
writer.WriteBreak();

lblHelloWorld.RenderControl(writer);

writer.WriteBreak();
writer.WriteBreak();

btnDemo.RenderControl(writer);
}
Note: A known work around to the problem of not having Visual Studio support for Web Part
development is to embed UserControls in the Web Part. You can read about that in this Code Project
article.
Page 4 of 47
Page 5 of 47

Accessing SharePoint data in your web part


There are two steps you need to take in order to access SharePoint data from within your web part. The
first is to reference Microsoft.SharePoint.dll. You can get a copy of this DLL from your SharePoint server
by browsing to the directory "[Program Files]\Common Files\Microsoft Shared\web server
extensions\12\ISAPI".
The second step is to take care of the code access security for your web part. The easiest way of doing this
is to set the target SharePoint site's trust level to "Full". This level of trust is generally acceptable in an
Intranet environment. If you require that the SharePoint site be run in a minimal or medium trust level
environment then you will need to configure your code access security manually.
To take the easy way out and set the site trust level to "Full" find the following in your site's web.config
file:
<trust level="WSS_Minimal" originUrl="" />
Now change this to:
<trust level="Full" originUrl="" />
Now you can write some code to access SharePoint data. This is just a question of learning and
understanding the SharePoint API, which is worthy of several articles in its own right. Here I show a
simple web part that displays the name of the presently logged in user:
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;

namespace ExampleWebPartLibrary
{
public class HelloUser : WebPart
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
// Get a contextual reference to the current SPWeb
SPWeb currentWeb = SPContext.Current.Web;

// Write a message to the current user


writer.Write("Hello " + currentWeb.CurrentUser.LoginName);
}
}
}
SPContext.Current.Web is the starting point for accessing SharePoint data. For example you can use it to
access data in lists and document libraries.
Using SharePoint settings to manage your Web Part

Web Parts will invariably need settings in order to be useful. There are two ways of providing your web
parts with settings in run time. In a bespoke environment it may be acceptable to place the settings in the
web.config and access them in the same way as you would for standard ASP.NET applications. However
if you require that users be able to easily configure and manage the web part themselves, then you need to
Page 5 of 47
Page 6 of 47

use the SharePoint API to give the web part settings. This will almost certainly be the case if you are an
Independent Software Vendor making a packaged release of your Web Part.
Fortunately it's quite easy to settings-enable your web part. The following steps assume you are starting
with an existing web part, but you can skip to the listing at the end of the article if you are starting from
scratch.
1. Add the required using statements
2. using System;
3.
4. using System.ComponentModel;
5. using System.Runtime.InteropServices;
6. using System.Xml.Serialization;
7.
8. using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
9. Change your web part to inherit from the Microsoft.SharePoint.WebPartPages.WebPart
10.Create a new guid for your web part. Add the Guid and XmlRoot attributes to your Web Part as
follows:
11.[Guid("692b5ada-2f4c-45b0-b9a5-e718db958ae6")]
12.[XmlRoot(Namespace = "ExampleWebPartLibrarySettingsDemo")]
public class SettingsDemo : Microsoft.SharePoint.WebPartPages.WebPart
13. Add the different attributes applied to the property that is used as a setting. Adjust the constant
string attribute arguments according to your needs.
14.private string mySetting;
15.
16. // SharePoint setting with required attributes
17.[Browsable(true),
18.Category("Example Web Parts"),
19.DefaultValue("Default"),
20.WebPartStorage(Storage.Shared),
21.FriendlyName("MySetting"),
22.Description("An example setting")]
23.public string MySetting
24. {
25. get { return mySetting; }
26. set { mySetting = value; }
}
27. Using the setting in code (in this case, the render method).
The complete code listing is as follows:
// using statements required for settings
using System;

using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Xml.Serialization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;

namespace ExampleWebPartLibrary
{
//Guid and XmlRoot attributes for a settings enabled web part
[Guid("692b5ada-2f4c-45b0-b9a5-e718db958ae6")]
Page 6 of 47
Page 7 of 47

[XmlRoot(Namespace = "ExampleWebPartLibrarySettingsDemo")]

// NB inherit from SharePoint WebPart rather than ASP.NET Web Part


public class SettingsDemo : Microsoft.SharePoint.WebPartPages.WebPart
{
private string mySetting;

// SharePoint setting with required attributes


[Browsable(true),
Category("Example Web Parts"),
DefaultValue("Default"),
WebPartStorage(Storage.Shared),
FriendlyName("MySetting"),
Description("An example setting")]
public string MySetting
{
get { return mySetting; }
set { mySetting = value; }
}

// use the setting in code


protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
writer.Write("Value of MySetting: ");
writer.Write(mySetting);
}

}
}

SharePoint 2007 Flash Animation Web Part


By Mahdi Abdulhamid

Page 7 of 47
Page 8 of 47

Introduction
I've seen that many people are using HTML content web part for displaying Flash animation. I don't
recommend this approach for many reasons, one of them being you won't tell your client to edit HTML
code for changing Flash properties; so it is better to have a dedicated web part for rendering Flash
animation.
Software Requirements
• Microsoft SharePoint 2007 installed (With Site Collection created on port:80)
• SharePoint Services 3.0 Extensions for Visual Studio 2005 installed
Using the code
To apply the code, you will need to create a new SharePoint Webpart Project then overrides the web part
class file:
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Utilities;
using System.Web.UI.HtmlControls;
namespace FlashWebPart
{
[Guid("f04fa49d-1342-4c7d-904a-c43ebc942f39")]
[XmlRoot(Namespace = "FlashWebPart")]
public class FlashWebPart : Microsoft.SharePoint.WebPartPages.WebPart
{
public FlashWebPart()
{
this.ExportMode = WebPartExportMode.All;
}
protected int flashWidth = 400;
protected int flashHeight = 300;
Page 8 of 47
Page 9 of 47

protected string flashUrl = "";

<BROWSABLE(true),
Category("Flash Info"),
DefaultValue(400),
WebPartStorage(Storage.Shared),
FriendlyName("Width"),
Description("Width of the web part")>
public int FlashWidth
{
get
{
return this.flashWidth;
}
set
{
this.flashWidth = value;
}
}
<BROWSABLE(true),
Category("Flash Info"),
DefaultValue(300),
WebPartStorage(Storage.Shared),
FriendlyName("Height"),
Description("Height of the web part")>
public int FlashHeight
{
get
{
return this.flashHeight;
}
set
{
this.flashHeight = value;
}
}
<BROWSABLE(true),
Category("Flash Info"),
DefaultValue(""),
WebPartStorage(Storage.Shared),
FriendlyName("URL"),
Description("URL of the web part")>
public string FlashURL
{
get
{
return this.flashUrl;
}
set
{
this.flashUrl = value;
}
}
Page 9 of 47
Page 10 of 47

protected override void Render(HtmlTextWriter writer)


{
string outHTML =
"<OBJECT classid=
\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" " +
"codebase=
\"http://download.macromedia.com/pub/shockwave/cabs/
flash/swflash.cab#version=7,0,0,0\" " +
"WIDTH=" + flashWidth + " HEIGHT=" + flashHeight + ">
" + "<PARAM NAME=movie VALUE=\"" + flashUrl + "\"> " +
"<PARAM NAME=WMODE VALUE=\"Transparent\">" +
"<PARAM NAME=quality VALUE=high> " +
"<EMBED src=\"" + flashUrl +
"\" quality=high wmode=\"transparent\" WIDTH=\"" +
flashWidth +
"\" HEIGHT=\"" + flashHeight +
"\" TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=
\"http://www.macromedia.com/shockwave/download/
index.cgi?P1_Prod_Version=ShockwaveFlash\"></EMBED> "
+ "</OBJECT>";
writer.Write(outHTML);
}
}
}

/w EPDw UKMTAy

Simple WebPart To Load UserControl


By agusto xaverius

It is a simple webpart but very usefull to load many usercontrols

Introduction
Moss/WSS is so CMS popular currently. There are many thing can be which can be done and is modified
at deep technology on that product.
Work with on that solution will ever be utilize webpart. But if we develop one webpart sometimes we do
ever make same old things which is make coding webpart and load the usercontrol what does we want.
Background

Page 10 of 47
Page 11 of 47

This concept is similiar with SmartPart which you just create one webpart and then it can be used to load
all your usercontrol without writing webpart again.
Using the Code
The listing code is like this:
1. Write on your class solution like this. Please reference Microsoft.Sharepoint.dll component and
System.Web.dll too.
using System;
using System.ComponentModel;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;

namespace WebPartLib
{
public class WebPartGeneral : Microsoft.SharePoint.WebPartPages.WebPart
{
private Control _childControl = null;
private string _userControlVirtualPath = string.Empty;
private string _errMessage = string.Empty;

public WebPartGeneral()
{}

[
Personalizable(),
Category("Miscellaneous"),
DefaultValue(""),
WebBrowsable(true),
WebDisplayName("User Control Virtual Path"),
WebDescription("User Control Virtual Path")
]
public string UserControlVirtualPath
{
get { return _userControlVirtualPath; }
set { _userControlVirtualPath = value; }
}

protected override void RenderWebPart(HtmlTextWriter output)


{
if (_errMessage != string.Empty) output.Write(_errMessage);
if (_userControlVirtualPath != string.Empty ||
_userControlVirtualPath.Equals("") == false)
RenderChildren(output);
}

protected override void RenderChildren(HtmlTextWriter output)


{
try
Page 11 of 47
Page 12 of 47

{
this.EnsureChildControls();
if (this._childControl != null)
this._childControl.RenderControl(output);
}
catch (Exception ex)
{
_errMessage = string.Format(
"Exception Message (RenderWebPart) = {0}<br />", ex.Message);
}
}

protected override void CreateChildControls()


{
base.CreateChildControls();
if (_userControlVirtualPath != string.Empty)
{
if (_childControl != null) return;
_childControl = Page.LoadControl(_userControlVirtualPath);
if (_childControl != null)
Controls.AddAt(0, _childControl);
}
}

public override void Dispose()


{

}
}
}
2. After the solution already successfully compile and the put the binary into bin folder on your
MOss/Wss site. After it also make one folder by which UserControls.

1. Modify your web.config


eControl Assembly="WebPartLib, Version=1.0.0.0, Culture=neutral"
Namespace="WebPartLib" TypeName="*" Safe="True"
AllowRemoteDesigner="True" />
and change trust level from WSS_Minimal into Full.
<trust level="Full" originUrl="" />
4. If Necesary you can client restart your IIS and the back to your site again and list the webpart into
list of webpart

5. Create new website solution and create a simple usercontrol and then copy all .ascx and .cs into
UserControls folder
6. Now you can utilize webpart and set the virtual path into your usercontrols and the simsalabim
your webpart now load your usercontrol. You can create another usercontrol again and you can
add your webpart again and set the usercontrols to load.

Page 12 of 47
Page 13 of 47

WebPart Life CycleBy Fabio Barbieri

This article examines the production of a simple WebPart in C#

Page 13 of 47
Page 14 of 47

Introduction
In Sharepoint 2007, a way to customize the environment pass is by building WebParts coded with one of
the languages available in VS2005. In this article, we're going to examine the production of a simple
WebPart in C#, to better comprehend the life cycle and later, look at events that the developer has to
consider in order to get the correct execution of code.
Use Case Description
In this sample will be proposed a typical case where the selection of an item in a dropdown list raises the
event of filling a second dropdown list (server-side event) with proper items to the value selected.
Specifically, the first dropdown list contains a short nations list, the second dropdown list will be loaded
with a short town list belonging to the nation selected.
Besides the two dropdown lists are shown the steps regarding principal event routines and property Text
of DropDownList nation.
The complete Webpart will have the following rendering graphic:

The Web Part


It is interesting to note that DropDownList nation has set ViewState and AutoPostBack to true. The article
scope is to highlight the WebPart life Cycle and understand when the value of a control (i.e. Text
property) that has ViewState set up to be true, becomes available. In practice, this happens when the user
selects a nation changing the first dropdown list item which starts the Postback event, at which point the
value of the new item is available.
The Code
As is possible to understand by the shown log, there are four predefined routines that take place in a
WebPart Life Cycle:
1. OnInit: Typically in this routine we define controls that will be involved with WebPart:
2. protected override void OnInit(EventArgs e)
3. {
4. try
5. {
6. _divPanel = new Panel();

Page 14 of 47
Page 15 of 47

7. _ddlCountry = new DropDownList();


8.
_ddlTown = new DropDownList();
9. CreateChildControls: In this routine are defined control properties and methods previously
declared. In most cases, we have to initialize the control's default value (as Text, Checked, Items,
and so on) and activity that is possible to call just at first WebPart load, checking PostBack:
10.protected override void CreateChildControls()
11. {
12. try
13. {
14. base.CreateChildControls();
15. _divPanel.ID = "_divPanel";
16. _divPanel.BorderStyle = BorderStyle.Ridge;
17. _divPanel.Width = 250;
18. _divPanel.Height = 300;
19. _divPanel.BackColor = System.Drawing.Color.Gainsboro;
20. Controls.Add(_divPanel);
21. _ddlCountry.AutoPostBack = true;
22. _ddlCountry.ID = "_ddlCountry";
23. _ddlCountry.Width = 150;
24. _ddlCountry.EnableViewState = true;
25. _ddlCountry.SelectedIndexChanged +=
26. new EventHandler(_ddlCountry_SelectedIndexChanged);
27. _divPanel.Controls.Add(_ddlCountry);
28. _ddlTown.AutoPostBack = false;
29. _ddlTown.ID = "_ddlTown";
30. _ddlTown.Width = 150;
31. _ddlTown.EnableViewState = true;
32. _divPanel.Controls.Add(_ddlTown);
33.
34. if (!Page.IsPostBack)
ddlCountry_Load();
35.OnPreRender: This is the routine where the control's value kept by ViewState (for example Item
value set up by the user to DropDownList nation), is available. For this reason, it's normal to
begin business procedure from here, and in our case we're going to load values for the second
dropdown list (Town DropDownList) with the proper data:
36.protected override void OnPreRender(EventArgs e)
37. {
38. try
39. {
40. _sMex += "OnPreRender: " + _ddlCountry.Text + " ";
41. string sStateSelected = _ddlCountry.Text;
42. _ddlTown.Items.Clear();
43.
44. switch (sStateSelected)
45. {
46. case "England":
47. ddlTown_Load("London", "Liverpool", "Bristol");
48. break;
49.
50. case "Spain":
Page 15 of 47
Page 16 of 47

51. ddlTown_Load("Madrid", "Barcelona", "Valencia");


52. break;
53.
54. case "Italy":
55. ddlTown_Load("Rome", "Milan", "Florence");
56. break;
57.
58. default:
59. ddlTown_Load("New York", "Tokio", "Paris");
60. break;
}
61.Render: That's the routine for HTML rendering WebPart:
62.protected override void Render(HtmlTextWriter writer)
63. {
64. _sMex += "Render: " + _ddlCountry.Text + " <br />";
65. writer.Write(" <div id='_divPanel'>");
66. writer.Write(" <table style='border-right: 1px ridge;
67. border-top: 1px ridge; border-left: 1px ridge;");
68. writer.Write(" border-bottom: 1px ridge;
69. background-color: gainsboro;'
70. cellpadding='3' cellspacing='2'");
71. writer.Write(" width='250'>");
72.
73. if (_sErrDescription == "")
74. {
75. // dropdownlist State
76. writer.Write(" <tr style='border-right:
77. 1px ridge; border-top: 1px ridge; border-left: 1px ridge;");
78. writer.Write(" border-bottom: 1px ridge;'>");
79. writer.Write(" <td style='height: 50px'>");
80. _ddlCountry.RenderControl(writer);
81. writer.Write(" </td>");
82. writer.Write(" </tr>");
83.
84. // dropdownlist town
85. writer.Write(" <tr style='border-right: 1px ridge;
86. border-top: 1px ridge; border-left: 1px ridge;");
87. writer.Write(" border-bottom: 1px ridge;'>");
88. writer.Write(" <td style='height: 50px'>");
89. _ddlTown.RenderControl(writer);
90. writer.Write(" </td>");
91. writer.Write(" </tr>");
}

Developing and Deploying Custom Web Parts for SharePoint Portal 2007

Overview and difference with SPS 2003:


Developing Web Part for SharePoint Portal 2007 is different as compared to developing for SPS 2003.
Web Parts Developed in .Net 1.1 for SPS 2003 used the SharePoint.WebPartPages namespace, however
Page 16 of 47
Page 17 of 47

the Web Part in ASP.Net 2.0 is found under the System.Web.UI.WebControls.WebParts.

Development of Web Part in VS 2005


To Get Started with creating Custom Web Part for MOSS 2007 in Microsoft Visual Studio 2005, Open
the IDE and create a new C# project, Select Class Library as Project Type. Name It as NewWebPart.

Add a reference to the System.Web from .Net components into the project. The System.Web dll contains
the required namespace of System.Web.UI.WebControls.WebParts .

Page 17 of 47
Page 18 of 47

In The Project explorer view rename the Class1.cs with NewWbPart.cs to be consistent with this
example; this will result in renaming the Class name as well. With the help of “using” keyword include
the namespaces as shown in the code example below. Derive / Extend the NewWebPart Class from the
WebPart Class ( System.Web.UI.WebControls.WebParts.WebPart), and add the code as shown below. The
CreateChildren Control is same as in .Net 1.1, that it would create and add controls to this Web Part
Class,. In this case I have only added a WebControl.Calender Object. The RenderControl Method is an
override for the WebPart Base Class and calls the RenderChildren Method, this causes the Children
Controls to be rendered on the Particular HtmlTextWriter passed as a parameter to the method.

using System;
using System.Collections.Generic;
using System.Text;

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace NewWepPart
{
public class NewWebPart : WebPart
{

protected override void CreateChildControls()


Page 18 of 47
Page 19 of 47

{
Calendar cldr = new Calendar();
cldr.Enabled = true;
cldr.ShowGridLines = true;
cldr.ShowTitle = true;
cldr.EnableViewState = true;
cldr.SelectedDate = DateTime.Now;

Controls.Add(cldr); �

}

public override void RenderControl(HtmlTextWriter writer)


{

RenderChildren(writer);
}

}
}

Build the project and on successful built you are ready to Deploy the Web Part to the Portal Site.

Deployment of Web Part:


In order to deploy a web part to a SharePoint portal 2007 site, we must have the URL of the site to which
we want our web part needs to be deployed (displayed in fact). As it is mentioned earlier that the Web
Parts developed in .Net 2.0 environment does have a .CAB project , instead an assembly is created on
build of project. Now there are two choices to deploy the assembly to the SharePoint portal directory.
 Deploy the assembly to the Assembly Folder (GAC) (requires the assembly to be stron named).
 Put the assembly to the bin folder of the portal directory.
For the sake of simplicity, the later choice is being demonstrated in this example.

Putting Assembly in Bin Folder:


The MOSS 2007 creates every portal in the inetpub\wwwroot\wss folder. The easiest way to find the bin
folder from these folder hierarchies is to go from inetmgr console. Locate the appropriate portal (for
which u want to deploy the web part), identified with the port number. Right click and have Properties.
Under the Home Directory Tab, note the path in Local path text box. Verify if the bin folder exists in the
specified path by opening it in browser. If the folder doesn’t exist then create one. Now copy the
assembly form the project output folder and paste it in bin folder of portal.

Page 19 of 47
Page 20 of 47

However there is another work around for putting the assembly in to the portal’s bin folder again ad again
each time the Web Part Project is built with changes.
Right click on the project name (NewWebPart) in the VS.Net 2005 IDE and click properties. Under
the Build page paste the same path copied from inetmgr console into the Output Path. As shown in
figure below. This will result in the latest assembly automatically deployed to the bin folder every time
the project is built.

Page 20 of 47
Page 21 of 47

Adding the Safe Control Entry:


Even though the assembly is present in the Portal’s Bin folder, there is another step required to make the
Control (Web Part) assembly usable on the Portal Pages. Since the control will need to render on multiple
machines in different browsers with as many user accounts as the organizations have. There is a need to
declare the control as “safe”. To do so open the web.config file placed under the portal’s directory in the
VS.Net 2005 IDE.

Page 21 of 47
Page 22 of 47

Then edit the file in the section of SafeControls, create a new SafeControl entry for our assembly as
shown below. Save the file and close it.

<SafeControls>
<SafeControl Assembly="NewWebPart" Namespace="NewWebPart" TypeName="*" Safe="True" />

SafeControls>

Configuring Portal to use NewWebPart


Since now the web part have been written and deployed to the desired portal’s directory. The next task is
to use the web part on the Portal’s Site. The Web Part Deployed to the portal can be placed on any site
within that Portal. For convenience this NewWebPart is demonstrated to be placed on the home page of
default Portal.
Open the portal site in the internet explorer; in this case http://oss1 is the URL for the default portal,
ensuring that the current logged in user has the administrative rights on the portal site.

To begin with, the first step is to add the newly deployed web to the Portal’s web part gallery, since the
portal is using the configuration databases to keep record of the contents of the portal, our newly created
web part’s information doesn’t exist in the database. We need to add the web part to the Web Part Gallery
before we can use it.

To do so, the following steps should be followed.


1. Click on the Site Actions button and then select Site Settings.

Page 22 of 47
Page 23 of 47

1. On the site settings page under Galleries column click on the Web Parts.

Page 23 of 47
Page 24 of 47

1. On the Web Part Gallery Page click on the New button, to add the new web part assembly to the gallery.

Page 24 of 47
Page 25 of 47

1. On the New Web Parts page locate the NewWebPart in the list, check the check box on the left and
click on the Populate Gallery button the top of the page. This will result in the Web Part entry creation in
the Web Part Gallery list, and hence it can be used from now on from the gallery. It can be notices easily
that the Web Parts developed form the new Frame work of 2.0 have an extension of .webpart after their
names. Whereas in earlier versions, it was a .dwp file. Both the .webpart and .dwp files are the XML
definition of the Web Part.

Page 25 of 47
Page 26 of 47

1. Until this step the web part is ready to be used on the site by selecting it from Web Part Gallery. Click on
the Site Actions button on the page and then select Edit Page, this will modify the appearance of the
page to enable the edit view. In this view Web Part Zones are highlighted so that a user can add a web
part to the zone, Click on the Add a Web Part button in the left zone to add the Web Part.

Page 26 of 47
Page 27 of 47

1. Select the NewWebPart from the web part list . it is found under the Misc section and then click
on�Advanced Web Part gallery and options.

Page 27 of 47
Page 28 of 47

1. In the�Add Web Part Pane at right , select Home Gallery and then drag the NewWebPart from the
pane into the Web Part Zone.

Page 28 of 47
Page 29 of 47

1. Click on the Exit Edit Mode link on the page and the site will return to the view mode.

Page 29 of 47
Page 30 of 47

Writing Custom Webparts for Sharepoint 2007


This is based on Sharepoint 2007 Beta1TR
Posted on 7/31/2006 @ 6:38 AM in #Sharepoint | 65 comments | 63302 views
As I have already indicated, and as Scott Guthrie also pointed out, Sharepoint 2007 is built upon
ASP.NET 2.0. Well, so a Sharepoint 2007 WebPart is a decendant of an ASP.NET 2.0 WebPart, i.e. Your
custom WebPart, inherits from Sharepoint WebPart, which inherits from an ASP.NET 2.0 WebPart.
Now, as already indicated by my good friend, Andrew Connell, it is highly recommended that you should
write an ASP.NET 2.0 WebPart instead of one that inherits from the Sharepoint WebPart. As Andrew
mentioned on his blog, it appropriate to build Web Parts derived from the SharePoint class only when you
need -
Cross page connections
Connections between Web Parts that are outside of a Web Part zone
Client-side connections (Web Part Page Services Component)
Data caching infrastructure

So in this blogpost, we will see how to write the simplest possible Sharepoint 2007 WebPart and deploy
it. Just for fun, we will inherit from the sharepoint webpart instead of the asp.net webpart.
Begin by creating a class library project, add references to System.Web, Microsoft.Sharepoint.dll (again
only because this blogpost talks about Sharepoint Webpart).
Then add a class as below, which as you can tell is a hella simple WebPart.
Page 30 of 47
Page 31 of 47

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Web;
using System.Web.Security;
using System.Security;
using System.Security.Permissions;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.WebPartPages;

namespace Sahil.Sharepoint.WebPartPages
{
[System.Xml.Serialization.XmlRoot(Namespace = "http://blah.winsmarts.com/demospace")]
public class CustomWebPart : WebPart
{
private string toDisplayText = "Default Text";
[WebPartStorage(Storage.Shared), System.Xml.Serialization.XmlElement(Namespace =
"http://blah.winsmarts.com/demospace")]
public string ToDisplayText
{
get { return toDisplayText; }
set { toDisplayText = value; }
}
protected override void RenderWebPart(System.Web.UI.HtmlTextWriter writer)
{
writer.Write(toDisplayText) ;
base.Render(writer);
}
}
}
Great !! Now, strongly name it, Build the dll, and use sn-t or reflector to find the public key token.
Then follow the following steps -
1. Locate the Sharepoint WebSite you wish to deploy this webpart in. This can be done via the IIS
Manager under administrative tools. The default ones would be virtual directories that look like GUIDs
under C:\INETPUB\WWROOT\WSS\<<GUID>>. In my case (yours may be different) the dir was -
C:\Inetpub\wwwroot\wss\VirtualDirectories\7ee252c4-9e98-4258-a6ae-77e16a287bea\bin
2. Drop the dll in the bin directory in the virtual dir.

Important: By dropping the webpart in the bin directory, you are effectively giving it partial trust. If you
were writing a plain vanilla ASP.NET 2.0 WebPart, you would need to decorate the Webpart with the
AllowPartialTrustedCallersAttribute @ the assembly level. You could also create a new trust policy for
your WebPart (recommended), or raise the trust level in the web.config file (default is WSS_Minimal), or
you could just drop the Webpart in the GAC; which again requires strong naming.
3. Under the same virtual directory, find the web.config, and add the following to the SafeControls
section -
<SafeControl Assembly="Sahil.Sharepoint.WebPartPages, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=84da1d46719d7853" Namespace="Sahil.Sharepoint.WebPartPages" TypeName="*"
Safe="True" AllowRemoteDesigner="True" />
4. Then browse to the WebSite, and go to Site Actions -> Site Settings -> Modify All Site Settings. Under
that, click on "Web Parts" under Galleries.
Page 31 of 47
Page 32 of 47

5. Click on "New" in the toolbar, and find the Sahil.Sharepoint.WebPartPages.CustomWebPart as shown


below -

6. Check the checkbox, go to the top, click on "Populate Gallery".

Getting Started With SharePoint Web Services


Posted by Trent Swanson on Feb 06, 2008 02:50 AM
Community
.NET
Topics
Web Services ,
Application Servers ,
Interop
SharePoint supports interoperability and remote operations through a set of web services, and by
SharePoint I am referring to WSS 3.0 (Windows SharePoint Services) and MOSS 2007 (Microsoft Office
SharePoint Server). There are number of approaches for programmatic access to SharePoint, such as the
object model, web services, RPC over HTTP, as well as WebDAV, all of which have their benefits and
their place depending on the needs of the application. The SharePoint RPC protocols can be useful and
powerful and it certainly has its strengths, especially when it comes to adding content. The object model
is much more robust and feature rich than the web services, but it does not offer support for remote
operations, so in order to leverage the object model your code must be running on the SharePoint server,
and you must be writing .NET code in order to leverage it. There are a number of different reasons for
working with SharePoint data remotely, be it administrative scripts or the need to work with SharePoint
content such as tasks in an application running on a client machine, or non-SharePoint applications in the
enterprise. The SharePoint web services are built on top of the object model and expose a subset of
features available in the object model, and allow for remote operations and the use of any language and
platform that supports the consumption of web services. For most tasks the web services that ship in
SharePoint are adequate, but you may find needed operations in the object model that have not been
surfaced in the web services, which will require extending the web services with a custom web service
implementation. In this article we will take a look at the web services available in WSS3 and MOSS 2007
out of the box, and how to consume them from Java and .NET.
RelatedVendorContent
5 Myths of Agile Development Explained
Profile your .NET code with ANTS Profiler – Download your free trial here
Introduction to Microsoft Visual Studio Team Systems
Defy all challenges. Together. Microsoft® Visual Studio Team System
Agile Development: A Manager’s Roadmap for Success
Web Services Architecture Overview
I will not go in to the detailed differences between the WSS and MOSS, as there are a number of articles
that do a very good job explaining this, only as needed and where related to the web services. Keep in
mind that MOSS 2007 is built on top of WSS 3.0, which is also built on top of ASP.NET 2.0 and runs in
IIS (Internet Information Server). A solid understanding of IIS and ASP.NET is important, and go long
way in working with and understanding SharePoint. A majority of the SharePoint web services we will
discuss are included in WSS 3.0, but there are a few additional ones that are included in MOSS 2007 to
leverage the additional features that ship with it, such as the more advanced enterprise search features.
The SharePoint web services are implemented in ASP.NET Web Services (ASMX), and you will find the
physical files for most of these web services in the "Microsoft Shared" directory under "web server
extensions\12\ISAPI" typically located at "C:\Program Files\Common Files\Microsoft Shared\web server
extensions\12\ISAPI". The admin web service for the Central Administration tool is located in the

Page 32 of 47
Page 33 of 47

ADMISAPI folder for which the central administration console contains a virtual directory named
"_vti_adm". When a SharePoint site is created it will contain a virtual directory named "_vti_bin" that
points to this location. IIS does not contain any application or virtual directories for subwebs, they do
however contain mapping to the _vti_bin virtual directory through SharePoint metadata and HttpModules.

For each service you will find a *.wsdl.aspx file that generates the service WSDL (Web Services
Description Language), a *.disco.aspx providing the service discovery implementation, and the actual
*.asmx endpoint files, most of which simply contain a page directive referencing the SharePoint assembly
and type containing the actual implementation for the service.

Page 33 of 47
Page 34 of 47

Service File Type Description


*.wsdl.aspx File that generates the WSDL (Web Services Description Language) in
(search.wsdl.aspx) SharePoint
*.disco.aspx
File that provides the discovery implementation
(seach.disco.aspx)
Web services endpoint, most of which contain a page directive referencing the
*.asmx (search.asmx) SharePoint assembly and type containing the actual implementation for the
service
Out of the Box Services
There are a number of web services implemented OOTB (out of the box) in SharePoint that will address
most of the common and basic tasks, from administrative tasks to search and working with list data, and
much more. Below is a listing of the SharePoint web services with an overview of the functionality
exposed for your reference. A simple expanded list like this helps me in working with the web services
giving me a quick view of the overall services and methods available.
Service Administration
Administrative methods for creating deleting sites and
retrieving languages used in the deployment
• CreateSite
(_vti_adm/Admin.asmx) • DeleteSite
• GetLanguage
• RefreshConfigCache
Methods for working with SharePoint list item alerts
Alerts (Alerts.asmx) • DeleteAlerts
• GetAlerts
Client proxy that provides user authentication for sites that use
forms-based authentication
Authentication (Authentication.asmx) • Login (Used to authenticate)
• Mode (Returns the authentication mode of the current
site)
Methods to copy files between or within sites
• CopyIntoItems (Copy document as byte array to
location on server)
Copy (Copy.asmx) • CopyIntoItemsLocal (Copy document from one
location on the same server to another)
• GetItem (Creates a byte array of a document that can
be passed to theCopyIntoItems method)
Document Workspace (Dws.asmx) Methods for managing Document Workspace sites and data
• CanCreateDwsUrl
• CreateDws
• CreateFolder
• FindDwsDoc
• GetDwsData
• GetDwsMetaData
• RemoveDwsUser

Page 34 of 47
Page 35 of 47

• RenameDws
• UpdateDwsData
Methods for returning forms that are used in the user interface
when working with the contents of a list
Forms (Forms.asmx) • GetForm
• GetFormCollection
Methods to create and manager picture libraries
• CheckSubwebAndList
• CreateNewFolder
• Delete
• Download
• Edit
Imaging (Imaging.asmx)
• GetItemsByIds
• GetItemsXMLData
• GetListItems
• ListPictureLibrary
• Rename
• Upload
Perform queries against sites and list in SharePoint
List Data Retrieval (DspSts.asmx) • Query (Performs queries against SharePoint lists and
sites)
Lists (Lists.asmx) Methods for working with Lists and List Data
• AddAttachment
• AddDiscussionBoardItem
• AddList
• AddListFromFeature
• ApplyContentTypeToList
• DeleteAttachment
• DeleteContentType
• DeleteContentTypeXmlDocument
• DeleteList
• GetAttachmentCollection
• GetList
• GetListAndView
• GetListCollection
• GetListContentType
• GetListContentTypes
• GetListItemChanges
• GetListItemChangesSinceToken
• GetListItems
• GetVersionCollection
• UndoCheckout
• UpdateContentType

Page 35 of 47
Page 36 of 47

• UpdateContentTypesXmlDocument
• UpdateContentTypeXmlDocument
• UpdateList
• UpdateListItems
Create and manage Meeting Workspace Sites
• AddMeeting
• AddMeetingFromICal
• CreateWorkspace
• DeleteWorkspace
• GetMeetingInformation
Meetings(Meetings.asmx) • GetMeetingWorkspaces
• RemoveMeeting
• RestoreMeeting
• SetAttendeeResponse
• SetWorkspaceTitle
• UpdateMeeting
• UpdateMeetingFromICal
Resolve and find Principals
People(People.asmx)
• ResolvePrincipals
Methods for working with permissions for a site or list
• AddPermission
• AddPermissionCollection
Permissions (Permissions.asmx) • GetPermissionCollection
• RemovePermission
• RemovePermissionCollection
• UpdatePermission
Methods for managing Active Directory e-mail distribution
groups and their memberships
• ChangeContactsMembershipInDistributionGroup
• ChangeUsersmembershipInDistributionGroup
• CreateContact
Directory • CreateDistributionGroup
Management(sharepointemailws.asm • DeleteContact
x)
• DeleteDistributionGroup
• GetJobStatus
• ModifyContact
• ModifyDistributionGroup
• RenameDistributionGroup
Site Data (SiteData.asmx) Methods that return metadata or list data from sites or lists
• EnumerateFolder
• GetAttachments
• GetChanges
• GetContent
Page 36 of 47
Page 37 of 47

• GetList
• GetListCollection
• GetListItems
• GetSite
• GetSiteAndWeb
• GetSiteUrl
• GetURLSegments
• GetWeb
Methods for returning information about the collection or site
template
• ExportWeb
Sites(Sites.asmx) • GetSiteTemplates
• GetUpdatedFormDigest
• ImportWeb
Methods for searching via search services
• Query
Search(spsearch.asmx) • QueryEx
• Registration
• Status
Users & Groups(usergroup.asmx) Methods for working with users role definitions and groups
• AddGroup
• AddGroupToRole
• AddRole
• AddRoleDef
• AddUserCollectionToGroup
• AddUserCollectionToRole
• AddUserToGroup
• AddUserToRole
• GetAllUserCollectionFromWeb
• GetGroupCollection
• GetList
• GetListAndView
• GetListCollection
• GetGroupCollectionFromRole
• GetGroupCollectionFromSite
• GetGroupCollectionFromUser
• GetGroupCollectionFromWeb
• GetGroupInfo
• GetRoleCollection
• GetRoleCollectionFromGroup
• GetRoleCollectionFromUser
• GetRoleCollectionFromWeb
• GetRoleInfo

Page 37 of 47
Page 38 of 47

• GetRolesAndPermissionsForCurrentUser
• GetRolesAndPermissionsForSite
• GetUserCollection
• GetUserCollectionFromGroup
• GetUserCollectionFromRole
• GetUserCollectionFromSite
• GetUserCollectionFromWeb
• GetUserInfo
• GetUserLoginFromEmail
• RemoveGroup
• RemoveGroupFromRole
• RemoveRole
• RemoveUserCollectionFromGroup
• RemoveUserCollectionFromRole
• RemoveUserCollectionFromSite
• RemoveUserFromGroup
• RemoveUserFromRole
• RemoveUserFromSite
• RemoveUserFromWeb
• UpdateGroupInfo
• UpdateRoleDefInfo
• UpdateRoleInfo
• UpdateUserInfo
Methods for working with file versions
• DeleteAllVersions
Versions (Versions.asmx) • DeleteVersion
• GetVersions
• RestoreVersion
Methods for working with list views
• AddView
• DeleteView
• GetViewCollection
Views(Views.asmx)
• GetViewHtml
• UpdateView
• UpdateViewHtml
• UpdateViewHtml2
Web Part Pages(WebPartPages.asmx) Methods for working with Web Part Pages
• AddWebPart
• AddWebPartToZone
• AssociateWorkflowMarkup
• ConvertWebPartFormat
• DeleteWebPart
• ExecuteProxyUpdates

Page 38 of 47
Page 39 of 47

• FetchLegalWorkflowActions
• GetAssemblyMetaData
• GetBindingResourceData
• GetCustomControlList
• GetDataFromDataSourceControl
• GetFormCapabilityFromDataSourceControl
• GetSafeAssemblyInfo
• GetWebPart
• GetWebPart2
• GetWebPartCrossPageCompatibility
• GetWebPartPage
• GetWebPartPageConnectionInfo
• GetWebPartPageDocument
• GetWebPartProperties
• GetWebPartProperties2
• RemoveWorkflowAssociation
• RenderWebPartForEdit
• SaveWebPart
• SaveWebPart2
• ValidateWorkflowMarkupAndCreateSupportObjects
Methods for working with sites and subsites
CreateContentType
CustomizeCss
DeleteContentType
GetActivatedFeatures
GetAllSubWebCollection
GetColumns
GetContentType
GetContentTypes
GetCustomizedPageStatus
Webs(Webs.asmx) GetListTemplates
GetWeb
GetWebCollection
RemoveContentTypeXmlDocument
RevertAllFileContentStreams
RevertCss
RevertFileContentStream
UpdateColumns
UpdateContentType
UpdateContentTypeXmlDocument
WebUrlFromPageUrl
MOSS Search (Search.asmx) Methods for searching via MOSS (Microsoft Office
SharePoint Server) Search services, which also includes a
method to retrieve the managed search properties
• GetSearchMetadata (Search managed properties)
• Query
• QueryEx

Page 39 of 47
Page 40 of 47

• Registration
• Status
Consuming the Query Services
Now that we have an understanding of the SharePoint web services, there is nothing like kicking the tires
and taking a ride after reading through the owner's manual. We don't have time here to dive deep in to all
of the web services, and will save the others for the next article. For some reason a number of the web
services in SharePoint either take or return an XML Node or an XML encoded string, and unfortunately
without a typed schema the tools are unable to infer what this should be and generate those nice proxy
objects for us. I have seen a number of implementations using string formatting with the web services to
address the lack of a typed schema, and have searched long and far for a schema that describes the XML
passed and returned from these services. I ended up creating queryresponse.xsd which was inferred from
a combination of the documentation and the xml passed in and out of these services, allowing me to
generate the class representation using xsd.exe for .NET users and JAXB for java users.
Note: There are two different search web services, as discussed previously, search.asmx for MOSS and
spsearch.asmx for WSS. These services are very similar in their schema, but attempting to call
spsearch.asmx on a machine running MOSS will throw an exception due to the fact that the WSS
indexing and query services have been disabled in favor of the more advanced search features in MOSS.
Example using .NET
Consuming the SharePoint web services from .NET is rather simple and straight forward, you simply
need to add a web reference and use the generated proxy. We will add a step to leverage the XSD we
created to generate a set of classes representing a query and response that we will use to serialize the
XML sent and deserilize the XML returned.
Configure Visual Studio 2005 to add XSD.exe to the menu
Visual studio includes a tool called XSD.exe that can be used to generate .NET types from an XSD. This
is however a command line tool and I like to add a menu option to visual studio to do this from the IDE.
If you have already done this or have some other add-in to do something similar you can skip this step.
1. Open the "External Tools" Dialog in the Visual Studio "Tools" menu
2. Click "Add"
3. Set the necessary properties and click "Ok"
Property Value
Command XSD >> CSharp
Title C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\xsd.exe
Arguments $(ItemPath) /c
Initial Directory $(ItemDir)
Use Output Window Checked

Page 40 of 47
Page 41 of 47

Download the XSD files


Download the XSD files from here which will be used to generate the proxy classes used to serialize and
de-serialize the search requests and responses. Unpack the downloaded file to a working directory; this
file contains the XSD along with the completed project.
Create a Project and Generate a .NET type from the XSD Now that we have the XSD we will create a
Windows Forms project and generate a .NET type form the downloaded XSD. After opening up
Microsft.Search.Query.xsd, go to the tools menu and select the XSD menu item that we created in the
previous step to generate the Microsoft_Search_Query.cs file.
Add a web reference
We are going to start by adding a web reference to the search web service, by right-clicking on the
"references" node for our project in the "solution explorer" window. There we will select "Add Web
Reference", enter "http://<server_name>/_vti_bin/spsearch.asmx" in the URL textbox and then click
"Go". You may be prompted to login to the SharePoint server and you should now have a list of Methods
supported by this service. Add "SPSearch" for the "Web Reference Name" and click "Add Reference".

Page 41 of 47
Page 42 of 47

Subclass the generate proxy


To simplify things even further, we will subclass the generated proxy with our own so that we can wrap
the QueryService to hide the validation, serialization, and de-serialization of the XML passed and
returned in the Query method using our class we generated from the XSD.
Create the application to call the service
Now we simply instantiate a query class and QueryService class, and then pass the query object to the
Query method on the QueryService class.
SPSearch.QueryService search = new SPSearch.QueryService();
Microsoft_Query_Request request = new Microsoft_Query_Request();
search.Query(request);
Example using Java
Consuming the SharePoint web services from Java is not much different, the fundamental steps are the
same, generate our class from the provided XSD, generate a web services proxy, and build the
application. Most of the challenges you will face in consuming SharePoint web services from java are
with authentication and the use of DataSet's in the SharePoint web services. There are a number of Java
IDEs available to simplify working with web services, but since I primarily work with .NET these days I
will show an example using the SDK and in this case leave the choosing of an IDE to you.
Note: This example was built and tested using J2SE 6.0 Update 3

Page 42 of 47
Page 43 of 47

Java SharePoint Sample Project Directory and Root Files


The full project and generated files are included along with couple of batch files to build and run the
sample. You will need to modify "xjc-build.bat" and "build-run.bat" with the home directory for your
JDK bin folder to run this, and edit wsspsample/Main.java with your server settings (endpoint, username,
and password) before building and running.
Import the Service WSDL
I start by retrieving the WSDL from my SharePoint server to my development machine for a couple
reasons. We will need to modify any WSDL that uses ADO.NET Data Sets, so as to work properly with
the tools. Also, access to the WSDL on the SharePoint server typically requires authentication and the
Java generated proxy requires the WSDL in the constructor, making authentication a bit of problem for
me.
Retrieve the Search WSDL
For Windows SharePoint Services 3.0 search service open up Internet Explorer and navigate to Error!
Hyperlink reference not valid. then from File|Save As..., save the page to the working directory as
spsearch.wsdl. If you are working with MOSS 2007 then you will use Error! Hyperlink reference not
valid.
Modify the Search WSDL
The QueryEx method as well as the MOSS 2007 GetSearchMetaData method returns ADO.NET Data
Sets. An ADO.NET Data Set is dynamically bound and is represented in WSDL with a cyclic reference to
the WSDL schema attribute, which causes some problems for us with the JAXB wsimport tool. I found
some workarounds that worked well with previous versions of the Java JDK, but these did not work with
the version I was using. Instead I chose to modify the WSDL as follows by opening it up in notepad and
searching for instances of "s:schema" to modify where it was used as a ref in a schema "element"
element, and remove the cyclic reference and leaving the schema "any" element.
<s:sequence>
<s:element ref="s:schema"/>
<s:any/>
</s:sequence>
Was change to the following:
<s:sequence>
<s:any minOccurs="0" maxOccurs="unbounded"/>
</s:sequence>
Import the WSDL

Page 43 of 47
Page 44 of 47

Now that we have our WSDL locally and it has been modified, we can use JAXB wsimport.exe tool to
generate the proxy classes.
wsimport -p wsspsample.webref.spsearch -keep spsearch.wsdl
wsimport -p wsspsample.webref.search -keep search.wsdl
We use the -keep flag with the import to keep the java code so that we can tweak the generated code for
our application. The tools generate code with an absolute path, so if you are planning on moving the
application to a different directory and storing the WSDL with the application we will need to modify
"webref\search\QueryService.java" url and build it ourselves. To do this we simply remove the absolute
path to the WSDL and use a relative path instead.
url = new URL("file:search.wsdl");
Generate Request Response Classes
To generate the Request and Response classes you are going to need to use the four "Microsoft.Search"
XSDs that I have created and the JAXB xjc.exe tool. In the following we simply suppress generation of
package level annotation and specify a target package, and the tool creates our classes for us.
xjc -npa -p wsspsample.xom.query -d . Microsoft.Search.Query.xsd
xjc -npa -p wsspsample.xom.response -d . Microsoft.Search.Response.xsd
Use the Generated Classes
We have an class representation of the Query and Response packets passed to and returned form the
QueryService Query method, as well as a Query service proxy. Now it's time to put that to use in an
application. The first thing we need to do is create a QueryService instance, the constructor for this object
will go and retrieve the local copy of our WSDL and load settings. From the QueryService instance we
retrieve a QueryServiceSoap instance via the getQueryServiceSoap method. Note that you will need to
hang on to and use the QueryServiceSoap reference as we do with the qsp variable, since the
getQueryServiceSoap method seems to return a new instance. We can then modify the endpoint address
here to something other than what is contained in the WSDL to make our application more dynamic
allowing it to connect to other SharePoint sites and SubSites other than that set in the WSDL.
QueryService qs = new QueryService();
QueryServiceSoap qsp = qs.getQueryServiceSoap();

BindingProvider bp = (BindingProvider)qsp;
//bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "Administrator");
//bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "pass@word1");
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"http://barbie/_vti_bin/spsearch.asmx");
Now we create methods to serialize the query and deserlialize the response packets.
public static String SerializeQuery(QueryPacket qp)
{
try
{
JAXBContext jc =JAXBContext.newInstance("wsspsample.xom.query");
Marshaller ma = jc.createMarshaller();
ma.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);
ByteArrayOutputStream os = new ByteArrayOutputStream();
ma.marshal(qp, os);
return os.toString();
}
catch(JAXBException ex)
{
return "";
}
}
public static ResponsePacket DeserializeResponse(String s)
{
Page 44 of 47
Page 45 of 47

try
{
JAXBContext jc = JAXBContext.newInstance("wsspsample.xom.response");
Unmarshaller um = jc.createUnmarshaller();
StreamSource source = new StreamSource(new StringReader(s));
return (ResponsePacket)um.unmarshal(source);
}
catch (JAXBException ex)
{
return new ResponsePacket();
}
}
From here we simply create a QueryPacket and necessary classes, set our values and call the service.
// Create a Search Query Packet Object
QueryPacket qp = new QueryPacket();
QueryType qt = new QueryType();
ContextType ct = new ContextType();
QueryTextType ctt = new QueryTextType();

ct.setQueryText(ctt);
qt.setContext(ct);
qp.setQuery(qt);

// Set search values


ctt.setValue("sharepoint");
ctt.setType("STRING"); //This is the default - not necessary
ctt.setLanguage("en-us"); //This is the default - not necessary

// Call the web service query


String sResponse = qsp.query(SerializeQuery(qp));

// Deserialize the response


ResponsePacket resp = DeserializeResponse(sResponse);
Build and Run the Application
We have our generated web services proxy and object model for query request and response, as well as
the application that leverages them, now we simply need to cross our fingers, build, run, and test this. You
will need a SharePoint server setup and will want to set the correct endpoint address used in Main.java to
your test SharePoint server as well as the credentials if necessary.
REST API Framework for SharePoint – Built on ASP.NET MVC
Some of the major web 2.0 sites like facebook and twitter are providing REST based API’s to interact
with their services, if your not familiar with Representational State Transfer (REST), then now might
be the perfect time for you to come up to speed because it seems that Microsoft is planning on
incorporating more REST features in .NET 4, we already have some REST support in the current
generation of tools.
The basic idea of REST is to use the existing infrastructure that the web already provides, we have
HTTP verbs such as GET, POST, DELETE and PUT, which map pretty well to the CRUD model we
deal with often. The web provides us with a simple error handling model, we all understand 404, 501
and 403 error codes (file not found, server error, unauthorised access). The final building block is the
URL itself, we can create descriptive URL’s such that any user can infer it’s intent just by looking at it,
while some may disagree with my summation, I think all of these elements together define what REST
is.
If we contrast all of this with the world of SOAP and webservices, we soon realise that the
webservices/SOAP model has been over-engineered. Do we really need to re-invent error codes and
Page 45 of 47
Page 46 of 47

the calling conventions that already sit on top of the web, do we need all this SOAP overhead, one
end-point for a raft of operations? Of course there will still be a place for traditional webservices, I’m
not saying they don’t work or are going away, they clearly work and will be around for a while.
The webforms model of ASP.NET hasn’t really made it easy to create REST services, it was never
really designed for it, however the ASP.NET framework has made developing REST’ful services a lot
easier.
The first feature that the MVC framework offers is the flexibility of offering a URL routing engine, so
that it is possible to easily create nice URL’s, but more than that, the way MVC uses the convention of
{controller}/{action}/{parameter} you end up with code that without much effort becomes very REST
like.
The second feature that MVC offers is the way each action on a controller returns an ActionResult, the
framework provides inherited result classes such as the JsonResult and ContentResult, in effect the
one action can return multiple payloads of data (in this case either a JSON view or an XML view).
While not strictly fitting to the REST definition, most modern REST API’s return data in a format that
is most easiest to work with which is increasing becoming JSON for AJAX/Mashable operations.

With this background we can now focus our attention on SharePoint, currently there are two ways to
work with the data stored:
• Web services
• Object Model
I’ve already touched on what the limitations of the web services are, the SharePoint object model
really only concerns us if our code is working inside SharePoint (i.e. on the same machine/s as
SharePoint).

The Benefits to SharePoint of a REST API


• Enterprise mash-ability – the web is becoming more and more useful, one reason is that its now
easier to mash together applications, look at any application that makes use of virtual earth or
Google earth, flickr, twitter, live services etc. Imagine having this flexibility in your organisation,
if your organisation has really embraced SharePoint then most likely it contains data that could be
mashed into other systems, this REST framework is about exposing that data more easily.
• It still fits with an organisations Service Oriented Architecture (SOA) in most cases. A lot of
people feel strongly that SharePoint isn’t the single source of truth for data, that may be the case,
but SharePoint is a tool that does aggregate data and adds value to it (a user might create a list
with BDC data with additional columns describing some business function), this framework is
designed to make this data more accessible to an organisation trying to construct some form of
SOA.
The URL Format
A REST API that sits over the object model would provide the best of both options, we could craft a
simple URL that returned the items that we are after such as:

http://mashserver/Site/ -- returns all sites


http://mashserver/Site/all/ -- same as above
http://mashserver/Site/get/{guid-id} -- returns the selected site
http://mashserver/List/ --returns all lists that the user has permissions for
http://mashserver/List/forsite/{site-guid-id} -- returns all the lists for the given site id
http://mashserver/ListItems/get/{list-guid-id} -- returns all the items in the list,
http://mashserver/BDC/ --Return all the BDC applications
http://mashserver/Permission/site/{site-guid} --Return objects representing the security ACL’s on the
given object

The REST API should expand across all areas of the SharePoint system. Each action should be
decorated with an accepted verb type attribute which MVC provides.
Page 46 of 47
Page 47 of 47

The Return Values

We could build a HybridResult that looks at the HTTP headers to determine the accepted input and
then either return JSON or XML:

In fact Omar has already provided a nice starting platform.

This HybridResult can also be smart enough to return a 404 if the object we are trying to serialize is
null. If we get any security exceptions we can set the return status code to 403, again the MVC
provides a nice mechanism to support this via it’s Error Handling attribute.

Problems
• Do we build our own object model, reinvent the wheel?
I think the answer is yes, we can’t serialize the SharePoint object model to our needs as a REST API,
in some cases we want to return properties in a form that would be easy to use from JavaScript. We
often don’t want to return the whole object graph, if you ask for all the lists, you really don’t want to
have a list object returned will a collection of list items. By using the new language features in .NET
3.5 we can build extension methods that provide a neat way to convert the existing Object Model
entities to those created by the MVC framework.
• Security – The double hop issue
Since the API is going to make heavy use of the object model, it’s going to have the same limitations
as the object model, i.e. the API web sites will need to live on the same server as SharePoint unless the
double hop authentication issue is taken care of via the use of Kerberos, which is a likely event in
most larger organisation.

Features - Thoughts?

So what do you think? Is a REST API for SharePoint something that would be useful? I’ve already
started developing some proof of concept prototypes which I’ve included on the project’s Codeplex
site: http://www.codeplex.com/REST4SharePoint so please leave any feedback there.

Page 47 of 47