views:

45

answers:

4

I need to record a user's name that is using an ASP.NET web service. To do this, I created a SoapExtension that captures an incoming Soap envelope and converts it to an XDocument. The problem is I know nothing about LINQ to XML and the examples I've reviewed don't quite seem to work with the SOAP envelope.

The SOAP message looks like this:

 <?xml version="1.0" encoding="utf-8"?>
 <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" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"&gt;
   <soap:Header>
     <wsa:Action>http://www.company.net/2009/09/17/wriapp/GetConfigInfo&lt;/wsa:Action&gt;
     <wsa:MessageID>urn:uuid:da599d3d-1df5-4460-8987-8ccd75b87cfe</wsa:MessageID>
     <wsa:ReplyTo><wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous&lt;/wsa:Address&gt;&lt;/wsa:ReplyTo&gt;
     <wsa:To>urn:Company:Wri:Tracking:1.0</wsa:To>
     <wsse:Security soap:mustUnderstand="1">
       <wsu:Timestamp wsu:Id="Timestamp-efb2ad77-7822-43d9-86d6-0cbfbf0ed262">
           <wsu:Created>2010-09-07T13:31:20Z</wsu:Created>
           <wsu:Expires>2010-09-07T13:36:20Z</wsu:Expires>
       </wsu:Timestamp>
       <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="SecurityToken-c51f6c78-555b-420c-ba79-402d75f24d5e">
         <wsse:Username>[email protected]</wsse:Username>
         <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"&gt;password1&lt;/wsse:Password&gt;
         <wsse:Nonce>xO+f8fJgh8zzxPi6JJMUag==</wsse:Nonce>
         <wsu:Created>2010-09-07T13:31:20Z</wsu:Created>
       </wsse:UsernameToken>
     </wsse:Security>
   </soap:Header>
   <soap:Body>
     <GetConfigInfo xmlns="http://www.company.net/2009/09/17/wriapp" />
   </soap:Body>
 </soap:Envelope>

All I need is the contents of the Username element.

I tried this...

 var xdoc = XDocument.Parse(xml, LoadOptions.None);
 var userName = from item in xdoc.Descendants("UsernameToken")
                select new
                {
                    UserName = item.Element("UserName")
                };

... but get no results.

When I tried using "wsse:UsernameToken" and "wsse:Username" I get an exception which says that the colon is not legal.

Any tips on how to get this information?

(I know I can probably just regex the name, but if I need to grab other data at some future point then it will be more efficient this way, I think.)

+2  A: 

The part in front of the colon is a namespace, knowing this I found this answer from a similar question.

Linq to XML with Namespace

msarchet
several people had a useful answer but this was the first (according to the "oldest" sort) so it got the answer. All of them got +1.
Sailing Judo
+2  A: 

You need to create a namespace and use that. It's highly counter intuitive, but this is how it works:

XNamespace ns = "http://schemas.xmlsoap.org/soap/envelope/";
from item in xdoc.Descendants(ns + "UsernameToken")
...etc...

...and you'll have to do that for any item that has a prefix.

I think you can also use curly braces ({}) as a wrapper around the URI, like this:

from item in xdoc.Descendants("{http://schemas.xmlsoap.org/soap/envelope/}UsernameToken")

but I've never tried it.

More details here.

jvenema
+2  A: 

It's down to the namespaces for those xml elements. You need to add that to your query. I'm not at a point to try this but something along the lines of:

XNamespace wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";

 var xdoc = XDocument.Parse(xml, LoadOptions.None);
 var userName = from item in xdoc.Descendants(wsu + "UsernameToken")
                select new
                {
                    UserName = item.Element(wsu + "UserName")
                };

For more information on namespaces in LINQ to XML: http://msdn.microsoft.com/en-us/library/bb387069.aspx

Duke of Muppets
+1  A: 

You have to include the whole namespace in the LINQ:

XNamespace wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";

var xdoc = XDocument.Parse(xml, LoadOptions.None);
var userName = from item in xdoc.Descendants(wsse + "UsernameToken")
                select new
                {
                    UserName = item.Element(wsse + "UserName")
                };
eWolf