Showing posts with label SharePoint SAP Integration. Show all posts
Showing posts with label SharePoint SAP Integration. Show all posts

Tuesday, 13 July 2010

Fix for WCF Client Proxy deserialization issue (related to svcutil.exe) when referencing Non-Microsoft Services (e.g. SAP services from SharePoint) - "Unable to generate a temporary class (result=1)."

When creating a client proxy for the SAP Service Registry (so I could dynamically set endpoints for my other WCF client calls), I had the following issue today when running a unit test:

Test method DDK.UnitTest.UDDIProxyTest.GetEndPointBasicTest threw exception: System.ServiceModel.CommunicationException: There was an error in serializing body of message findServiceDefinitionsRequest: 'Unable to generate a temporary class (result=1).

error CS0030: Cannot convert type 'DDK.BusinessService.UDDIRegistrySearchProxy.classificationPair[]' to 'DDK.BusinessService.UDDIRegistrySearchProxy.classificationPair'

This error is a result of issues with .NET commandline tools wsdl.exe or svcutil.exe incorrectly creating multidimensional arrays in the strongly typed proxy class (Reference.cs), as per screenshot below:


Cause:
This problem occurs when the svcutil.exe or the Web Services Description Language Tool (Wsdl.exe) are used to generate the client information. When you publish a schema that contains nested nodes that have the maxOccurs attribute set to the "unbounded" value, these tools create multidimensional arrays in the generated datatypes.cs file. Therefore, the generated Reference.cs file contains incorrect types for the nested nodes.

The problem and fix is described in the following kb articles:
http://support.microsoft.com/kb/891386 and 
http://support.microsoft.com/kb/326790/en-us

The fix is to basically change the multi-dimensional array in the Reference.cs file related to your service reference to a single dimension.
e.g.

classificationPair[] [] 
instead becomes
classificationPair[] 

Note that you will of course need to update all parameter references in the Reference.cs file to this multi-dimensional array, not just the original declarations.
DDK

Wednesday, 2 December 2009

"The service implementation selected is invalid." when attempting to create a web service in SAP Netweaver Developer Studio

I'm currently trying to get the SAP universal worklist APIs to provide information to SharePoint via a web service (to ensure there is only a single task list for users to see). To this end, I needed to create a web service hosted on the SAP BPM server.

When attempting to create a Java Web service (e.g. a bottom up service, based on a java bean service implementation) in Netweaver Developer Studio (NWDS), you might receive the following cryptic error message:


"The service implementation selected is invalid."

It is as clear as mud - but the issue here is that the class name of the service implementation is lower case. To resolve the issue, just refactor the class with a right click on the offending java file and change the first letter to upper case. Quite painful if you ask me - they really need a better explanation than that in their user interface!


Fix it with a refactor:


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:

Friday, 18 September 2009

SAP to Microsoft .NET Integration - Fixes required to WSDL after referencing SAP BAPI WSDLs to work with .NET Service References in Visual Studio 2008

After referencing a Web Service that is based on a SAP BAPI (as opposed to a SAP Enterprise Service), you may need to save and modify the WSDL so to remove reserved words in the file. Otherwise, you will get compile-time errors from the Service Reference generated code such as:


An object reference is required for the non-static field, method, or property 'SharePointCustomLookup.CostCentreSearchService.Bapiret2.System.get'


Solution/Fix:
1. Save the WSDL from the HTTP location to your local machine (you can get this WSDL location if it is already set up from transaction /soamanager in SAP GUI). Open up the wsdl in your fave text editor.
2. Replace all instances of “System” with “SYSTEM” (To avoid conflicts with the System namespace in .NET)
3. Replace all instances of “parameters” with “parameter” so that parameters are read correctly by Visual Studio 2008.
4. Update your service reference to use the locally modified WSDL (which should have the correct endpoints to the web services on your SAP PI/ECC Server )

These modifications to the WSDL is not required for all BAPI Web Service calls - only ones which exhibit the compile-time issue.




One other important thing to note is that if your BAPI has an input parameter, then you have to instantiate the parameter AND all the lists and arrays which make up that input parameter - otherwise you won't get a return result.

e.g. For calling a Project Definition GetList BAPI, you have to instantiate parameter and the Project Definition List with a zero-sized array - otherwise you will NOT get any values back - and yet receive no error.


