2

我成功地System.ServiceModel.Syndication.SyndicationFeed从我的 ASP.NET 3.5 网站添加了一些 Atom10 输出。这是我第一次在生产环境中使用 ServiceStack,一切正常。

我的第一次尝试导致了 UTF-16 而不是 UTF-8,这对于除 IE 之外的所有浏览器都可以。所以我不得不创建XmlWriterResult类来解决这个问题。我的解决方案有效,但我应该怎么做?

public class AsStringService : IService<AsString>
{
    public object Execute(AsString request)
    {
        SyndicationFeed feed = new SyndicationFeed("Test Feed " + request.Name, "This is a test feed", new Uri("http://Contoso/testfeed"), "TestFeedID", DateTime.Now);
        SyndicationItem item = new SyndicationItem("Test Item", "This is the content for Test Item", new Uri("http://localhost/ItemOne"), "TestItemID", DateTime.Now);

        List<SyndicationItem> items = new List<SyndicationItem>();
        items.Add(item);
        feed.Items = items;
        Atom10FeedFormatter atomFormatter = new Atom10FeedFormatter(feed);

        return new XmlWriterResult(xmlWriter => atomFormatter.WriteTo(xmlWriter));
    }
}

XmlWriterResult是:

public delegate void XmlWriterDelegate(XmlWriter xmlWriter);

/// <summary>
/// From https://groups.google.com/forum/?fromgroups=#!topic/servicestack/1U02g7kViRs
/// </summary>
public class XmlWriterResult : IDisposable, IStreamWriter, IHasOptions
{
     private readonly XmlWriterDelegate _writesToXmlWriter;

     public XmlWriterResult(XmlWriterDelegate writesToXmlWriter)
     {
         _writesToXmlWriter = writesToXmlWriter;
         this.Options = new Dictionary<string, string> {
              { HttpHeaders.ContentType, "text/xml" }
         };
     }

     public void Dispose()
     {
     }

     public void WriteTo(Stream responseStream)
     {
         using (XmlWriter xmlWriter = XmlWriter.Create(responseStream))
         {
             _writesToXmlWriter(xmlWriter);
         }
     }

     public IDictionary<string, string> Options { get; set; }
}

(是的,我喜欢delegate,我也做很多F#)

4

1 回答 1

2

由于这不是一个没有明确答案的问题,我只想告诉你我会怎么做。

假设SyndicationFeed是一个干净的 DTO / POCO,你应该在你的服务中返回它:

public class AsStringService : IService
{
    public object Any(AsString request)
    {
        SyndicationFeed feed = new SyndicationFeed("Test Feed " + request.Name, 
           "This is a test feed", new Uri("http://Contoso/testfeed"), 
           "TestFeedID", DateTime.Now);
        SyndicationItem item = new SyndicationItem("Test Item", 
           "This is the content for Test Item", 
            new Uri("http://localhost/ItemOne"), 
           "TestItemID", DateTime.Now);

        List<SyndicationItem> items = new List<SyndicationItem>();
        items.Add(item);
        feed.Items = items;

        return feed;
    }
}

这个例子使用了更好的 ServiceStack 的 New API ,你应该尝试在未来的服务中使用它。

这将允许您在所有 ServiceStack 注册的 Content-Types 中获得 Content Negotiation。

注册自定义媒体类型

然后,您可以注册一个自定义媒体类型,如ServiceStack 的 Northwind v-card 示例所示

private const string AtomContentType = "application/rss+xml";

public static void Register(IAppHost appHost)
{
    appHost.ContentTypeFilters.Register(AtomContentType, SerializeToStream, 
        DeserializeFromStream);
}

public static void SerializeToStream(IRequestContext requestContext, 
    object response, Stream stream)
{
    var syndicationFeed = response as SyndicationFeed;
        if (SyndicationFeed == null) return;

    using (XmlWriter xmlWriter = XmlWriter.Create(stream))
    {
            Atom10FeedFormatter atomFormatter = new Atom10FeedFormatter(feed);
            atomFormatter.WriteTo(xmlWriter);
    }
}

public static object DeserializeFromStream(Type type, Stream stream)
{
    throw new NotImplementedException();
}

现在rss+xml格式应该出现在/metadata页面中,ServiceStack 将允许您在所有支持的 Content-Negotation 模式下请求格式,例如:

  • Accept: application/rss+xmlHTTP 标头
  • 使用预定义的路线,例如:/rss+xml/syncreply/AsString
  • 或附加/route?format=rss+xml到 QueryString

注意:您可能需要对“+”字符进行 url 编码

于 2012-10-23T02:41:20.050 回答