サービス ステーション
Web フィードを作成および使用する
Jon Flanders
コードは MSDN コード ギャラリーからダウンロードできます。
オンラインでのコードの参照
目次
Web フィード
WCF とフィード
フィードの構造
フィードを公開する
フィードを実装する
AtomPub
フィードを使用する
MSDN Magazine の 2009 年 1 月号では、Representational State Transfer (REST) をクライアント/サーバー型アプリケーションを構築するためのアーキテクチャとしてとらえ、その使用方法の基本を説明しました。1 月号のコラムは、このタイプのアプリケーションを Microsoft .NET Framework 3.5 の Windows Communication Foundation (WCF) 機能を使用して構築する方法を紹介するシリーズの第 1 回でもあります。
今月は、WCF のその他の Web フィード機能について話します。この機能は、WCF の基本サポートだけを使用して実現できます。前回の「サービス ステーション」コラムに目を通しておくと今回のコラムを理解しやすくなりますが、このコラムだけをお読みいただいても問題ありません (ただし、WCF REST の基本についてある程度の知識があると、理解の助けとなります)。
Web フィードは、アプリケーションで World Wide Web から情報を取得するための手段として、10 年ほど前に登場しました。これまで、フィードはブログの記事や情報を公開するために使われてきましたが、アーキテクチャがシンプルなため、それ以外の種類のデータを公開する手段としても広く使用されるようになっています。
フィードは、HTTP URI を介して公開される XML データにすぎません。フィード リーダーは、任意の間隔で URI をポーリングし、取得したデータを処理します。ユーザーにフィード データを公開するアプリケーションとしてのリーダーには、新しいデータが公開されたことをユーザーに通知する役割があります。人が関与しないフィード リーダー (任意のアプリケーション コードなど) の場合、フィード リーダーが新しいデータを取得すると、通常は何らかのアプリケーション アクションがトリガされます。
フィードの多くはブログ データを公開する目的で使用されているのに、なぜサービスの構築に関するコラムで取り上げているのでしょうか。データを公開するためのフィード形式が単純なこと、そしてフィード リーダー (とフィードを解析するためのライブラリ) が至る所で使用されていることこそ、ブログ データに限らず多くの種類のデータがフィードとして公開されるようになった理由です。たとえば、ADO.NET Data Services は、完全にフィード テクノロジに基づくサービス対応データ層です (特に、Atom Publishing Protocol (AtomPub) と呼ばれる、Atom を基に構築された標準に準拠しています。AtomPub についてはこの後説明します)。Microsoft Windows Azure プラットフォームでは、他のさまざまな企業のサービスと同様に、そのデータ機能の多くをこの方法で公開しています。
フィードが普及した理由の 1 つは、使用されるのがよく知られている最も標準的な XML 形式であることです。業界では、RSS (Really Simple Syndication) と Atom という一般的なフィード スキーマの採用が進んでいます。データ プロバイダごとにカスタムの形式を使用するアプローチはとられていません。RSS の方が先に登場した形式です。Atom も広く使用されるようになりましたが、今も多くのフィードで RSS と Atom の両バージョンが公開されています。サービス (特に RESTful サービス) を構築する場合は、フィードを使うことを検討してください。読み取り専用のサービスの場合は RSS か Atom を、読み取りと書き込みに対応したサービスの場合は AtomPub を利用することをお勧めします。
WCF とフィード
.NET Framework 3.5 の WCF では、RESTful エンドポイントを構築するための基本サポートに加え、フィードの公開もサポートされています。WCF の HTTP ベース エンドポイントを作成し、普及しているどちらかのフィード形式を使用してフィードを公開できます。.NET Framework 3.5 SP1 の WCF では、フィードのサポートが追加されており、AtomPub 仕様をサポートするエンドポイントを簡単に実装できます。
私見ですが、WCF におけるフィード サポートのすばらしい特徴の 1 つは、Atom 形式や RSS 形式の詳細を把握する必要がないという点です。WCF には、一般的なオブジェクト グラフの構築に使用できるオブジェクト モデルが用意されています (このオブジェクト モデルは RSS よりも Atom に似ています。Atom のモデルの方が RSS よりも機能がやや充実しているからです)。そのため、このオブジェクト グラフの最上位オブジェクトを取得し、フレームワークによって提供される別のオブジェクト (フォーマッタと呼ばれる) に渡すことができます。フォーマッタは、オブジェクト グラフのデータを適切なフィード形式にシリアル化します。これが、同じエンドポイントから RSS と Atom の両方を簡単に公開できるしくみです。将来フィードの形式が変更されても、新しいフォーマッタだけを準備すればよいため、開発者に影響が及ぶこともありません。皆さんが行う必要があるのは、オブジェクト グラフへのデータの入力だけです。インフラストラクチャがデータを適切なフィード形式に変換してくれます。
フィードの構造
先へ進む前に、フィードの構造と、WCF オブジェクト モデルとフィード構造の関係について、簡単に説明します。フィードは、データのコレクションを公開するための非常に単純な手段です (図 1 を参照)。(一般に) フィードには、タイトル、説明、発行日、最終更新日時のほかに、アイテムのコレクションが含まれます。これらの各アイテムも、発行日、タイトル、コンテンツが含まれるかなり単純なデータです。通常、コンテンツには重要なデータが含まれます。ブログ エントリ、新聞記事など、情報の種類は問いません。各アイテムには、個別のアイテムやその代替の表現 (単なる要約ではなく、そのデータの完全な HTML ページなど) へのハイパーリンクを含めることができます。図 1に、フィードを視覚的に表したものを示します。
図 1 フィードのアーキテクチャ
MSDN Magazine の記事に関する情報をフィードを通じて公開する場合を考えてみましょう。まず、このフィードを通じてどのようなデータを公開するのかを決める必要があります。選択肢はいくつかありますが、このサンプルを MSDN Magazine のすべての号と記事のフィードとして実装してみます。更新情報を受け取ったフィード リーダーは、個別のアイテムとして発行された各記事 (コンテンツとして、記事の短い要約を含む) を表示することになります。
前回のコラムでは MSDN Magazine のデータを提供する汎用 RESTful サービス エンドポイントを構築しましたが、今回のサンプルでは、このコードを拡張することにします。繰り返しになりますが、今回の内容を理解するために前回のコラムを読む必要はありません。ただし、私がこのシナリオをサンプルとして選んだ意図が書かれています。それは、実際に RESTful Web サービスと SOAP ベース Web サービスの両方に当てはまるものです。多くの場合、フィードは、既存のサービスに追加するメリットの大きい実装の詳細です。WCF の強みは、WCF を使用して構築されたどのサービスにも、そのサービス全体が RESTful であるかどうかに関係なく、フィード エンドポイントを実に簡単に追加できることです。
フィードを公開する
まず、サービス コントラクトと定義を拡張し、フィードを公開するための操作を追加する必要があります。そこで、IMSDNMagazineService インターフェイスに GetIssuesFeed という名前の新しいメソッドを追加しました (図 2 を参照)。
図 2 GetIssuesFeed メソッドを追加する
[ServiceContract]
public interface IMSDNMagazineService {
[OperationContract]
[WebGet(UriTemplate="/")]
IssuesCollection GetAllIssues();
[OperationContract]
[WebGet(UriTemplate = "/feed?format={format}")]
[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
SyndicationFeedFormatter GetIssuesFeed(string format);
[OperationContract]
[WebGet(UriTemplate = "/{year}")]
IssuesData GetIssuesByYear(string year);
//remainder of interface commented for clarity
...
}
このメソッドには注意すべき点がいくつかあります。まず、戻り値の型は SyndicationFeedFormatter です。これは、筆者が前にフォーマッタと総称した WCF フィード サポートの一部です。SyndicationFeedFormatter は、皆さんがデータを追加した、元になるオブジェクトを参照し、フィード オブジェクトの種類に応じて適切な XML フィード形式を生成します。
WebGetAttribute の UriTemplate プロパティにも注目してください。このプロパティは、WCF に対し、各メソッドで応答または処理する必要のある URI を示します。このケースで興味深いのは、GetIssuesFeed メソッドが "/feed" というリテラルの URI テンプレートを持つという点です。GetIssuesByYear (フィードとは関係のないジェネリック RESTful メソッド) の URI には、変数パス セグメント ("/{year}") があります。URI の解析およびルーティング メカニズムではすべての要素が文字列に変換されるため、これら 2 つの UriTemplate は競合するように思われます。
WCF における UriTemplate の解析規則では、リテラルの照合は変数の照合の前に行われることになっています。したがって、受信 URI が "/feed" で終わるときは GetIssuesFeed にルーティングされますが、前述のパス セグメントを持つそれ以外の URI は GetIssuesByYear にルーティングされます。クライアントが要求しているフィード形式を示すクエリ文字列も使用していることに注意してください (明示的に要求された場合に限って RSS を返し、それ以外の場合は Atom を返します)。
GetIssuesFeed メソッドでもう 1 つ興味深い要素は、ServiceKnownTypeAttribute です。この属性は、実際の戻り値 (シリアル化を適切に行うために必要) として渡すことのできる戻り値の派生クラスをシリアル化層に通知するために、WCF によって使用されます。このケースでは、両方の形式を返さなければならない場合もあるかもしれません。そこで、それぞれが SyndicationFeedFormatter の適切な派生クラスを参照する、2 つの ServiceKnownTypeAttribute の宣言を追加しています (AtomFeedFormatter と Rss20FeedFormatter)。クラスの名前からおわかりになるでしょうが、AtomFeedFormatter は Atom 形式のフィードを返し、Rss20FeedFormatter は RSS 2.0 形式のフィードを返します。これはごく普通の WCF インフラストラクチャです。しかし、WCF の戻り値でポリモーフィズムを試してみた経験がない方は、この機能を目にしたことがないかもしれません。
フィードを実装する
これで実装以外の内容については全部説明しました。MSDN Magazine の号と記事に関するデータを取得し、それを WCF オブジェクト モデルに転送するだけでよいので、実装は実に簡単です。このオブジェクト モデルは SyndicationFeedFormatter に基づくモデルではありません。SyndicationFeedFormatter は形式を設定するオブジェクトであることを思い出してください。このオブジェクト モデルの中心は、SyndicationFeed という名前の型です (図 3 を参照)。SyndicationFeed オブジェクトを使用して、有効な SyndicationFeedFormatter を取得できます。SyndicationFeed は各フィード アイテムを保持するオブジェクトであり、それらのアイテムは SyndicationFeed.Items コレクションの一部です。
図 3 SyndicationFeed オブジェクト モデル
SyndicationFeed オブジェクト モデルは一般的なフィードの概念に基づいていますが、どちらかというと (SyndicationItem に Authors コレクション、Links コレクション、Content プロパティ、Summary プロパティが含まれている) Atom 向けのモデルです。図 4に、サービスに GetIssuesFeed メソッドを実装するコードを示します。
図 4 GetIssuesFeed
public SyndicationFeedFormatter GetIssuesFeed(string format) {
SyndicationFeedFormatter ret = null;
SyndicationFeed myFeedData = new SyndicationFeed();
myFeedData.Title = new TextSyndicationContent(
"MSDN Magazine feed");
Articles articles = GetAllArticles();
SyndicationItem sitem = null;
List<SyndicationItem> list = new List<SyndicationItem>();
myFeedData.Items = list;
SyndicationLink altLink = null;
foreach (var item in articles) {
sitem = new SyndicationItem {
Title = new TextSyndicationContent(
"MSDN Magazine Article: " + item.Title),
Content = new XmlSyndicationContent(GenerateContent(item)),
PublishDate = GetPublished(item),
LastUpdatedTime = GetUpdated(item)
};
altLink = MakeLinkForArticle(item);
sitem.Links.Add(altLink);
list.Add(sitem);
}
ret = new Atom10FeedFormatter(myFeedData);
return ret;
}
この単純なコードは、WCF でのあらゆるフィード コードと同じ基本的なパターンに従っています。つまり、SyndicationFeed オブジェクトを作成し、必要に応じてそのプロパティを設定して、SyndicationItem のリストを作成します。そしてそのリストを SyndicationFeed オブジェクトに関連付けた後 (この処理は自動では行われません)、データを含む SyndicationItem をリストに追加します (MSDN Magazine Web サイトからコード全体をダウンロードできるため、ここでは簡潔さを重視して、ヘルパ メソッドを一部省略しています)。
何を公開するかによって (RSS、Atom、またはその両方)、SyndicationItem プロパティの設定は若干複雑になりますが、基本的には Title、PublishedDate、LastUpdatedDate、および Content プロパティを設定します。
このコードでもう 1 つ注意すべきなのは、LastUpdatedTime と PublishDate が DateTimeOffset 型であることです。これは、正確な日時とタイム ゾーンの処理を簡素化するために .NET Framework 3.5 で追加された新しい型です。
Title と Content は、皆さんが考えておられるものとは若干異なります。Title の型は TextSyndicationContent で、Content の型は SyndicationContent 基本型です。これらの型や主要な派生型である XmlSyndicationContent は、コンテンツの含まれるフィードのさまざまな部分を管理するために使用されますが、フィードに含まれるコンテンツに応じて変わることがあります。たとえば、SyndicationItem.Content プロパティには、プレーン テキスト、何らかの形の XML (XHTML や HTML も可)、何らかの種類のバイナリ コンテンツへのリンク (この場合の型は UrlSyndicationContent) を設定できます。SyndicationContent は、フィード アイテム内のデータのこれらすべての型をサポートする、必須の間接層です。
このフィードの準備が整ったら、フィードのユーザー エージェント要求を行うことができます。そして Internet Explorer で他のフィード リーダー ユーザー エージェントと同じようにフィードを取得し、ユーザーはそれをサブスクライブできます。
多くのサイトやサービスを Atom に移行させている要因の 1 つが、Atom Publishing Protocol (AtomPub) です。Atom はフィードの形式であり、AtomPub はリソースの取得、作成、更新に関する仕様です。AtomPub は REST の制約に基づいて構築された仕様なので、REST を理解しておけば、AtomPub を難なく扱うことができます。ほとんどの対話は Atom インスタンスで行われるため、形式もよく知られています。
AtomPub の大部分は Atom フィードに関係するものですが、サービス ドキュメントとカテゴリという 2 つの新しいドキュメントの種類があります。.NET Framework 3.5 SP1 では、これらの新しいドキュメントの種類をサポートする 2 つの新しいオブジェクトを通じて、AtomPub をサポートしています (.NET Framework 3.5 でも AtomPub の実装は可能ですが、SP1 には作業を楽にしてくれる機能が追加されています)。
AtomPub サービス ドキュメントは、ユーザー エージェントに対し、特定の AtomPub エンドポイントがどのようなワークスペースをサポートしているかを通知するメタデータ ドキュメントです。ワークスペースはメンバ リソースのコレクションであり、メンバ リソースは、実際には特定の Atom フィードへのハイパーリンクです。サービス ドキュメントでは、各フィードがサポートするメディアの種類 (たとえば、イメージやその他のバイナリ ファイル) などの要素も指定できますが、どのフィードも標準的な Atom エントリをサポートしている必要があります。
AtomPub 仕様では、各フィード (メンバ リソース) に対する統一インターフェイスの使用方法も規定されています。この対応関係を図 5 に示します。
図 5 統一インターフェイスの AtomPub アプリケーション |
リソース | 統一インターフェイスのメソッド | 説明 |
サービス ドキュメント | GET | ユーザー エージェントは、URI を把握した後、GET でサービス ドキュメントを取得できます。 |
カテゴリ ドキュメント | GET | カテゴリの表現を取得するために使用します。 |
コレクション | GET | 表現、つまり Atom フィードを取得します。 |
コレクション | POST | 新しい Atom エントリを作成します。 |
メンバ | GET | 個別のメンバ (個別の Atom エントリやバイナリ ファイル) を取得します。 |
メンバ | PUT | メンバを変更します。 |
メンバ | DELETE | メンバを削除します。 |
SP1 で追加された型は ServiceDocument (SyndicationItem と似ています) と AtomPub10ServiceDocumentFormatter (SyndicationFeedFormatter と同じ働きをします) です。サービス ドキュメント内の各コレクションを表す ResourceCollectionInfo という名前の型もあります。この型は、ServiceDocument と関係があります。この関係は、SyndicationFeed と SyndicationItem の関係に少し似ています。ServiceDocument はサービス ドキュメント自体のメイン コンテンツを生成するために ResourceCollectionInfo のリストを保持するためです。
エンドポイントで AtomPub をサポートするためには、まず別のメソッドをコントラクトに追加する必要があります。
[OperationContract]
[WebGet(UriTemplate = "/servicedoc")]
AtomPub10ServiceDocumentFormatter GetServiceDoc();
その後で、図 6 に示すような実装を提供できます。これにより、図 7 のサービス ドキュメントが生成されます。
図 6 AtomPub サービス ドキュメントの実装
public AtomPub10ServiceDocumentFormatter GetServiceDoc() {
OutgoingWebResponseContext ctx =
WebOperationContext.Current.OutgoingResponse;
ctx.ContentType = "application/atomsvc+xml";
AtomPub10ServiceDocumentFormatter ret = null;
//create the ServiceDocument type
ServiceDocument doc = new ServiceDocument();
IncomingWebRequestContext ictx =
WebOperationContext.Current.IncomingRequest;
//set the BaseUri to the current request URI
doc.BaseUri = ictx.UriTemplateMatch.RequestUri;
//create a Collection of resources
List<ResourceCollectionInfo> resources =
new List<ResourceCollectionInfo>();
//create the Blog resource
ResourceCollectionInfo mainBlog =
new ResourceCollectionInfo("MSDNMagazine",
new Uri("feed", UriKind.Relative));
//add the Accepts for this resource
//remember this is the default if no accepts if present
mainBlog.Accepts.Add("application/atom+xml;type=entry");
resources.Add(mainBlog);
//create the Pictures resource
ResourceCollectionInfo mainPictures =
new ResourceCollectionInfo("Pictures",
new Uri("pictures", UriKind.Relative));
//add the Accepts for this resource
mainPictures.Accepts.Add("image/png");
mainPictures.Accepts.Add("image/jpeg");
mainPictures.Accepts.Add("image/gif");
resources.Add(mainPictures);
//create the Workspace
Workspace main = new Workspace("Main", resources);
//add the Workspace to the Service Document
doc.Workspaces.Add(main);
//get the formatter
ret = doc.GetFormatter()
as AtomPub10ServiceDocumentFormatter;
return ret;
}
図 7 サービスを定義する
<?xml version="1.0" encoding="utf-8"?>
<service xml:base="http://localhost:1355/Issues.svc/servicedoc"
xmlns="http://www.w3.org/2007/app"
xmlns:a10="http://www.w3.org/2005/Atom">
<app:workspace xmlns:app="http://www.w3.org/2007/app">
<a10:title type="text">Main</a10:title>
<app:collection href="feed">
<a10:title type="text">MSDNMagazine</a10:title>
<app:accept>application/atom+xml;type=entry</app:accept>
</app:collection>
<app:collection href="pictures">
<a10:title type="text">Pictures</a10:title>
<app:accept>image/png</app:accept>
<app:accept>image/jpeg</app:accept>
<app:accept>image/gif</app:accept>
</app:collection>
</app:workspace>
</service>
このサービス ドキュメントでは、2 つのコレクションを含む Main という名前のワークスペースが 1 つあることを通知します。一方のコレクションには "feed" の相対 URI が含まれており、既定のメディアの種類 (Atom エントリのメディアの種類) がその入力として使用されます。もう一方のコレクションはバイナリ ファイル (具体的にはイメージ ファイル) を保持しており (メディアの種類はリストされているものに制限されます)、"pictures" の URI が含まれています。このドキュメントにより、ユーザー エージェントは、図 5 に示した規則に則って AtomPub エンドポイントと簡単に対話できるようになります。
AtomPub は、ブログやその関連ファイル (イメージなど) のみならず、さまざまなシナリオに適用できる便利な標準です。
フィードを使用する
フィードを使用するために、SyndicationFeed API をクライアントで機能させることもできます。現在使われているフィード形式は多岐にわたるため (そして今後さらに増えると思われます)、フィードの処理はカスタム コードの使用を伴う難しい作業となります。そこで役立つのが、.NET Framework 基本ライブラリに追加された SyndicationFeed API です。次のシンプルなコードは、フィードの使用方法を示しています。
string uri = "http://localhost:1355/Issues.svc/feed";
XmlReader xr = XmlReader.Create(uri);
SyndicationFeed feed = SyndicationFeed.Load(xr);
Console.WriteLine("Feed title:{0}",feed.Title.Text);
foreach (var item in feed.Items) {
Console.WriteLine("Item {0}",item.Title.Text);
}
多くの企業が、サービスとフレームワークを構築するための手段を可能な限り AtomPub に統一しようとしています。ADO.NET Data Services では、AtomPub を使用してデータ エンティティを公開します。そして ADO.NET Data Services は、Microsoft Azure におけるすべてのテーブル、ブログ、キュー機能を提供するために使用されます。Windows Live サービスでは、そのほとんどの公開サービスで AtomPub が使用されています。ここで重要なのは、現在皆さんが構築しているアプリケーションで Atom や AtomPub を公開していなくても、近い将来、AtomPub サービスの操作方法と使用方法を知る必要に迫られる可能性は非常に高いということです。このコラムで紹介した内容が入門用の手引きとしてお役に立てばさいわいです。
ADO.NET Data Services と WCF のどちらが適切か
.NET Framework 3.5 の ADO.NET Data Services と WCF のどちらを使用しても、標準準拠の Web フィードを生成する RESTful サービスを簡単に公開できます。では、ADO.NET Data Services と WCF に組み込まれているサポートは、それぞれどのような状況で使用すればよいのでしょうか。
WCF には、サービス エンドポイントの公開や呼び出しの機能が用意されています。WCF 3.5 では、標準的な SOAP ベースのエンドポイントを作成することも、単純な RESTful サービス インターフェイスのスタイルに従ったエンドポイントを作成することもできます。RESTful エンドポイントを公開するには、リソース識別子を定義するために使用される UriTemplate で、サービス クラス内のメソッドに注釈を付ける必要があります。URI がそのテンプレートに一致すると、メソッドが呼び出され、テンプレートからパラメータが渡されます。サービス コントラクトは、クラス内の一連の注釈付きメソッドで構成されます。
WCF サービスから結果を RSS または Atom 互換フィードとして返すには、メソッド内で、返すコンテンツを表す SyndicationItem のリストを含む SyndicationFeed オブジェクトを作成します。次に、適切な型を持つ SyndicationFeedFormatter を作成するときにこの SyndicationFeed を渡し、メソッドから SyndicationFeedFormatter が返されるようにします。
ADO.NET Data Services は WCF を基に構築されており、エンティティ モデル (Microsoft Entity Framework や他の IQueryable データ ソースによって公開されるモデルなど) に基づいて、クエリの実行が可能な REST ベースのエンドポイントを提供します。ADO.NET Data Services では、モデルがサービス コントラクトになります。このモデルのクエリは、標準的な URI を通じて行うことができます。この URI には、サービスのルートやリソースのパスのほかに、フィルタ処理、並べ替え、ページング、グラフ拡張などのクエリ オプションが含まれます。さらに ADO.NET Data Services は、アクセス許可の制御機能、カスタム サービス操作の公開機能、クエリのインターセプトを通じたリソースへのアクセス方法 (たとえば、ユーザー ベースのセキュリティを実装するためのアクセスの方法) のカスタマイズ機能を提供します。
ADO.NET Data Services は JSON 仕様と AtomPub 仕様をサポートしており、(許可されている) サービスに対し、標準的な HTTP 動詞を使用して挿入、更新、削除を行う機能も用意されています。したがって、ADO.NET Data Services には任意の HTTP クライアントからアクセスできます。
さらに、マイクロソフトは、.NET Client Framework、Silverlight、および Ajax 向けの ADO.NET Data Services クライアントを提供しています。このクライアントを使用すると、厳密に型指定された LINQ ベースの手法で、ADO.NET Data Service に準拠したエンドポイント (ADO.NET Data Services を使用して実装されたエンドポイントか、Azure テーブルなどのカスタム実装を使用して実装されたエンドポイントかは問いません) に対してデータのクエリや更新を行うことができます。
そのため、クエリの実行が可能な REST ベースのモデルを ADO.NET データ プロバイダや IQueryable ソースなどのデータ ソース (メモリ内コレクションを含む) 上で公開し、シンプルな HTTP クライアントまたは厳密に型指定されたクライアントで使用できる JSON または AtomPub 互換の形式で結果を返すには、ADO.NET Data Services に用意されている数多くの機能を使用してください。そうすれば、最小限の作業で済みます。
一方、カスタムのアプリケーション ロジックに基づいてフィードを自ら作成する一連のメソッドを実装する場合は、WCF の組み込み機能を使用してください。フィードを RSS または Atom 互換の形式で返すことのできる RESTful サービスとして、これらのメソッドを簡単に公開できます。
—データ プログラマビリティ担当の主席アーキテクト、Michael Pizzo
ご意見やご質問は、sstation@microsoft.com まで英語でお送りください。
Jon Flanders は、フリーのコンサルタント、講演者、Pluralsight のトレーナーという 3 つの肩書きを持っています。彼は、BizTalk Server、Windows Workflow Foundation、および Windows Communication Foundation のスペシャリストです。Jon のブログのアドレスは masteringbiztalk.com/blogs/jon です。