Marshalling and Unmarshalling Entities

Recently, I have encountered problems transporting lightweight entities across a Web service. I have been working on frameworks such as Apache Axis and WSIF to verify the Web service on different languages. After several investigations I noticed this isn’t that straightforward. For example, consider the following entity:
 
using System.Runtime.Serialization;
using System;
using System.Data.Linq.Mapping;
 
namespace Business.Entity
{
    [Serializable()]
    [Table(Name="Issues")]
    public class Issue
    {
        private int issueId;
        private string issueDescription;
        private string isDeleted;
        public Issue()
        {
        }
        [Column(IsPrimaryKey=true, Name="issue_id")]
        public int IssueID
        {
            get
            {
                return issueId;
            }
            set
            {
                issueId = value;
            }
        }
        [Column(Storage="issueDescription", Name="issue_description")]
        public string IssueDescription
        {
            get
            {
                return issueDescription;
            }
            set
            {
                issueDescription = value;
            }
        }
        [Column(Storage = "isDeleted", Name = "is_deleted")]
        public string IsDeleted
        {
            get
            {
                return isDeleted;
            }
            set
            {
                isDeleted = value;
            }
        }
    }
}
 
Now, let’s take a look at a Web Method in the Web service.
 
[WebMethod]
public Issue GetIssueByIssueId(int issueId)
{
  Issue issue = new Issue();
  issue.IssueId = 1;
  issue.IssueDescription = "-na-";
  issue.IsDeleted = "Y";
  return issue;
}
 
Let’s take a look at a method that consumes the above Web Method.
 
protected void FindIssueByIssueId_Click(object sender, EventArgs e)
{
  ServiceProvider.IssueService service = new ServiceProvider.IssueService();
  Issue issue = service.GetIssueByIssueId(1);
}
 
Unfortunately, if you attempt to compile the above code, you hit the following error:
 
Cannot implicitly convert type ‘ServiceProvider.Issue’ to ‘Business.Entity.Issue’
 
So how do we solve this? I’m recommending a translation service that translates (marshall and unmarshall) custom entities to and from a XML string. The following is a simple translation service:
 
CS
 
using System;
using System.IO;
using System.Xml.Serialization;
 
namespace K365labs.Foundation
{
    [Serializable]
    public class TranslationService<TEntity>
    {
        public TranslationService()
        {
        }
        public string ToXML(TEntity entity)
        {
            string output = string.Empty;
            using (StringWriter writer = new StringWriter())
            {
                XmlSerializer serializer = null;
                serializer = new XmlSerializer(typeof(TEntity));
                serializer.Serialize(writer, entity);
                output = writer.ToString();
                writer.Close();
            }
            return output;
        }
        public TEntity FromXML(string xmlString)
        {
            TEntity entity = default(TEntity);
            XmlSerializer serializer = null;
            using (StringReader reader = new StringReader(xmlString))
            {
                serializer = new XmlSerializer(typeof(TEntity));
                entity = (TEntity)serializer.Deserialize(reader);
            }
            return entity;
        }
    }
}
 
VB
 
Imports System
Imports System.IO
Imports System.Xml.Serialization
 
Namespace K365labs.Foundation
    <Serializable()> _
    Public Class TranslationService(Of TEntity)
        Public Sub New()
        End Sub
        Public Function FromXML(ByVal xmlString As String) As TEntity
            Dim entity As TEntity = Nothing
            Dim serializer As XmlSerializer = Nothing
            Using reader As New StringReader(xmlString)
                serializer = New XmlSerializer(GetType(TEntity))
                entity = CType(serializer.Deserialize(reader), TEntity)
            End Using
            Return entity
        End Function
        Public Function ToXML(ByVal entity As TEntity) As String
            Dim output As String = String.Empty
            Using writer As New StringWriter()
                Dim serializer As XmlSerializer = Nothing
                serializer = New XmlSerializer(GetType(TEntity))
                serializer.Serialize(writer, entity)
                output = writer.ToString()
                writer.Close()
            End Using
            Return output
        End Function
    End Class
End Namespace
 
Now we modify the Web method in our Web service to use the service. The following is the modified Web Method:
 
[WebMethod]
public Issue GetIssueByIssueId(int issueId)
{
  Issue issue = new Issue();
  issue.IssueId = 1;
  issue.IssueDescription = "-na-";
  issue.IsDeleted = "Y";
 
  EntityTranslator<Issue> translator = new EntityTranslator<Issue>();
 
  return translator.ToXML;
}
 
To call our new Web Service method, we need modify the method on the consuming end. The following is the modified method:
 
protected void FindIssueByIssueId_Click(object sender, EventArgs e)
{
  ServiceProvider.IssueService service = new ServiceProvider.IssueService();
  string xmlIssue = service.GetIssueByIssueId(1);
  
  TranslationService<Issue> translator = new TranslationService<Issue>();
  Issue issue = translator.FromXML(xmlIssue);
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: