9 min read

Data applications

When building applications that utilize data, it is important to start with defining what data you are going to collect and how it will be stored once collected. In the last chapter, we created a Silverlight application to post a collection of ink strokes to the server. We are going to expand the inkPresenter control to allow a user to submit additional information.

Most developers would have had experience building business object layers, and with Silverlight we can still make use of these objects, either by using referenced class projects/libraries or by consuming WCF services and utilizing the associated data contracts.

Time for action – creating a business object

We’ll create a business object that can be used by both Silverlight and our ASP.NET application. To accomplish this, we’ll create the business object in our ASP.NET application, define it as a data contract, and expose it to Silverlight via our WCF service.

Start Visual Studio and open the CakeORamaData solution. When we created the solution, we originally created a Silverlight application and an ASP.NET web project.

    1. In the web project, add a reference to the System.Runtime.Serialization assembly.

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    1. Right-click on the web project and choose to add a new class. Name this class ServiceObjects and click OK.

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    1. In the ServiceObjects class file, replace the existing code with the following code:

using System;
using System.Runtime.Serialization;

namespace CakeORamaData.Web
{
[DataContract]
public class CustomerCakeIdea
{
[DataMember]
public string CustomerName { get; set; }
[DataMember]
public string PhoneNumber { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public DateTime EventDate { get; set; }
[DataMember]
public StrokeInfo[] Strokes { get; set; }
}

[DataContract]
public class StrokeInfo
{
[DataMember]
public double Width { get; set; }
[DataMember]
public double Height { get; set; }
[DataMember]
public byte[] Color { get; set; }
[DataMember]
public byte[] OutlineColor { get; set; }
[DataMember]
public StylusPointInfo[] Points { get; set; }
}

[DataContract]
public class StylusPointInfo
{
[DataMember]
public double X { get; set; }
[DataMember]
public double Y { get; set; }
}
}


  1. What we are doing here is defining the data that we’ll be collecting from the customer.

What just happened?

We just added a business object that will be used by our WCF service and our Silverlight application. We added serialization attributes to our class, so that it can be serialized with WCF and consumed by Silverlight.

The [DataContract] and [DataMember] attributes are the serialization attributes that WCF will use when serializing our business object for transmission. WCF provides an opt-in model, meaning that types used with WCF must include these attributes in order to participate in serialization. The [DataContract] attribute is required, however if you wish to, you can use the [DataMember] attribute on any of the properties of the class.

By default, WCF will use the System.Runtime.Serialization.DataContractSerialzer to serialize the DataContract classes into XML. The .NET Framework also provides a NetDataContractSerializer which includes CLR information in the XML or the JsonDataContractSerializer that will convert the object into JavaScript Object Notation (JSON). The WebGet attribute provides an easy way to define which serializer is used.

For more information on these serializers and the WebGet attribute visit the following MSDN web sites:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx.
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.netdatacontractserializer.aspx.
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.aspx.
http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webgetattribute.aspx.

Windows Communication Foundation (WCF)

Windows Communication Foundation (WCF) provides a simplified development experience for connected applications using the service oriented programming model. WCF builds upon and improves the web service model by providing flexible channels in which to connect and communicate with a web service. By utilizing these channels developers can expose their services to a wide variety of client applications such as Silverlight, Windows Presentation Foundation and Windows Forms.

Service oriented applications provide a scalable and reusable programming model, allowing applications to expose limited and controlled functionality to a variety of consuming clients such as web sites, enterprise applications, smart clients, and Silverlight applications.

When building WCF applications the service contract is typically defined by an interface decorated with attributes that declare the service and the operations. Using an interface allows the contract to be separated from the implementation and is the standard practice with WCF.

You can read more about Windows Communication Foundation on the MSDN website at: http://msdn.microsoft.com/en-us/netframework/aa663324.aspx.

Time for action – creating a Silverlight-enabled WCF service

Now that we have our business object, we need to define a WCF service that can accept the business object and save the data to an XML file.

