Solved

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

Posted on 2004-08-25
9
498 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
  • 5
  • 4
9 Comments
 
LVL 26

Expert Comment

by:rdcpro
Comment Utility
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
Comment Utility
When I try that, VB .NET says:
"Use elements (not attributes) for fields/paramaters"
0
 

Author Comment

by:AlJeek
Comment Utility
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
 
LVL 26

Expert Comment

by:rdcpro
Comment Utility
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:AlJeek
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Thanks a lot Mike, will give it a go!

Cheers,
Aled.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

SASS allows you to treat your CSS code in a more OOP way. Let's have a look on how you can structure your code in order for it to be easily maintained and reused.
JavaScript has plenty of pieces of code people often just copy/paste from somewhere but never quite fully understand. Self-Executing functions are just one good example that I'll try to demystify here.
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
The viewer will learn how to dynamically set the form action using jQuery.

772 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now