Winsmarts.com

Microsoft MVP

MVP Logo

Awarded the Microsoft MVP Award.

Hosted By

blah!bLaH!BLOG!!

Using a WCF Client to talk to SharePoint OOTB Web Services

Posted on 7/8/2008 @ 12:08 AM in #Sharepoint | 4 comments | 3371 views

First of all - OOTB SP Web services suck! There I said it. I know this will make many raise their eyebrows, but sure bring on your arguments. I think WCF is so darned superior to ASMX's that you'd be crazy to not use WCF instead of asmx's.

However, certain web services are darned hard to write ;-), example - ExcelService.asmx. So sometimes you may have a situation where you would want to use an OOTB Web Service with a WCF client. This takes some interesting adjustments.

The issue is, after you "right click add service reference", WCF gives you a clean proxy - divorced from authentication mechanisms. So, I did "Add Service Reference" to ExcelService.asmx, and wrote the following C# code,

   1:  ExcelService.ExcelServiceSoapClient client = new ExcelSheetFun.ExcelService.ExcelServiceSoapClient();
   2:  
   3:   
   4:  ExcelService.Status[] outStatus;
   5:  string sessionID = client.OpenWorkbook(docLibAddress + excelFileName, "en-US", "en-US", out outStatus);
   6:  ExcelService.RangeCoordinates rc = new ExcelSheetFun.ExcelService.RangeCoordinates();
   7:  rc.Column = 2;
   8:  rc.Row = 3;
   9:  rc.Height = 3;
  10:  rc.Width = 1;
  11:  outStatus = client.Calculate(sessionID, "SimpleAddition", rc);
  12:  object o = client.GetCell(sessionID, "SimpleAddition", 4, 1, false, out outStatus);

Only to be rudely shown the following error -

 

The exception is a MessageSecurityException, and it says ---

"The Http request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'NTLM'.

Okay so, ExcelService expects NTLM (or Kerberos). To make it work, you need to make 2 adjustments -

a) Change your .config to the following under the security for your basicHttpBinding -

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <configuration>
   3:    <system.serviceModel>
   4:      <bindings>
   5:        <basicHttpBinding>
   6:          <binding name="ExcelServiceSoap" SettingsRemovedForBrevity>
   7:            <readerQuotas SettingsRemovedForBrevity/>
   8:            <security mode="TransportCredentialOnly">
   9:              <transport clientCredentialType="Ntlm" proxyCredentialType="Ntlm" realm=""/>
  10:              <message clientCredentialType="UserName" algorithmSuite="Default" />
  11:            </security>
  12:          </binding>
  13:        </basicHttpBinding>
  14:      </bindings>
  15:      <client>
  16:        <endpoint address="http://smw2k8/_vti_bin/ExcelService.asmx"
  17:            binding="basicHttpBinding" bindingConfiguration="ExcelServiceSoap"
  18:            contract="ExcelService.ExcelServiceSoap" name="ExcelServiceSoap" />
  19:      </client>
  20:    </system.serviceModel>
  21:  </configuration>

And, add the following line to your C# code (shown in bold red)

   1:  ExcelService.ExcelServiceSoapClient client = new ExcelSheetFun.ExcelService.ExcelServiceSoapClient();
   2:  client.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
   3:   
   4:  ExcelService.Status[] outStatus;
   5:  string sessionID = client.OpenWorkbook(docLibAddress + excelFileName, "en-US", "en-US", out outStatus);
   6:  ExcelService.RangeCoordinates rc = new ExcelSheetFun.ExcelService.RangeCoordinates();
   7:  rc.Column = 2;
   8:  rc.Row = 3;
   9:  rc.Height = 3;
  10:  rc.Width = 1;
  11:  outStatus = client.Calculate(sessionID, "SimpleAddition", rc);
  12:  object o = client.GetCell(sessionID, "SimpleAddition", 4, 1, false, out outStatus);
  13:   

If you wish to specify alternate credentials, you may simply do so using the following code:

 

   1:  client.ClientCredentials.Windows.ClientCredential = 
   2:      new System.Net.NetworkCredential("userName", "password", "domain");

 

What is cool about WCF now is that, if (which it doesn't), your server side ASMX (which you didn't write), supported alternate credentials (like any good WCF endpoint would have), you could have used ANY authentication mechanism. Heck, it could have used any communication mechanism as well. But since you are stuck with asmx's that you didn't write - you're outta luck. But atleast you can use them as asmx's over basicHttpBinding.

Anyone still wanna argue that ASMX's suck? Go on .. tell me why you love asmx's over WCF. I'll give ya a starter, asmx's don't need all these twiddly configurations, but you get so much more flexibility with WCF, so you gotta live with it's twiddliness.


On 7/16/2008 4:14:00 PM Steve Clements said ..
As i think i heard from you we will all just be xml editors and tweakers soon!! I agree with that WCF is more superior...who wouldn't, but this post certainly addressed a need. Perhaps MOSS v.Next will be WCF services with AJAX dripping from the UI!!

On 7/16/2008 4:47:50 PM Steve Clements said ..
Although I should say it doesnt seem to work for all...
using (OCUserProfileService.UserProfileServiceSoapClient service =
new TestAndDestroy.OCUserProfileService.UserProfileServiceSoapClient(GetWcfBinding())) { service.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation; PropertyData[] properties = service.GetUserProfileByName("domain\\user.name"); foreach (PropertyData p in properties) {
Console.WriteLine(p.Name);
Console.WriteLine(p.Values);
} produces....
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://microsoft.com/webservices/SharePointPortalServer/UserProfileService:GetUserProfileByNameResponse. The InnerException message was 'Error in line 1 position 392. 'Element' 'IsPrivacyChanged' from namespace 'http://microsoft.com/webservices/SharePointPortalServer/UserProfileService' is not expected. Expecting element 'Name | Privacy'.'. Please see InnerException for more details. any ideas???

On 7/25/2008 5:03:57 PM Brock said ..
Awesome -- works great !!! But -- boy are you right -- those OOTB webservices totally blow. I am going to be deploy my own WCF services (using the VPP mangler) using the SP object model to get some decent services (I hope).

On 7/25/2008 11:58:32 PM Sahil Malik said ..
Brock - are you the Brock I know? (Brock A?)

Please post your comments:


Your feedback will be submitted for moderation, and will appear after it is approved.

Name:  
Email (optional): Your email address will not be posted.
URL (optional):
Comments: HTML will be ignored, URLs will be converted to hyperlinks  
Enter the text you see in the box:
 

Site designed and maintained by Sahil Malik | All Rights Reserved. ©2007 WinSmarts.com.