Thursday 26 November 2009

Exposing the SAP Netweaver CE 7.1 BPM Universal Worklist (UWL) through an iView and the Object Tag Viewer Web Part in SharePoint 2007

SAP iViews are one of many mechanisms by which you can surface SAP content into a SharePoint site. This post describes how you can show the SAP Universal Worklist (UWL) in SharePoint through a custom web part called the Object Tag Page Viewer.

As desribed in an MS white paper ( http://download.microsoft.com/download/B/F/2/BF2C3AAD-BC64-496C-B3BC-72ADD9617E2C/iView%20Integration%20with%20Microsoft%20Office%20SharePoint%20Server.pdf):

"There are scenarios where an end user would require logging in to SAP GUI or SAP Portal to perform some of their commonly performed operations. It would be convenient if these operations were performed from a portal like Microsoft Office SharePoint Server Portal (MOSS) which an end user might be using more frequently. In such scenarios the best point of integration is to display SAP iViews or Web Dynpro iViews in MOSS. MOSS out of the box provides two web parts that can be used for displaying pages from portals/web sites outside MOSS. These are Page Viewer Web Part and iView Web Part. When configuring SAP iView or Web Dynpro iViews, these web parts can go in to an infinite refresh loop with some iViews. In order to overcome this issue, there is a need to develop a custom web part that would display the SAP iView. The Object Tag Page Viewer Web Part is an approach that allows MOSS portals to display these iViews. "

While the document above covers the creation of the custom web part, there are a few issues with it:

  • a) It doesn't cover how you set up or consume something like the SAP UWL (The UWL is basically the same thing as the Task list in SharePoint)
  • b) The code in the whitepaper is not complete.

The Object Tag Page Viewer Web Part (Code)

using System;
using System.Runtime.InteropServices;
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.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.ComponentModel;

namespace Microsoft
{
///
/// Created as per pdf Document "SAP iView Integration with Microsoft Office SharePoint 2007"
///

[Guid("a9c26185-1970-4f29-b45c-edad343938c1")]
public class ObjectTagPageViewer : System.Web.UI.WebControls.WebParts.WebPart
{
const int heightWidth = 150;

#region Properties
/// /// The URL to display in the Object Tag ///
private string pageUrl = "http://";

[Personalizable(), WebBrowsable(true), Browsable(true), Category("Custom Property"), DefaultValue("http://"), WebPartStorage(Storage.Personal),
FriendlyName("Page Url"), Description("Default page URL such as http://www.live.com")]
public string PageUrl { get { return pageUrl; } set { pageUrl = value; } }

#endregion

///
///
///

///
protected override void OnPreRender(EventArgs e)
{
if (base.Height.IsEmpty)
{
base.Height = heightWidth;
}
base.OnPreRender(e);
}

protected override void Render(HtmlTextWriter output)
{
if (String.Compare(pageUrl, "http://") == 0 String.IsNullOrEmpty(pageUrl))
{
output.WriteBreak();
output.WriteLine(@"To link to content, <a id="'ObjectTagPageViewer_" href="javascript:MSOTlPn_ShowToolPane2Wrapper("> output.WriteBreak();
}
else
{
if (Uri.IsWellFormedUriString(pageUrl, UriKind.Absolute))
{
string objectTagID = "outputObject_" + base.UniqueID;
output.AddAttribute(HtmlTextWriterAttribute.Id, objectTagID, false);
output.AddAttribute(HtmlTextWriterAttribute.Name, objectTagID, false);
output.AddAttribute(HtmlTextWriterAttribute.Width, "100%", false);
output.AddAttribute(HtmlTextWriterAttribute.Height, "100%", false);
output.AddAttribute(HtmlTextWriterAttribute.Type, "text/html", false);
output.AddAttribute("data", pageUrl, false);
output.RenderBeginTag(HtmlTextWriterTag.Object);
output.RenderEndTag();
}
else
{
output.WriteBreak();
output.WriteLine("Please enter a valid Absolute Page Url ");
output.WriteBreak();

}

}
}

public ObjectTagPageViewer()
{
}

}
}

Setup of iView Web Part to show the SAP UWL