//You must instantiate the input parameter and any lists/arrays within that
//parameter for any results to be returned
Z_BAPI_PROJECTDEF_GETLISTClient client = new Z_BAPI_PROJECTDEF_GETLISTClient();
ProjectdefGetlist parameter = new ProjectdefGetlist();
parameter.ProjectDefinitionList = new Bapiprexp[0];
ProjectdefGetlistResponse response = client.ProjectdefGetlist(parameter);

Friday, 28 August 2009

Calling a SAP PI Web Service (using WCF bindings) from a SharePoint 2007 Workflow

There are 2 rules when calling a SAP PI web service from a SharePoint workflow:
  1. You have to use custom bindings to get authentication to work.
  2. After you've added your web service via the "Add Service" dialog, you have to copy the all of the contents under into the SharePoint web.config - as per http://blogs.msdn.com/sharepointdesigner/archive/2008/11/02/calling-a-wcf-service-from-a-sharepoint-workflow-using-visual-studio.aspx. This is because the contents of app.config are (obviously) not accessible by the SharePoint Workflow runtime - you have to use the web.config instead.

Point 1 - Custom Bindings

If you try to call a web service in SAP PI which requires credentials, none of the normal authentication methods seem to work. You will always get the following error in WCF.

The HTTP request is unauthorized with client authentication scheme 'Anonymous'.
The authentication header received from the server was 'Basic realm="XISOAPApps"




To fix this, you need to use the following custom bindings rather than the normal basicHttpBinding, like so:





<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomHttpTransportBinding">
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap11" writeEncoding="utf-8">
<readerQuotas maxDepth="10000000" maxStringContentLength="10000000"
maxArrayLength="67108864" maxBytesPerRead="65536" maxNameTableCharCount="100000" />
</textMessageEncoding>
<httpTransport authenticationScheme="Basic" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard" keepAliveEnabled="false"
proxyAuthenticationScheme="Basic" realm="XISOAPApps" useDefaultWebProxy="true" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://servername:50000/XISOAPAdapter/MessageServlet?channel=:INTEGRATION_SERVER_DPI:SOAPSenderPOCreate&version=3.0&Sender.Service=INTEGRATION_SERVER_DPI&Interface=http://zz"
binding="customBinding" bindingConfiguration="CustomHttpTransportBinding"
contract="PurchaseOrderProcessingService.PurchaseOrderProcessing_Out"
name="PurchaseOrderProcessing_OutPort" />
<endpoint address="http://servername:50000/XISOAPAdapter/MessageServlet?channel=:INTEGRATION_SERVER_DPI:SOAPSenderPORelease&version=3.0&Sender.Service=INTEGRATION_SERVER_DPI&Interface=http://zz"
binding="customBinding" bindingConfiguration="CustomHttpTransportBinding"
contract="PurchaseOrderReleaseService.PurchaseOrderRelease_Out"
name="PurchaseOrderRelease_OutPort" />
<endpoint address="http://servername:50000/XISOAPAdapter/MessageServlet?channel=:INTEGRATION_SERVER_DPI:SOAPSenderGOS_URL_CREATE&version=3.0&Sender.Service=INTEGRATION_SERVER_DPI&http://zz"
binding="customBinding" bindingConfiguration="CustomHttpTransportBinding"
contract="PurchaseOrderAttachUrlService.MI_GOS_URL_CREATE_Syn_Out"
name="MI_GOS_URL_CREATE_Syn_OutPort" />
</client>
</system.serviceModel>
</configuration>

Point 2 - Web Service Configuration Settings
(from http://blogs.msdn.com/sharepointdesigner/archive/2008/11/02/calling-a-wcf-service-from-a-sharepoint-workflow-using-visual-studio.aspx)

  1. Open web.config in VS for editing. You can find the file in the "\inetpub\wwwroot\wss\VirtualDirectories\80" directory, where 80 corresponds to the port of your SharePoint application.
  2. Copy the "System.ServiceModel" element from app.config into web.config. If you already have a "System.ServiceModel” element, you’ll need to merge the and elements in manually.
  3. To complete your changes, open a windows command window (Start/Run/cmd.exe) and type "iisreset", which will cycle the sharepoint web application, so it can pick up the web.config changes.