Showing posts with label webservice. Show all posts
Showing posts with label webservice. Show all posts

Monday, June 11, 2012

Accessing the SharePoint user profile service from BizTalk


I have a client scenario where weird 3rd party system 1, sends me an update of some information, from time to time, about a user, this information needs to be instantly replicated into SharePoint.

I could use BCS but it’s not instant…  It’s coming to me via BizTalk, so I have it in near real time, so 

I can update SharePoint can’t I??… well yes it seems you can…

There is the web service that SharePoint quite nicely exposes:

It has many methods one of these is: ModifyUserPropertyByAccountName

It’s a one way send in BizTalk. 

When you add a reference, you need to add a generated item, that consumes a WCF Service.

You will get 2 schema s an orchestration and a port binding, the schema s are useful, the orchestration you can choose to use it or not, it contains a bunch of multi-part message types,  and a massive port for every single method.

The port is useful, because it contains the operations, you will need to use when you create the port, so one port can have many operations to the same web service, they give you the binding for this port, which is very nice, I suggest you use it.

Here is where all the nice stuff ends, and the really interesting stuff begins. If you use this, it does not work. 

You may get:

Error details: System.ServiceModel.FaultException: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Server was unable to process request. ---&gt; Invalid String Value: Input must match string data type.</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>

This made no sense to me, as I was sending a string, and updating a string…..

If you look at the schema for the message:



value is defined as xs:anyType, which means you can put anything in here, which is correct, I want to, a string, a datetime, a int. So the schema is flexible…

The wsdl is very vague:

      <s:complexType name="ValueData">
        <s:sequence>
          <s:element minOccurs="0" maxOccurs="1" name="Value" />
        </s:sequence>
      </s:complexType>

The value is does not specify xs:anytype however because it does not specify a type BizTalk interprets this, bad sharepoint.

However it does not go far enough… and hence it is a real let down when you have gotten past the authentication issue to find this. See my other post to fix this.

If you call the method from .net code, it works… however to find out why it works, you look at the xml that this call generates:

<ValueData>
   <Value xsi:type="xsd:dateTime">2012-06-25T10:01:17.486123+10:00</Value>   </ValueData>

The “value”  has an uppercase V, BizTalk puts is with a lower case V.  so that’s the first fix.

The next problem: xsi:type ??

It’s not even in the schema, it’s not in the wsdl.  I try and try and try to get it in to the schema, it’s not going to happen.

I managed to add an attribute to the value, called type, however it’s coming up as:

<ns0:Value ns0:type

Now the values are being set in SharePoint, all to NULL because it cannot interpret the type.

Now I know what I need to make the message look like, I have BizTalk pipelines… I can touch up the message before I send it to SharePoint.

So I go and touch up the message and the thing works perfectly. !!

I can now communicate from BizTalk to SharePoint, to update the user profiles.

My port looked like this:



Tuesday, May 8, 2012

Accessing an authenticated web service using BizTalk and impersonation


I need to access the SharePoint user profile service.

SharePoint quite nicely exposes:  http://{Server}/_vti_bin/userprofileservice.asmx

It is authenticated, quite rightly so, however the user I am accessing it with has permissions, however it still asks for username and password.

I was getting this error:

The adapter failed to transmit message going to send port "WcfSendPort_UserProfileServiceSoapOneWay" with URL "http://{Server}/_vti_bin/userprofileservice.asmx". It will be retransmitted after the retry interval specified for this Send Port. Details:"System.ServiceModel.FaultException: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Server was unable to process request. ---&gt; System.ServiceModel.EndpointNotFoundException</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>

Server was unable to process request. System.ServiceModel.EndpointNotFoundException

Not much help to me…

After some searching I found I needed to use impersonation.

The main reason was from .net I can simply do:
WSService.Credentials = System.Net.CredentialCache.DefaultCredentials;

Now the current user is impersonated and if they have permissions it works. GREAT.

I’m in BizTalk, and I’m on the WCF port…

The port is using wcf-basichttp as the protocol, and it should be able to just I have no idea how.

Well the solution I found is rather simple.

Use a wcf-custom port.  

Setup the basic-httpbinding.

First of all set the transport to client credential type ntlm 

 













