Output an XML type attribute using DataContract

AID: 1420
  • Status: Published

9550 points

Awards
  • Experts Exchange Approved
This tutorial will show you how to add an attribute to an XML stream returned from a Windows Communication Foundation (WCF) Web Service.  Some knowledge of WCF and XML is required; the code is in C#.  Below is an XML sample of an attributed XML stream comprised of an array of dynamically placed arguments.
<info xmlns="http://myns.com">
  <args>
    <arg type="firstname">
      <value>William</value>
    </arg>
    <arg type="lastname">
      <value>Campbell</value>
    </arg>
</info>
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:

Select allOpen in new window



Unfortunately, there is *no way* to get this exact piece of XML is in the current version of WCF as attributes in XML streams are not supported using DataContract!

The solution to follow uses the 'KnownType' WCF attribute to piggyback the Microsoft 'i:type' attribute.  Using the method described in this article, we can get close to the above (desired) XML as the output we get looks like this:
<info xmlns="http://myns.com" 
  xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <args>
    <arg i:type="firstname"> 
      <value>William</value>
    </arg>
    <arg i:type="lastname">
      <value>Campbell</value>
    </arg>
</info>
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:

Select allOpen in new window



Notice the difference is the addition of namespace 'i' that changes 'type' to 'i:type'.  If you can live with the 'i:' prefix, this solution is for you.

With that said, let's get under way with a sample definition of a WCF service that will use my technique.
using System;
using System.ServiceModel;
using System.ServiceModel.Web;

[ServiceContract]
[DataContractFormat]
public interface IRPCService
{
    [OperationContract]
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "/getuserxml?id={userID}")]
    info GetUserXML(String userID);
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:

Select allOpen in new window



GetUserXML is a function declaration in a .svc file.  It is a RESTful (REpresentational State Transfer) Web Service call which would be invoked like this.
http://www.experts-exchange.com/RPCService.svc/getuserxml?id=williamcampbell
                                    
1:

Select allOpen in new window



The function returns an 'info' class as 'plain' serialized XML to the caller.  Within the plain serialized XML will be the embedded attributes.  Each attribute that will appear in the serialized XML must be declared as a KnownType and have its own class implementation.  The code below shows a base class that defines two KnownTypes.
using System;
using System.Runtime.Serialization;

[DataContract(Name="arg",
    Namespace="http://myns.com")]
[KnownType(typeof(FirstNameArg))]
[KnownType(typeof(LastNameArg))]
public class BaseArg
{
    public BaseArg() { }
     [DataMember(Name="value")]
     public String Value { get;set; }
}

[DataContract(Name="firstname",
    Namespace="http://myns.com")]
public class FirstNameArg : BaseArg
{
} 

[DataContract(Name="lastname",
    Namespace="http://myns.com")]
public class LastNameArg : BaseArg
{
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:

Select allOpen in new window



The Args FirsNameArg and LastNameArg can now be used in the info class.
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

[DataContract(Name = "info", 
   Namespace = "http://myns.com")]
public class info
{
    public info()
    {
        Args = new List<BaseArg>();
    }

    public void AddArg(BaseArg arg, String value)
    {
        arg.Value = value;
        Args.Add(arg);
    }

