Creating a Syndication Feed with WCF 3.5
The WCF 3.5 Syndication API, include rich support of creating and consuming syndicated content.
In this post I'm going to create a service , which provides information about articles both in RSS 2.0 and ATOM 1.0 formats.
Service Contract
The following code described the service contract, which include two methods with the same uri, but different query parameter format (rss/atom).
[ServiceContract]
public interface IArticleService
{
[OperationContract, WebGet(UriTemplate = "feeds?format=rss", ResponseFormat = WebMessageFormat.Xml)]
Rss20FeedFormatter GetArticleInfoRss();
[OperationContract, WebGet(UriTemplate = "feeds?format=atom", ResponseFormat = WebMessageFormat.Xml)]
Atom10FeedFormatter GetArticleInfoAtom();
}
Service Implementation
The following web service implementation expose the two feed formats, one using Rss20FeedFormatter and the second Atom10FeedFormatter which resides on System.ServiceModel.Syndication namespace (in System.ServiceModel.Web.dll).
public class ArticleService : IArticleService
{
public Rss20FeedFormatter GetArticleInfoRss()
{
SyndicationFeed syndicationFeed = GetSyndicationFeed();
Rss20FeedFormatter formatter =
new Rss20FeedFormatter(syndicationFeed);
return formatter;
}
public Atom10FeedFormatter GetArticleInfoAtom()
{
SyndicationFeed syndicationFeed = GetSyndicationFeed();
Atom10FeedFormatter formatter =
new Atom10FeedFormatter(syndicationFeed);
return formatter;
}
private SyndicationFeed GetSyndicationFeed()
{
Uri uri = OperationContext.Current.IncomingMessageHeaders.To;
SyndicationFeed syndicationFeed = new SyndicationFeed(
"WCF 3.5 Articles",
"WCF - Windows Communication Foundation Articles ",
uri,
"FeedID",
DateTime.Now);
SyndicationItem item1 = new SyndicationItem(
"Article 1",
"This is the content for Article 1",
new Uri("http://www.wcf.com/wcfSyndication1.aspx"),
"ItemID1",
DateTime.Now);
SyndicationItem item2 = new SyndicationItem(
"Article 2",
"This is the content for Article 2",
new Uri("http://www.wcf.com/wcfSyndication2.aspx"),
"ItemID2",
DateTime.Now);
List<SyndicationItem> items = new List<SyndicationItem>();
items.Add(item1);
items.Add(item2);
syndicationFeed.Items = items;
return syndicationFeed;
}
}
Service Host
The
Web.Config of the service include
webHttpBinding, as described in the following service model:
<system.serviceModel>
<services>
<service name="ArticleService.ArticleService"
behaviorConfiguration="ArticleService.ArticleServiceBehavior">
<endpoint address=""
binding="webHttpBinding"
contract="ArticleService.IArticleService"
behaviorConfiguration="webHttpBehavior">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ArticleService.ArticleServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Transforming a Feed
The following code sample transform the feed content into RSS 2.0 and prints it into the console.
String feedUri = "http://localhost:1329/ArticleService.svc/feeds?format=rss";
XmlReader reader = XmlReader.Create(feedUri);
SyndicationFeed feed = SyndicationFeed.Load(reader);
// transform it to RSS
Rss20FeedFormatter formatter = new Rss20FeedFormatter(feed);
XmlWriter writer = XmlWriter.Create(Console.Out, null);
// write it to the Console
formatter.WriteTo(writer);
writer.Flush();
When you type the same url into a browser, the result for RSS 2.0 is:
And for ATOM 2.0 format:
Conclusion
WCF 3.5 supports creating and consuming both RSS 2.0 and ATOM 1.0 formats which is very easy to use. You can serve and consume syndicated content over any transport.
This is very powerfull, since with those formats you can express any set of data.
The source code WCF Syndication.
Using the ASP.NET AJAX Calendar Control
This post is about using of the Calendar extender control from the ASP.NET AJAX Control Toolkit.
For using the ASP.NET AJAX Control Toolkit toolkit, you need to download the ASP.NET AJAX Control Toolkit from http://www.asp.net/ajax/downloads/.
Installing the ASP.NET AJAX Control Toolkit
-
Download the AJAX Control Toolkit source code, extract it into folder ..\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\AJAX Control Toolkit, create new folder for that.
-
-
Copy files AjaxControlToolkit.dll and AjaxControlToolkit from directory ..\AJAX Control Toolkit\SampleWebSite\Bin to directory ..\AJAX Control Toolkit\Binaries, Then
-
Install the Control Toolkit Project Templates by double clicking on the file ..\AJAX Control Toolkit\AjaxControlExtender\AjaxControlExtender.vsi.
Creating ASP.NET AJAX Enabled Project
Create new Web Site using the AJAX Control Toolkit Web Site template, as showing in the following figure:
Drag and drop into page Default.aspx asp:TextBox and ajaxToolkit:CalendarExtender, so the page should be look like:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:TextBox ID="Date1" runat="server"></asp:TextBox>
<ajaxToolkit:CalendarExtender
ID="CalendarExtender1" runat="server" TargetControlID="Date1">
</ajaxToolkit:CalendarExtender>
</div>
</form>
</body>
</html>
Note that TergetControlID point to the text box id.
The Default CalendarExtender Control:

When pressing the mouse in the text box:

After selecting date:
Source code of the ASP.NET AJAX CalendarExtender Sample.
Displaying Chart using Silverlight 2.0 User Control
In this post I'm going to create a Chart User Control using Silverlight 2.0.
In previous post My New Innovative Project I talked about the application I'm developed, which is related to the finance market, and for that I need to display a financial chart. This chart is responsible for historical prices, and the data is received from a csv file as described in CsvReader and Linq.
This chart is only first version and it will improved with tool tip, and much more.
The result of this post is as shown in the following figure:
Silverlight 2
For develop with Silverlight 2, I installed Silverlight 2 Beta 1 and Microsoft Silverlight Tools Beta 1 for Visual Studio 2008 both availavle in http://silverlight.net/.
The following figure shows how to create Silverlight Application project template:
The result solution contains two projects:
ChartingApplication
This project contains two Xaml files:
App.xaml.cs
The following sample is the App class implementation, that loads the main control:
public partial class App : Application
{
public App()
{
this.Startup += this.Application_Startup;
this.Exit += this.Application_Exit;
this.UnhandledException += this.Application_UnhandledException;
InitializeComponent();
}
private void Application_Startup(object sender, StartupEventArgs e)
{
// Load the main control
this.RootVisual = new Chart(600, 350);
}
private void Application_Exit(object sender, EventArgs e)
{
}
private void Application_UnhandledException(
object sender, ApplicationUnhandledExceptionEventArgs e)
{
}
}
App.xaml
The App.xaml is empty:
<Application xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ChartingApplication.App"
>
<Application.Resources>
</Application.Resources>
</Application>
Chart.xaml
Partial of the Chart.xaml is shown in the following code:
<UserControl x:Class="ChartingApplication.Chart"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot" Background="Blue">
<Rectangle
x:Name="chartBackground"
Width="800"
Height="400"
Canvas.Left="0"
Canvas.Top="0"
Stroke="#FFD4D4D4" >
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FFD4D4D4" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<TextBlock
x:Name="titleLabel" FontSize="18" FontWeight="Bold" />
<Canvas x:Name="chartContainer" Canvas.Left="60" Canvas.Top="64" Background="#FFFAFA">
//...
Chart.xaml.cs
The Chart.cs User Control is declared as follows:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Linq;
using ChartingApplication.HistoricalDataService;
namespace ChartingApplication
{
[ScriptableType]
public partial class Chart : UserControl
{
private HistoricalDataServiceSoapClient m_historicalDataService = new HistoricalDataServiceSoapClient();
private Double m_chartWidth;
private Double m_chartHeight;
private Double m_chartContainerWidth;
private Double m_chartContainerHeight;
private Double m_chartViewWidth;
private Double m_chartViewHeight;
private const Int32 NUM_OF_X_LABELS = 14;
private const Int32 NUM_OF_Y_LABELS = 5;
public Chart(Double chartWidth, Double chartHeight)
{
InitializeComponent();
HtmlPage.RegisterScriptableObject("Chart", this);
m_historicalDataService.GetIndexDataCompleted +=
new EventHandler<GetIndexDataCompletedEventArgs>(GetHistoricalDataCompleted);
}
You can read about RegisterScriptableObject on Creating Silverlight Controls and Web Service with ASP.NET Futures.
I also register event handler for method GetHistoricalDataCompleted, since all the service references from Silverlight are asynchronously.
In the following code you can see how Linq helps me to work with data received from the HistoricalDataService:
[ScriptableMember]
public void GetHistoricalData(String index, String fromDate, String toDate)
{
m_historicalDataService.GetIndexDataAsync(index, fromDate, toDate);
}
[ScriptableMember]
public void GetHistoricalDataCompleted(Object sender, GetIndexDataCompletedEventArgs e)
{
DataPoint[] data = e.Result;
Double maxValue = Double.Parse(data.Max(p => p.Value));
Double minValue = Double.Parse(data.Min(p => p.Value));
Double diff = Math.Abs(maxValue - minValue) * 1.2;
Double minY = minValue - diff / 10;
Double maxY = maxValue + diff / 10;
Double spread = m_chartContainerWidth / data.Length;
Double yy = Double.Parse(data[0].Value) - minY;
String dataString =
String.Format("M {0},{1}", m_chartContainerWidth, m_chartViewHeight - yy);
Double xValue = m_chartContainerWidth;
foreach (DataPoint dp in data)
{
xValue -= spread;
Double yValue = m_chartViewHeight - (Double.Parse(dp.Value) - minY);
dataString += String.Format(" L {0},{1}", xValue, yValue);
}
DisplayXLabels();
DisplayYLabels(minY, maxY);
ShowData(
dataString,
String.Format(" L 0,{0} L {1},{2} Z",
m_chartViewHeight - 1, m_chartContainerWidth, m_chartViewHeight - 1));
}
public void ShowData(String dataString, String fillDataString)
{
titleLabel.Text = "S&P 500 INDEX,RTH (^GSPC)";
series1Stroke.SetValue(Path.DataProperty, dataString);
series1Fill.SetValue(Path.DataProperty, dataString + fillDataString);
}
ChartingApplication_Web
The ChartingApplication contains the following items:
HistoricalDataService
The HistoricalWebService read in the constructor all the data about S&P, and parse it into a collection.
The GetIndexData web method, gets the date range, and return a collection of all the related data. The following code describes class HistoricalDataService:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class HistoricalDataService : System.Web.Services.WebService
{
private ICollection<IndexEntity> m_historicalData;
public HistoricalDataService()
{
String fileName = Path.Combine(
Path.Combine(HttpRuntime.AppDomainAppPath, "App_Data"),
"S_and_P_2000_2008_Daily.csv");
CsvReader<IndexEntity> reader = new CsvReader<IndexEntity>(fileName);
m_historicalData = reader.Parse();
}
[WebMethod]
public List<DataPoint> GetIndexData(
String index, String startDateString, String endDateString)
{
List<DataPoint> result = new List<DataPoint>();
DateTime startDate = DateTime.Parse(startDateString);
DateTime endDate = DateTime.Parse(endDateString);
var data =
from e in m_historicalData
where (e.Date > startDate && e.Date < endDate)
select new DataPoint(e.Date.ToString(), e.Close.ToString());
foreach (DataPoint dataPoint in data)
{
result.Add(dataPoint);
}
return result;
}
}
[Serializable]
public sealed class DataPoint
{
private String m_date;
private String m_value;
public DataPoint()
{
}
public DataPoint(String date, String value)
{
m_date = date;
m_value = value;
}
public String Date
{
get
{
return m_date;
}
set
{
m_date = value;
}
}
public String Value
{
get
{
return m_value;
}
set
{
m_value = value;
}
}
}
ChartingApplicationTestPage.aspx
ChartingApplicationTestPage.aspx page contains the java script, for get the user date range, and when pressing the button, the chart control gets into the HistoricalDataService to get the relevant data, and display it.
<html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;">
<head runat="server">
<title>Test Page For ChartingApplication</title>
<script type="text/javascript">
function getHistoricalData(index, from, to)
{
var control = document.getElementById("Xaml1");
control.Content.Chart.GetHistoricalData(index, from, to);
}
</script>
</head>
<body style="height:100%;margin:0;">
<form id="form1" runat="server" style="height:100%;">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
Index:
<input type="text" name="index1" value="S&P 500" />
<br />
From:
<input type="text" name="from1" value="5/4/2007" />
<br />
To:
<input type="text" name="to1" value="2/1/2008" />
<br />
<input
type="button"
id="button1"
value="Get Historical Data"
onclick = "getHistoricalData(index1.value, from1.value, to1.value);" />
</div>
<div style="height:100%;">
<asp:Silverlight
ID="Xaml1"
runat="server"
Source="~/ClientBin/ChartingApplication.xap"
Version="2.0"
Width="100%"
Height="100%" />
</div>
</form>
</body>
</html>
The solution explorer of this project:
The source code of Displaying Chart using Silverlight 2 User Control.
Call Silverlight from JavaScript
This post is about great feature - the Managed HTML Bridge.
With this feature, you can use JavaScript to call Scriptable managed code include properties, methods and events.
In the previous post I wrote about Creating Silverlight Controls and Web Service with ASP.NET Futures, I will use this type of project to create a Web Application, and Xaml control.
Register the Class as Scriptable Object
After creating the Web Application and a Silverlight Project, lets register the class as scriptable object, inside the Page_Loaded method:
[Scriptable]
public partial class Page : Canvas
{
HtmlElement m_buttonElement = null;
public void Page_Loaded(object o, EventArgs e)
{
// Required to initialize variables
InitializeComponent();
WebApplication.Current.RegisterScriptableObject("MyControl", this);
m_buttonElement = HtmlPage.Document.GetElementByID("button1");
}
[Scriptable]
public void Hello(String name)
{
// Access the HTML DOM from Managed Code
m_buttonElement.SetAttribute("value", String.Format("Hello {0}!", name));
}
}
The
Scriptable Attribute define the class and the method accessible from
JavaScript.
Calling Managed Code from JavaScript
The following html sample page describe how to call the managed code using JavaScript.
<head runat="server">
<title>Untitled Page</title>
<script type="text/javascript">
function onClickButton()
{
var control = document.getElementById("Xaml1");
control.content.MyControl.Hello("Gady");
control.content.findName("tb").Text = "Hello Silverlight";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:Xaml ID="Xaml1" runat="server" Width="200" Height="200" XamlUrl="~/Page.Xaml" />
</div>
<div>
<input type="button" id="button1" value="Click Me" onclick = "onClickButton();" />
</div>
</form>
</body>
When pressing on the button, the JavaScript methos onClickButton() is called, and:
-
Get the Xaml control 'Xaml1'.
-
Call the Managed Acriptable method Hello().
-
Find the text block Xaml element "tb" and changed the text to "Hello Silverlight".
Before button clicked...
After button clicked...
The source code of Silverlight JavaScript.
Enjoy!