Then flip over to Behavior

It will be blank.  Right click end point behavior: 






Select add extension.

Add client credentials and configure like so:















 After doing this my error went away.

Saturday, July 30, 2011

Encoded Multi Part Messages to SOAP adapter

I had one of those old/non conforming to the standards web service of kinds I needed to call.
The ones you really hate, and wish they’d just upgrade them to WCF... but hey thats 90% of integration, old rotten systems... so I persisted.

It did accept xml messages, however was very fussy as it seemed to employ the good old, no xml translator, the one that is more of a text base, string manipulation xml decoder, where if you send quite valid xml, it will fail because they didn’t support it.
This kind of set up is... sadly... quite common....
It would not handle xml tags that had no content, but had a closing tag.

EG: <salary currency="en-AU"></salary>
It needed to have them encoded differently:
<salary currency="en-AU"/>
Now both of these examples are valid xml, however good old string parser went the easy route and didn’t cater for an end tag.
The problem is that you can’t exactly tell biztalk to not put the end tag, it’s going to put xml, valid xml, and thats what it does....
Further more... it also complained about white space in my xml message.... ??? you say???
<salary currency=""><salary> <standout logoid="”1111"><standout>
The white space it didn’t like was between the tags, <salary>[--- white space ---]<standout>

Now how on earth do you cater for this?

A custom pipeline component to the rescue, just before it sends the message I would “FixUP” the xml by removing the end tags, and white space between tags, using my old favourite, c#.net .
So I go to the trouble of making a custom pipeline component, hook it up to a custom send pipeline, and then attach the pipeline to the send port.

BANG, nothing happens... it stil fails for the same reason.

At this point I’m a little annoyed, and more p’d off than i’d care to mention.
I spend the next hour trying to figure out why......

Firstly the web service is a SOAP web service, I have to use the SOAP adapter because it’s a multipart message, I check with Yossi. http://blog.sabratech.co.uk/2009/08/biztalk-wcf-adapter-and-multipart.html to discover that even if I went to WCF and fudged a wcf-http port to work it would not make much difference.

I then try and pump the message out to the file system, using a send port in the orchestration. I get a message, with only the first part. It throws me for a second, then I realise that the FILE adapter does not support multi part messages. Weird, considering all messages are multi part messages, most with one part, but I prevail.

How do I see what is going to the adapter? I really need to see the message, I mean I have tested by component, and it is good, it works and does the trick, its .net, so I of course have a .TEST project to test it...

How... Ah..ha... You can stop the send port, not unenlist it, but stop it, the message will still go to the port however sit there waiting for you.

I can then see the message from the admin console, ALL parts of the message, a much better way to debug messages BTW, I notice the message part has been encoded, the multi part message takes two strings, the second of which is my xml message. So the message is wrapped in a <string> tag, with the contents.... no longer in XML format, they are html encoded. My lovely <salary> tag is now a horrid, & lt;Salary& gt; the xml is hardly readable.... I cringe, it’s destroyed my lovely xml...

Now I can see what’s going on, before it even gets to my custom pipeline, my xml is encoded, therefor my pipeline which is looking for xml, does not find any, and does not work.... UGH!

Interestingly when I assign the value of the xml in the outbound message, I do it from a message assignment shape, I have the xml in my grasp...
I do a cheeky thing in BizTalk, turn the message into an xml document, which I can turn into text. Luckily I wrote the pipeline by using a separate class for the tagging and white space cleaning. So I can call the methods from the message assignment shape, and I process the xml, clean and massage it.

I then set the xml document back up by loading the NEW xml into to, and then set the value of the parameter of the outbound message to the xmldocument.

The message is now encoded before it goes to the port. I send the message to the port and wolla, response message, in xml... that tells me it worked.

This is a bit of a hack and a workaround, it does work, however I would have preferred the pipeline to work.

I do note with interest that only the SOAP adapter is able to process this multipart message, because it’s an OLD soap web service, I did hear of talk of scrapping the SOAP adapter, however multipart messages are VERY common on soap web services, and this would be foolish to scrap it. I’d like to see support for multi part messages in the WCF set of adapters, with more backwards compatible support, so I don’t have to use an out dated SOAP adapter.