Solved

Please Help!: How do I get an attribute value from a soap message in vb .net??

Posted on 2004-08-25
9
511 Views
Last Modified: 2013-11-19
Hi all,

A soap message returned by an axis (Java/Apache) web service contains elements with attributes.

e.g.

<Values Count="3">
<Value>Hello</Value>
<Value>World</Value>
<Value>!!!</Value>
</Values>

could be part of the message.   How do I get the attribute value in vb .net?  The web service is defined by a wsdl which I need to update to show that the attribute is there, but i'm not sure how.

Part of the wsdl defining the above would be:
<xs:complexType name="Values">
  <xs:complexContent>
    <xs:restriction base="soapenc:Array">
      <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:Vallue>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

<xs:complexType name="Value">
  <xs:element name="Value" type="xs:string"/>
</xs:complexType>

How can I add the attribute to it.  VB net currently reads in Values as an array.

Thanks!
Al.
0
Comment
Question by:AlJeek
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
9 Comments
 
LVL 26

Expert Comment

by:rdcpro
ID: 11893935
The attribute goes outside of the content model for your value element:

<xs:complexType name="Value">
      <xs:sequence>
            <xs:element name="Value" type="xs:string" minOccurs="1" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:attribute name="Count" type="xs:int" use="required"/>
</xs:complexType>

Regards,
Mike Sharp
0
 

Author Comment

by:AlJeek
ID: 11894126
When I try that, VB .NET says:
"Use elements (not attributes) for fields/paramaters"
0
 

Author Comment

by:AlJeek
ID: 11894267
Incase it's relevant, our model is more like:

<xs:complexType name="Values">
  <xs:complexContent>
    <xs:restriction base="soapenc:Array">
      <attribute ref="soapenc:arrayType" wsdl:arrayType="typens:Vallue>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

<xs:complexType name="Value">
  <xs:element name="AValue1" type="typens:AValue1"/>
  <xs:element name="AValue2" type="typens:AValue2"/>
</xs:complexType>

etc.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 26

Expert Comment

by:rdcpro
ID: 11895692
Hmmm...I was afraid you'd run into that issue.  It seems to me that if you want to specify the size of the array, you'd do it like:

<Values xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="xsd:string[5]">
  <Value>Mike</Value>
  <Value>Sharp</Value>
  <Value>string</Value>
  <Value>cheese</Value>
  <Value>food</Value>
</numbers>

But SOAP 1.2 has a few more attributes for describing arrays:

  <!-- Array attributes. Needed to give the type and dimensions of an array"s contents, and the offset for partially-transmitted arrays. -->

  <xs:simpleType name="arraySizeBase" >
    <xs:annotation>
        <xs:documentation>
        A list type that allows * and non negative integers. Used as the
    base type for arraySize below.
        </xs:documentation>
      </xs:annotation>
    <xs:list>
        <xs:simpleType>
          <xs:union memberTypes="xs:nonNegativeInteger" >
              <xs:simpleType>
                <xs:restriction base="xs:token" >
                    <xs:enumeration value="*" />
                  </xs:restriction>
              </xs:simpleType>
            </xs:union>
        </xs:simpleType>
      </xs:list>
  </xs:simpleType>


  <xs:simpleType name="arraySize" >
    <xs:annotation>
        <xs:documentation>
        Pattern based restriction of the arraySizeBase list type. Used
    as the type of the arraySize attribute. Restricts asterisk ( * )
    to first list item only. Instances must contain at least an
    asterisk ( * ) or a nonNegativeInteger. May contain other
    nonNegativeIntegers as subsequent list items.
      Valid instances include;
      
        *
        1
        * 2
        2 2
        * 2 0

        </xs:documentation>
      </xs:annotation>
    <xs:restriction base="tns:arraySizeBase" >
        <xs:pattern value="(\*|(\d+))(\s+\d+)*" />
      </xs:restriction>
  </xs:simpleType>
   
  <xs:attribute name="arraySize" type="tns:arraySize" />
  <xs:attribute name="itemType" type="xs:QName" />

  <xs:attributeGroup name="arrayAttributes" >
    <xs:attribute ref="tns:arraySize" />
      <xs:attribute ref="tns:itemType" />
  </xs:attributeGroup>    
 
Maybe these will help?

Mike Sharp
0
 

Author Comment

by:AlJeek
ID: 11897037
Thanks Mike, that's very useful.

Count is an example attribute we have, but not a vital one, since I expect that clients that connect to our webservice will be able to count the array size themselves.  From what I've seen too, vb .net seems to not care if you send the size as you showed and just counts the children (we sent 0 everytime and it still counted it right).

What we do need really need however is to know how to specify attributes that have nothing to do with arrays themselves, but describe some useful information about the array or its elements.

For example, say we needed a client to specify an option.  We could send them a soap message which could include:

<Values>
  <Option index="1" optionName="A">
    <Value>Hello</Value>
    <Value>World!</Value>
  </Option>
  <Option index = "2" optionName="B">
    <Value>Whatever</Value>
    <Value>Really</Value>
  </Option>
....etc
</Values>

Again you could argue that they don't need the index if we send the options in order (and they take for granted that the first option is the first in the array).  But how would we get the optionName attribute?

We want to change the structure of the soap message given by the webservice as little as possible at the moment, so no extra parent/child elements please (although this would make more sense).

Thanks again!

Aled.
0
 
LVL 26

Accepted Solution