    1. With the CakeORamaData solution open, right-click on the web project and choose to add a new folder, rename it to Services.
    2. Right-click on the web project again and choose to add a new item. Add a new WCF Service named CakeService.svc to the Services folder. This will create an interface and implementation files for our WCF service. Avoid adding the Silverlight-enabled WCF service, as this adds a service that goes against the standard design patterns used with WCF:

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

The standard design practice with WCF is to create an interface that defines the ServiceContract and OperationContracts of the service. The interface is then provided, a default implementation on the server. When the service is exposed through metadata, the interface will be used to define the operations of the service and generate the client classes. The Silverlight-enabled WCF service does not create an interface, just an implementation, it is there as a quick entry point into WCF for developers new to the technology.

    1. Replace the code in the ICakeService.cs file with the definition below. We are defining a contract with one operation that allows a client application to submit a CustomerCakeIdea instance:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace CakeORamaData.Web.Services
{
// NOTE: If you change the interface name “ICakeService” here,
you must also update the reference to “ICakeService” in Web.config.
[ServiceContract]
public interface ICakeService
{
[OperationContract]
void SubmitCakeIdea(CustomerCakeIdea idea);
}
}


    1. The CakeService.svc.cs file will contain the implementation of our service interface. Add the following code to the body of the CakeService.svc.cs file to save the customer information to an XML file:

using System;
using System.ServiceModel.Activation;
using System.Xml;

namespace CakeORamaData.Web.Services
{
// NOTE: If you change the class name “CakeService” here, you
must also update the reference to “CakeService” in Web.config.
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class CakeService : ICakeService
{
public void SubmitCakeIdea(CustomerCakeIdea idea)
{
if (idea == null) return;
using (var writer = XmlWriter.Create(String.Format(@”C:
ProjectsCakeORamaCustomerData{0}.xml”, idea.CustomerName)))
{
writer.WriteStartDocument();

//<customer>
writer.WriteStartElement(“customer”);
writer.WriteAttributeString(“name”, idea.CustomerName);
writer.WriteAttributeString(“phone”, idea.PhoneNumber);
writer.WriteAttributeString(“email”, idea.Email);

// <eventDate></eventDate>
writer.WriteStartElement(“eventDate”);
writer.WriteValue(idea.EventDate);
writer.WriteEndElement();

// <strokes>
writer.WriteStartElement(“strokes”);

if (idea.Strokes != null && idea.Strokes.Length > 0)
{
foreach (var stroke in idea.Strokes)
{
// <stroke>
writer.WriteStartElement(“stroke”);

writer.WriteAttributeString(“width”, stroke.Width.
ToString());
writer.WriteAttributeString(“height”, stroke.Height.
ToString());

writer.WriteStartElement(“color”);
writer.WriteAttributeString(“a”, stroke.Color[0].
ToString());
writer.WriteAttributeString(“r”, stroke.Color[1].
ToString());
writer.WriteAttributeString(“g”, stroke.Color[2].
ToString());
writer.WriteAttributeString(“b”, stroke.Color[3].
ToString());
writer.WriteEndElement();

writer.WriteStartElement(“outlineColor”);
writer.WriteAttributeString(“a”, stroke.
OutlineColor[0].ToString());
writer.WriteAttributeString(“r”, stroke.
OutlineColor[1].ToString());
writer.WriteAttributeString(“g”, stroke.
OutlineColor[2].ToString());
writer.WriteAttributeString(“b”, stroke.
OutlineColor[3].ToString());
writer.WriteEndElement();

if (stroke.Points != null && stroke.Points.Length > 0)
{
writer.WriteStartElement(“points”);
foreach (var point in stroke.Points)
{
writer.WriteStartElement(“point”);
writer.WriteAttributeString(“x”, point.
X.ToString());
writer.WriteAttributeString(“y”, point.
Y.ToString());
writer.WriteEndElement();
}
writer.WriteEndElement();
}

// </stroke>
writer.WriteEndElement();
}
}

// </strokes>
writer.WriteEndElement();

//</customer>
writer.WriteEndElement();

writer.WriteEndDocument();
}
}
}
}


We added the AspNetCompatibilityRequirements attribute to our CakeService implementation. This attribute is required in order to use a WCF service from within ASP.NET.

