<

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x

Output an XML type attribute using DataContract

Published on
23,834 Points
14,234 Views
1 Endorsement
Last Modified:
Awarded
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>

Open 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>

Open 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);
}

Open 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

Open 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
{
}

Open 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; }
}

Open in new window


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

Open in new window


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

Open 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>

Open 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>

Open 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;
}

Open 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

1
Comment
0 Comments

Featured Post

Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

Join & Write a Comment

Watch this simple and effective video tutorial to extract attachments from Outlook 2007 and try this easy method by yourself. No need to go anywhere, just watch the video and export attachments from Outlook in few simple steps. To know more, click h…
I've published three five-minute Experts Exchange video Micro Tutorials that describe terrific features in an excellent, free PDF product called PDF-XChange Editor: How to rotate pages in a PDF with free software (https://www.experts-exchange.com…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month