  1. Go to http://insert_ce_server_name_here/irj/portal and log in.
  2. Go to Content Administration -> Portal Content -> Content Provided by SAP -> End User Content -> Standard Portal Users -> iViews -> com.sap.netweaver.bc.uwl.iviews -> Universal Worklist
  3. Right Click - > Preview
  4. Use the url that shows in the new preview window and put it into an Object Tag Page Viewer Web Part that you’ve added to a SharePoint Web Part page (as per the Microsoft Whitepaper)
  5. Et voila! SAP UWL now shows in SharePoint. Clicking on tasks opens them up into another window - from where the user can action the task.
  6. Tasks now open up in a new window for actioning:

Thursday 19 November 2009

Deploying SharePoint 2007 Custom Content Types using Inheritance with a SharePoint Feature

I had the following question sent to me this morning regarding the creation of custom content types:

"I need to create custom content types in MOSS 2007 and want to know the best way to do it. I want to achive the inheritance such as: My Core Content Type --- > Generic Content Type -- > News Content Type"

You will find that Microsoft themselves use a feature as the mechanism to deploy all of the out of the box (OOB) content types. You can see this file at:
"C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\FEATURES\ctypes\ctypeswss.xml".

In fact, the feature.xml file that Microsoft uses is in the same directory. This uses a standard schema, which can be found on MSDN here http://msdn.microsoft.com/en-us/library/ms463449.aspx

Which brings me to the content type inheritance part of the question.

The critical part to understand when creating the feature is that inheritance in content types is defined by the Ctype ID. If you go to the Content Type Gallery (for your site/site collection) and create a new content type, you can see this ctype in the URL when you hover over the name of your new content type in the gallery list. For example, when I click on the content type I just created, the link was to this location:
http://servername/_layouts/ManageContentType.aspx?ctype=0x0100E00AAE6F9A33274BBC67EACB89D61FFA&Source=%2F%5Flayouts%2Fmngctype%2Easpx

When I create a new content type that inherits from the other content type, then I just append a 01 to it and it inherits from the parent type. i.e. the Content Type Id is
ctype=0x0100E00AAE6F9A33274BBC67EACB89D61FFA01
A "grandchild" of the parent type would be
ctype=0x0100E00AAE6F9A33274BBC67EACB89D61FFA0101
and so on.



In summary, to answer the question:

  1. Create a feature to deploy your content types (using WSPBuilder or your preferred tool).
  2. In the elements file, specify your content type id (ctype) and fields which should be displayed.
  3. Give the wsp file to SharePoint administrators to Deploy the file.
  4. Done!
Additional Notes/References
  1. Another option which allows more control and full programmatic flexibility would be to create a feature receiver which then allows you to run code against the SharePoint object model to perform additional checks in the OnFeatureActivated/OnFeatureInstalled event
  2. As a best practice, Content types should not be modified by a feature once they have been installed - as manual changes to the content type may be overwritten.
  3. One of the most illuminating articles on this topic can be found here:
    http://blogs.msdn.com/eigilm/archive/2007/09/04/inherit-content-types.aspx

Tuesday 17 November 2009

Where to find the SAP Universal Worklist (UWL) API jar files (bc.uwl.service.api_api.jar, bc.uwl.service.api_core.jar, com.sap.security.api.jar)

Apparently with Netweaver Developer Studio (NWDS) 7.0, the UWL API files for accessing the Universal Worklist in SAP were included with the install. However, in NWDS 7.1, it appears that the following files are no longer included:

  • bc.uwl.service.api_api.jar
  • bc.uwl.service.api_core.jar
  • com.sap.security.api.jar

To obtain these files, you need to go to the SAP patches site at http://service.sap.com/patches.

Then navigate to:

"Support Packages and Patches - Entry by Application Group" ->
"SAP Netweaver" ->
"SAP Netweaver" (yes the same menu item twice) ->
"SAP EHP1 FOR SAP NW CE 7.1" ->
"Entry by Component" ->
"BPM Portal Integration" ->
"UWL COLL PROCESS ENGINE 7.11" ->
Download one of the patch files e.g. UWLJWF03_0-20002656.SCA


Then once downloaded, you can just import the SCA file into your project through Netweaver Developer studio or you can rename the file to a zip and extract the jar files you need.

Thursday 12 November 2009

WCF Fix-The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'NTLM'.

I thought I'd done a post on this error previously, but I double checked google and I obviously hadn't.

The Problem
When calling WSS / SharePoint web services (such as Lists.asmx) via WCF, you will normally get this error if you leave the settings as configured by the “Add Service Reference Wizard” :

“The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'NTLM'.”

The Solution

You must specify a non-anonymous impersonation level for your ClientCredentials. Just specifying a username and password for your WCF Service reference's ClientCredentials.UserName.UserName and ClientCredentials.UserName.Password is not sufficient to resolve the problem.

In particular (When SharePoint server is on different domain):

ServiceReference1.ListsSoapClient client = new ServiceReference1.ListsSoapClient();
client.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("username", "password", "domain");
client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Identification;
client.GetListCollection();


Of course, when on same domain, don’t have to pass in the Windows.ClientCredential information. You can also set the above values in app.config configuration elements rather than code, but I won't cover that here.

You can use (with descending levels of security):
System.Security.Principal.TokenImpersonationLevel.Identification
System.Security.Principal.TokenImpersonationLevel.Impersonation
System.Security.Principal.TokenImpersonationLevel.Delegation

Details on these impersonation levels can be found at: http://msdn.microsoft.com/en-us/library/system.security.principal.tokenimpersonationlevel.aspx

Config Changes


<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="ListsSoap">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
<client>
<endpoint address="http://servername/_vti_bin/Lists.asmx"
binding="basicHttpBinding" bindingConfiguration="ListsSoap"
contract="ServiceReference1.ListsSoap" name="ListsSoap1" />
</client>
</system.serviceModel>
</configuration>