    1. Open Windows Explorer and create the path C:ProjectsCakeORamaCustomerData on your hard drive to store the customer XML files.

One thing to note is that you will need to grant write permission to this directory for the ASP.NET user account when in a production environment.

    1. When adding a WCF service through Visual Studio, binding information is added to the web.config file. The default binding for WCF is wsHttpBinding, which is not a valid binding for Silverlight. The valid bindings for Silverlight are basicHttpBinding, binaryHttpBinding (implemented with a customBinding), and netTcpBinding. We need to modify the web.config, so that Silverlight can consume the service. Open the web.config file and add this customBinding section to the <system.serviceModel> node:

<bindings>
<customBinding>
<binding name=”customBinding0″>
<binaryMessageEncoding />
<httpTransport>
<extendedProtectionPolicy policyEnforcement=”Never” />
</httpTransport>
</binding>
</customBinding>
</bindings>


    1. We’ll need to change the <service> node in the web.config to use our new customBinding, (we use the customBinding to implement binary HTTP which sends the information as a binary stream to the service), rather than the wsHttpbinding from:

<service behaviorConfiguration=”CakeORamaData.Web.Services.
CakeServiceBehavior”
name=”CakeORamaData.Web.Services.CakeService”>
<endpoint address=”” binding=”wsHttpBinding”
contract=”CakeORamaData.Web.Services.ICakeService”>
<identity>
<dns value=”localhost” />
</identity>
</endpoint>
<endpoint address=”mex” binding=”mexHttpBinding” contract=”IM
etadataExchange” />
</service>


To the following:

<service behaviorConfiguration=”CakeORamaData.Web.Services.
CakeServiceBehavior”
name=”CakeORamaData.Web.Services.CakeService”>
<endpoint address=”” binding=”customBinding” bindingConfiguratio
n=”customBinding0″
contract=”CakeORamaData.Web.Services.ICakeService” />
<endpoint address=”mex” binding=”mexHttpBinding” contract=”IMeta
dataExchange” />
</service>


    1. Set the start page to the CakeService.svc file, then build and run the solution. We will be presented with the following screen, which lets us know that the service and bindings are set up correctly:

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    1. Our next step is to add the service reference to Silverlight. On the Silverlight project, right-click on the References node and choose to Add a Service Reference:

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    1. On the dialog that opens, click the Discover button and choose the Services in Solution option. Visual Studio will search the current solution for any services:

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    1. Visual Studio will find our CakeService and all we have to do is change the Namespace to something that makes sense such as Services and click the OK button:

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    1. We can see that Visual Studio has added some additional references and files to our project. Developers used to WCF or Web Services will notice the assembly references and the Service References folder:

Microsoft Silverlight 4 Business Application Development: Beginner’s Guide

    1. Silverlight creates a ServiceReferences.ClientConfig file that stores the configuration for the service bindings. If we open this file, we can take a look at the client side bindings to our WCF service. These bindings tell our Silverlight application how to connect to the WCF service and the URL where it is located:

<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name=”CustomBinding_ICakeService”>
<binaryMessageEncoding />
<httpTransport
maxReceivedMessageSize=”2147483647″ maxBufferSize=”2147483647″>
<extendedProtectionPolicy policyEnforcemen
t=”Never” />
</httpTransport>
</binding>
</customBinding>
</bindings>
<client>
<endpoint address=”http://localhost:2268/Services/
CakeService.svc”
binding=”customBinding” bindingConfiguration=”Cust
omBinding_ICakeService”
contract=”Services.ICakeService”
name=”CustomBinding_ICakeService” />
</client>
</system.serviceModel>
</configuration>


LEAVE A REPLY

Please enter your comment!
Please enter your name here