DCSIMG
March 2008 - Posts - Gady Elkarif's Blog

Gady Elkarif's Blog

March 2008 - Posts

Creating a Syndication Feed with WCF 3.5

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).

  • Rss20FeedFormatter - A class that serializes SyndicationFeed to and from RSS 2.0 format.
  • Atom10FeedFormatter - A class that serializes SyndicationFeed to and from ATOM 1.0 format.

    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:

WCF 3.5 Syndication API

 

And for ATOM 2.0 format:

WCF 3.5 Syndication API

 

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

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.
  • Build AjaxControlToolkit solution. If you have problems to compile project TemplateVSI, download and install the Microsoft Visual J# Version 2.0 redistributable Package.
  • 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:

ASP.NET AJAX Control Toolkit Project Template

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:

ASP.NER AJAX CalendarExtender Sample

 When pressing the mouse in the text box:

ASP.NER AJAX CalendarExtender Sample

After selecting date:

 ASP.NER AJAX CalendarExtender Sample

Source code of the ASP.NET AJAX CalendarExtender Sample.

 

Posted: Mar 15 2008, 07:34 PM by egady | with 15 comment(s)
תגים:,

Displaying Chart using Silverlight 2 User Control

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 Chart User Control

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:

Silverlight 2 Project

The result solution contains two projects:

  • ChartingApplication - Silverlight class library to support the Chart control (ChartingApplication.xap).
  • ChartingApplication_Web - Web application with a Silverlight link to the ChartingApplication.

ChartingApplication

This project contains two Xaml files:

  • App.xaml - Declares the application starting point.
  • Chart.xaml - The chart user control.

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 - asmx web service for retrieving the data.
  • ChartingApplicationTestPage.aspx - the aspx page that contains the control.

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:

Silverlight 2 User Control Project

The source code of Displaying Chart using Silverlight 2 User Control.

Call Silverlight from JavaScript

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

Silverlight JavaScript

After button clicked...

Silverlight JavaScript

The source code of Silverlight JavaScript.

Enjoy!