views:

400

answers:

2

I would like to expose a SyndicationFeedFormatter with wcf and basicHttpBinding. I continue to get errors like that shown below. I have included the interface/class and the web.config wcf configuration.

I have tried to expose SyndicationFeedFormatter as well as IList but am unable to get past the following error. Has anyone been able to do this or someone confirm what the problem is?

thx - dave

Error message

System.ServiceModel.Dispatcher.NetDispatcherFaultException: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetFeaturesResult. The InnerException message was 'Error in line 1 position 123. Element 'http://tempuri.org/:GetFeaturesResult' contains data of the 'http://schemas.datacontract.org/2004/07/System.ServiceModel.Syndication:Rss20FeedFormatter' data contract

My interface/contract looks like

[ServiceContract]
[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
public interface IGetData {

    [OperationContract]
    SyndicationFeedFormatter GetFeatures();

    [OperationContract]
    IList<SyndicationItem> GetFeatures2();

}

My method looks like ....

    public SyndicationFeedFormatter GetFeatures()() {
        // Generate some items...
        SyndicationFeed feed = new SyndicationFeed() {
            Title = new TextSyndicationContent("Mike's Feed"),
            Description = new TextSyndicationContent("Mike's Feed Description")
        };

        feed.Items = from i in new int[] { 1, 2, 3, 4, 5 }
                     select new SyndicationItem() {
                         Title = new TextSyndicationContent(string.Format("Feed item {0}", i)),
                         Summary = new TextSyndicationContent("Not much to see here"),
                         PublishDate = DateTime.Now,
                         LastUpdatedTime = DateTime.Now,
                         Copyright = new TextSyndicationContent("MikeT!"),
                     };

        return (new Rss20FeedFormatter(feed));
    }

    public IList<SyndicationItem> GetFeatures2() {

        List<string> includeList = new List<string>();
        includeList.Add("Feature");

        IList<SyndicationItem> mylist = ReaderManager.GetFeedByCategory2(includeList, null, null);
        return mylist;

    }

My web.config looks like the following

binding="webHttpBinding" contract="SLNavigationApp.Web.IGetData"> -->

         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

     </service>
 </services>

 <behaviors>
     <endpointBehaviors>
         <behavior name="webHttpBehavior">
             <webHttp />
         </behavior>
     </endpointBehaviors>
     <serviceBehaviors>
         <behavior name="SLNavigationApp.Web.GetDataBehavior">
             <serviceMetadata httpGetEnabled="true" />
             <serviceDebug includeExceptionDetailInFaults="true" />
         </behavior>
    </serviceBehaviors>
 </behaviors>

+1  A: 

I'm confused: Are you using WebHttpBinding, or the BasicHttpBinding? You should definitely be using the former, and that should just work.

If you're trying to use BasicHttpBinding, do you mind sharing why? The SyndicationFeedFormatter classes aren't DataContracts or XmlSerializable (which is what you'd need to support for BasicHttpBinding), so it would likely not work in that case unless you did a little bit of extra work. What I'd likely try to get around this would be to simply change my ServiceContract to return Message objects instead, like this:

[ServiceContract]
[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
public interface IGetData {
    [OperationContract]
    Message GetFeatures();

}

...

SyndicationFeedFormatter frm = new Rss20FeedFormatter(feed);
return Message.CreateMessage(
   MessageVersion.None, "GetFeatures", 
   new FeedBodyWriter(frm)
   );

...

class FeedBodyWriter : BodyWriter {
   SyndicationFeedFormatter formatter;
   public FeedBodyWriter(SyndicationFeedFormatter formatter) : base(false) {
      this.formatter = formatter;
   }
   protected override void OnWriteBodyContents(XmlDictionaryWriter writer) {
      formatter.WriteTo(writer);
   }
}
tomasr
I was using basicHttpBinding as I was going to use Silverlight as the client for the wcf service and as I understand SL can only use basicHttpBinding. I do not want to expose the syndicated item as rss or atom (at least not at this point). I would however like to use the collection of Syndicated Items however in SL (as the collection) which i could use for binding in SL. I am not familiar with return type Message however I will give it a try. ty
David
David: I see. The Message type is the generic message representation in WCF. Think of it as an raw-xml untyped message, and it's defined in System.ServiceModel.Channels. Hope that helps!
tomasr
A: 

Cool, I was wondering why my service wasn't producing browser-readable content. I was also using basicHttpBinding (because all the rest of the calls are from Silverlight).

As an unrelated sidenote:

You can change: from i in new int[] { 1, 2, 3, 4, 5 }

To: from i in Enumerable.Range(1, 5)

This can be very handy! I usually use it as "Enumerable.Range(1, pagecount)" in an XLINQ query when I'm pulling paged XML data from a server.

Paul