by:
rdcpro earned 250 total points
ID: 11897382
I don't think you can use SOAP encoding by itself for that, at least not as an array.  There is an extensibility mechanism, but I'm not that familiar with it.  I've tried to avoid soap encoding more recently in favor of a message-centric architecture.  But there may be an approach you can use that's based on the soap encoding arrayType...I've never tried it, but it sounds reasonable.  I wish I could provide a better example, however, in your case it might be better to use a Struct, rather than an array, wouldn't it?  

I've been working on a web service the last week or so that uses a SOAP extension to provide direct access to the xml stream itself, rather than try to use .NET to deserialize into an object.  I like it better, because my message is an InfoPath document that I process, update a DB and then save to a document library in Sharepoint.  But of course working with the stream itself may not work for you.

But in case it does, here are some interesting articles that discuss messaging based as opposed to RPC based web services:

http://msdn.microsoft.com/msdnmag/issues/02/02/WebServ/default.aspx
http://msdn.microsoft.com/msdnmag/issues/02/12/WebServicesDesign/default.aspx
http://msdn.microsoft.com/msdnmag/issues/03/03/WebServices/default.aspx

Regards,
Mike Sharp
0
 

Author Comment

by:AlJeek
ID: 11900729
Thanks for the info Mike.

I was afraid of that, I guess we're going to have to change the structure of the message so that an array has a parent element.  This way, we don't need attributes.

I don't want to get into direct xml access, as our customers will be writing their own clients to connect to our webservice, and we want it to be as easy as possible.

Not sure what you mean by using a structure though, how would I incorporate one into a wsdl?

Thanks,
Aled.
0
 
LVL 26

Expert Comment

by:rdcpro
ID: 11903593
A struct is a complex type, like an array.  It can have repeating members, as well.  While an array has a position accessor, you access structs by element name and/or position.  In .NET, you can deserialize directly to a struct, so the implementation details of connecting your web service to the messaging are totally hidden.  You simply create a web method that takes the struct object as it's parameter.  If you have a schema, wsdl.exe will generate stub classes that essentially do the same thing, but they're classes rather than structs.  They can be tweaked to fit, though.  Once you've got all this written, ASP.NET will autogenerate the WSDL for you.  The Microsoft Office InfoPath 2003 SDK has an excellent example of using structs for this.  It's a purchase order web service, and here's an abbreviated example (in C#, however):

The basic part of the message is a rootPO struct, defined here:

        [System.Xml.Serialization.XmlRootAttribute(ElementName="root", IsNullable=false)]
        public struct rootPO
        {
            public routingInfo routingInfo;
            public purchaseRequestPO purchaseRequest;

            [System.Xml.Serialization.XmlAnyAttributeAttribute()]
            public System.Xml.XmlAttribute[] AnyAttr;
        }
 
Skipping the routingInfo stuff, the purchaseRequestPO is:

        [System.Xml.Serialization.XmlRootAttribute(ElementName="purchaseRequest", IsNullable=false)]
        public struct purchaseRequestPO
        {
            public int number;

            [System.Xml.Serialization.XmlElementAttribute(DataType="date")]
            public System.DateTime dateOpened;

            public string chargeTo;

            public string group;

            public string name;

            public string email;

            [System.Xml.Serialization.XmlArrayItemAttribute(ElementName="item", IsNullable=false)]
            public itemPO[] list;

            public System.Single total;
        }

As you can see, it has a few public string members (exposed as properties of the purchaseRequest instance).  It also has an array, itemPO[].

It goes on from there, but the serialization attributes tell ASP.NET how to deserialize the incoming message to the rootPO object.  The web method to process a PO starts out like:

        [WebMethod]
        public bool ProcessPO(rootPO PO)
        {
            bool fValidPO = true;
            SortedList aiPartNumbers;
            string sPartNumbers;
           
            int i = 0;

            int iPartNumber;
            int iQuantityRequested;
            int iQuantityAvailable;

            string sConnect;
            string sSqlQuery;
            OleDbConnection oOleDbConn;
            OleDbCommand oOleDbCommand;
            OleDbDataReader oOleDbReader;

            try
            {
                PO.purchaseRequest.number = GetPurchaseOrderNumber(PO);
               
                // Build a hash table of requested part numbers and their associated index
                // in the product list in the PO request.
                aiPartNumbers = new SortedList();
                sPartNumbers = "";
                for (i=0; i<PO.purchaseRequest.list.Length; i++)


and goes on from here.  This might be more what you're looking for, I think.  Download the SDK, and you can run the solution (you may have to edit the sln file to point to the right server--some of the SDK samples didn't run directly from the solution without some editing--at least for me.

Regards,
Mike Sharp
0
 

Author Comment

by:AlJeek
ID: 11903805
Thanks a lot Mike, will give it a go!

Cheers,
Aled.
0

Featured Post

Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Help needed with Powershell  XML to MySQL 5 89
XSLT Display Label Name 1 42
TSQL XML Namespaces 7 54
Please Explain What Reading a Zip file Back In Means 11 79
This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
Shoutout to Emily Plummer (http://www.experts-exchange.com/members/eplummer26.html) for giving me this article! She did most of it, I just finished it up and posted it for her :)    Introduction In a previous article (http://www.experts-exchang…
The viewer will learn the benefit of using external CSS files and the relationship between class and ID selectors. Create your external css file by saving it as style.css then set up your style tags: (CODE) Reference the nav tag and set your prop…
HTML5 has deprecated a few of the older ways of showing media as well as offering up a new way to create games and animations. Audio, video, and canvas are just a few of the adjustments made between XHTML and HTML5. As we learned in our last micr…

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question