    [DataMember(Name = "args")]
    List<BaseArg> Args { get; set; }
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:

Select allOpen in new window



The info class results in the outer tag:
<info>
</info>
                                    
1:
2:

Select allOpen in new window



info declares an array of BaseArg with a [DataMember] contract of "args" resulting in:
<info>
   <args>
   </args>
</info>
                                    
1:
2:
3:
4:

Select allOpen in new window



Each BaseArg that is added results in an <arg> tag with an i:type inside it.  The code DataContract(Name="firstname") above results in:
<info>
   <args>
        <arg i:type="firstname">
        </arg>
   </args>
</info>
                                    
1:
2:
3:
4:
5:
6:

Select allOpen in new window



The value passed to the BaseArg classes 'Value' function becomes the body of the arg:
<info>
   <args>
        <arg i:type="firstname">
          <value>William</value>
        </arg>
   </args>
</info>
                                    
1:
2:
3:
4:
5:
6:
7:

Select allOpen in new window



And so on for other args...

A simplified version of the function body for GetUserXML could be seen here:
public info GetUserXML(String userID)
{
    // lookup userID in the Database
    info exinfo = new info();

    exinfo.AddArg(new FirstNameArg(), "William");
    exinfo.AddArg(new LastNameArg(), "Campbell");

    return exinfo;
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:

Select allOpen in new window



Although not an ideal solution to the attribute problem, this tutorial will help you move forward if you are blocked by the need for dynamic XML attributes in WCF.


WilliamCampbell


References:
XML Attributes: http://www.w3schools.com/Xml/xml_attributes.asp
DataContracts: http://msdn.microsoft.com/en-us/library/ms733127.aspx
KnownType: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.knowntypeattribute.aspx
RESTful Web Services: http://www.developer.com/net/article.php/3695436
Original EE Question: http://www.experts-exchange.com/Q_24370166.html

Asked On
2009-08-31 at 07:36:48ID1420
Tags

DataContract Attribute

,

XML

,

C#

,

WCF

Topic

Web Services and WCF

Views
7166

Comments

Add your Comment

Please Sign up or Log in to comment on this article.

Join Experts Exchange Today

Gain Access to all our Tech Resources

Get personalized answers

Ask unlimited questions

Access Proven Solutions

Search 3.2 million solutions

Read In-Depth How-To Guides

1000+ articles, demos, & tips

Watch Step by Step Tutorials

Learn direct from top tech pros

And Much More!

Your complete tech resource

See Plans and Pricing

30-day free trial. Register in 60 seconds.

Loading Advertisement...

Top Web Services and WCF Experts

  1. apeter

    41,940

    0 points yesterday

    Profile
    Rank: Sage
  2. kaufmed

    37,400

    0 points yesterday

    Profile
    Rank: Genius
  3. TheLearnedOne

    25,250

    0 points yesterday

    Profile
    Rank: Savant
  4. CodeCruiser

    24,800

    0 points yesterday

    Profile
    Rank: Genius
  5. DarrenD

    19,350

    0 points yesterday

    Profile
    Rank: Sage
  6. BuggyCoder

    18,965

    0 points yesterday

    Profile
    Rank: Sage
  7. ambience

    17,400

    0 points yesterday

    Profile
    Rank: Sage
  8. rkworlds

    16,498

    0 points yesterday

    Profile
    Rank: Genius
  9. srosebabu

    15,248

    2,000 points yesterday

    Profile
    Rank: Guru
  10. navneethegde

    14,625

    0 points yesterday

    Profile
    Rank: Wizard
  11. askanilkris

    9,600

    0 points yesterday

    Profile
    Rank: Master
  12. Mikal613

    6,800

    0 points yesterday

    Profile
    Rank: Genius
  13. mas_oz2003

    6,600

    0 points yesterday

    Profile
    Rank: Genius
  14. dj_alik

    6,600

    0 points yesterday

    Profile
    Rank: Sage
  15. DaveBaldwin

    5,925

    0 points yesterday

    Profile
    Rank: Genius
  16. santhimurthyd

    5,400

    0 points yesterday

    Profile
    Rank: Wizard
  17. gauthampj

    4,920

    0 points yesterday

    Profile
    Rank: Genius
  18. Tchuki

    4,800

    0 points yesterday

    Profile
    Rank: Wizard
  19. lucky85

    4,168

    0 points yesterday

    Profile
    Rank: Wizard
  20. cactus_data

    4,000

    0 points yesterday

    Profile
    Rank: Genius
  21. anarki_jimbel

    4,000

    0 points yesterday

    Profile
    Rank: Genius
  22. for_yan

    4,000

    0 points yesterday

    Profile
    Rank: Genius
  23. ve3ofa

    3,800

    0 points yesterday

    Profile
    Rank: Genius
  24. techChallenger1

    3,600

    0 points yesterday

    Profile
    Rank: Guru
  25. KBerger

    3,500

    0 points yesterday

    Profile

Hall Of Fame