Este artigo foi traduzido por máquina.

Estação de serviço

Criando E consumindo feeds da Web

Jon Flanders

Download do código disponível na Galeria de código do MSDN
Procure o código on-line

Conteúdo

Feeds da Web
O WCF e feeds
Estrutura de alimentação
Expor um feed
Implementando o feed
AtomPub
Consumindo feeds

NaProblema de 2009 de janeiro de MSDN Magazine, Abordei as noções básicas de usando (REPRESENTATIONAL State Transfer) como a arquitetura para a criação de aplicativos cliente / servidor. Também comecei examinar como você poderia criar esses aplicativos usando os recursos do WCF (Windows Communication Foundation) no Microsoft .NET Framework 3.5.

Este mês, vou falar sobre alguns Web adicional feed recursos do WCF que estão habilitados somente por causa do suporte base. Ao ler anterior coluna Estação de serviço ajudarão a entender este, com segurança você poderá ler essa única sem fazer quaisquer danos a mesmo (embora algum conhecimento de conceitos básicos do WCF REST seja útil).

Feeds da Web já existem para quase uma década como uma forma de aplicativos para extrair informações de World Wide Web. Tradicionalmente usado para expor artigos e informações de blogs, feeds são agora comumente usados para expor outros tipos de dados bem devido a simplicidade da arquitetura.

Feeds são simplesmente os dados XML expostos por meio de um URI de HTTP. Um leitor de feed é responsável pela pesquisa o URI alguns intervalos e, em seguida, processar os dados recuperados. O leitor, quando ele é um aplicativo que se destina a expor os dados feeds para uma pessoa, notificarão o usuário que novos dados estão disponíveis. No caso de um leitor de alimentação automática (que pode ser qualquer código de aplicativo), geralmente alguma ação do aplicativo será acionada pela aquisição de novos dados.

Considerando que vários feeds são expor dados de blog, por que este é o tópico de uma coluna sobre a criação de serviços? A simplicidade do feed formatos para exposição de dados, além da onipresença de leitores de alimentação (e bibliotecas para analisar feeds) levou a muitos outros tipos de dados sejam expostos como feeds. Serviços de dados ADO.NET, por exemplo, é uma camada de dados de habilitados para serviços criada completamente usando tecnologia de alimentação (especificamente usando um padrão embutido no início da Atom chamado Atom Publishing Protocol (AtomPub), que discutirei posteriormente neste artigo). A plataforma Microsoft Windows Azure expõe muito sua funcionalidade de dados dessa forma, como serviços de um número de outras empresas.

Um motivo para o sucesso dos feeds é que eles usar um formato XML bem conhecido e principalmente padronizado. Em vez de usar um formato personalizado por um provedor de dados, a indústria tem adotado dois esquemas de feeds comuns: RSS (Really Simple Syndication) e Atom. RSS é o mais antigo dos dois formatos, e embora Atom surgiu como o padrão amplamente adotado, vários feeds ainda exponham as RSS Atom versões e. Se você estiver criando um serviço, especificamente um serviço RESTful, você também utilizarão a serem consideradas criando-o usando um feed usando RSS ou Atom se o serviço não AtomPub somente leitura, ou usando se o serviço de leitura/gravação.

O WCF e feeds

Na parte superior de seu suporte base para criar pontos de extremidade RESTful, o WCF no .NET Framework 3.5 também inclui suporte para expor feeds. Você pode criar um ponto de extremidade baseado em WCF HTTP e expor feeds usando qualquer formato de feed comuns. O WCF no .NET Framework 3.5 SP1 adiciona suporte adicional para feeds permitindo que você implementar facilmente um ponto de extremidade que oferece suporte à especificação AtomPub.

Em minha opinião, um dos recursos boa do suporte feed no WCF é que ele abstrai os necessário conhecê-profundidade detalhes dos formatos Atom ou RSS. O WCF fornece um modelo de objeto que você usar para criar um gráfico de objeto genérico (o modelo de objeto é mais semelhante Atom, como Atom tem um modelo de um pouco mais sofisticado de RSS). Em seguida, você pode levar de nível superior do gráfico do objeto e passá-lo a outro objeto framework-desde conhecido como um formatador. O formatador se encarrega de serializar os dados de gráfico do objeto no formato de alimentação correto. Isso é como você pode facilmente expor RSS e Atom do mesmo ponto de extremidade — e ele também separa você contra futuras alterações em formatos de feeds, desde então, tudo o que será necessário é um novo formatador. Seu trabalho é preencher o gráfico do objeto com dados. A infra-estrutura se encarrega de converter seus dados em formato de alimentação correto.

Estrutura de alimentação

Antes de eu ir mais, deixe-me falar um pouco sobre a estrutura de feeds e como ela está relacionada ao modelo de objeto do WCF. Feeds são uma maneira bastante simples para expor um conjunto de dados (consulte a Figura 1 ). Um feed (genericamente) inclui um título, uma descrição, uma data publicada, uma data de última-atualizado/hora, bem como uma coleção de itens. Cada um desses itens também é um dado bastante simples, com uma data publicada, um título e conteúdo. O conteúdo geralmente contém os dados importantes, seja que uma entrada de blog, um artigo de jornal ou alguma outra informação. Cada item pode ter hiperlinks que podem vincular a um item individual ou em uma representação alternativa do item (como uma página HTML completa de seus dados em vez de apenas um resumo). Consulte a Figura 1 para uma representação visual de um feed.

fig01.gif

Figura 1 arquitetura de um feed

Imagine que eu queria expor informações sobre artigos MSDN Magazine através de um feed. Primeiro, preciso decidir quais dados para expor via este feed. Embora haja algumas opções, decidi implementar esse exemplo como um feed de todos os problemas e artigos publicados no MSDN Magazine. Quando um leitor de feed obtém uma atualização, ela mostrará cada artigo publicado como um item separado, com um pequeno resumo do artigo como o conteúdo.

Neste exemplo, vou para ser estende o código do minha última coluna, em que criei uma empresa de serviço genérico RESTful para servir dos dados de MSDN Magazine. Novamente, você não necessariamente precise voltar e leia esse artigo para entender esse um, mas há uma finalidade meu escolher neste cenário específico como meu exemplo e, na verdade, aplica aos serviços RESTful e da Web baseados em SOAP. Em geral, um feed é um detalhe de implementação de BOM para adicionar a um serviço existente. A vantagem das WCF é a simples para adicionar um ponto de extremidade feed a praticamente qualquer serviço você já criou-se com o WCF, independentemente do serviço inteiro está RESTful.

Expor um feed

A primeira coisa que vou fazer é estender meu contrato de serviço e a definição para incluir uma operação que pode expor um feed. Para fazer isso, adicionei um novo método chamado GetIssuesFeed para meu IMSDNMagazineService interface (veja a Figura 2 ).

A Figura 2 Adicionando um método 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
  ...
}

Existem algumas coisas a Observação sobre esse método. Primeiro, o tipo de retorno é SyndicationFeedFormatter, parte o WCF feed que chamada anteriormente genericamente o formatador de suporte. Ele fará referência o objeto subjacente que eu tenha preenchido com dados, e ele irá gerar o XML correto feed formatação conforme o tipo do objeto alimentação.

Outra coisa a observar é a propriedade UriTemplate de WebGetAttribute. Isso indica ao WCF que URI cada método deve responder a ou a alça. Nesse caso, o que é de interesse é que o método de GetIssuesFeed possui um modelo URI que é um literal: "/ alimentação". GetIssuesByYear (que é o método RESTful genérico que não tem nada a fazer com feeds) tem um segmento de variável de caminho (" / {ano} ") no seu URI. Desde que a análise de URI e o mecanismo de circulação transforma tudo em uma seqüência de caracteres, parece que esses dois UriTemplates seria em conflito.

As regras de análise de UriTemplate no WCF exigem que uma correspondência literal corresponderá antes de uma correspondência de variável. Assim, se a entrada URI termina com " / alimentação ", ele roteará GetIssuesFeed, mas qualquer outro URI com apenas esse segmento do caminho será roteado para GetIssuesByYear. Observe que ESTOU também usando uma seqüência de caracteres de consulta para indicar que feed formato o cliente está solicitando. (Eu irá retornar RSS somente se solicitado especificamente; caso contrário, será retorno Atom.)

A terceira coisa de interesse no método GetIssuesFeed é ServiceKnownTypeAttribute. Esse atributo é usado pelo WCF para informar sua camada de serialização de quaisquer classes derivadas do valor de retorno que pode ser passado como o valor de retorno real (que ele precisa para executar corretamente a serialização). Nesse caso, quero potencialmente retornar os dois formatos de e para que eu tenha duas declarações de ServiceKnownTypeAttribute, cada referência a classe de SyndicationFeedFormatter derivada: AtomFeedFormatter e Rss20FeedFormatter. Ele é bastante óbvio de nomes de classe, mas AtomFeedFormatter retorna um feed usando o formato Atom e Rss20FeedFormatter retorna um feed usando o formato de RSS 2.0. Isso é normal apenas WCF infra-estrutura, mas você pode não ter visto essa funcionalidade, a menos que você tentou fazer polimorfismo com valores de retorno WCF antes.

Implementando o feed

Uau, isso é tudo isso sem obter a implementação. A implementação é relativamente fácil, pois apenas ela precisa levar meus dados sobre problemas e artigos e transferir os dados para o modelo de objeto do WCF. O modelo de objeto não esteja baseado em torno SyndicationFeedFormatter, lembre-se que o objeto que faz a formatação. O modelo de objeto centros em torno de um tipo chamado SyndicationFeed (veja a Figura 3 ). Um objeto SyndicationFeed pode ser usado para obter um SyndicationFeedFormatter válido, e ele é o objeto que mantém para cada item de alimentação. Os itens são parte da coleção SyndicationFeed.Items.

fig03.gif

A Figura 3 modelo de objeto SyndicationFeed

O modelo de objeto SyndicationFeed segue a idéia de um feed genérico, embora seu modelo é gerado um pouco para Atom (com as coleções de autores e links, bem como as propriedades de conteúdo e resumo em SyndicationItem). a Figura 4 mostra o código que implementa o método GetIssuesFeed no meu serviço.

A Figura 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;
}

Isso é uncomplicated código e segue o mesmo padrão básico como todos os alimentação de código no WCF, que é criar um objeto SyndicationFeed, defina suas propriedades conforme apropriado, crie uma lista de SyndicationItems e depois de associar a lista SyndicationFeed objeto (isso não é feito automaticamente), preenchendo a lista com SyndicationItems contendo seus dados. (Você pode baixar o código completo do site MSDN Magazine, forma por motivos de concisão, ainda não mostrei todos os auxiliares métodos aqui)

Preencher a propriedade SyndicationItem apresente um pouco de complexidade dependendo se você estiver planejando expor RSS ou Atom (ou ambos). Mas, essencialmente, ele é definir as propriedades título, PublishedDate, LastUpdatedDate e conteúdo.

Outra coisa a observar sobre este código é que LastUpdatedTime e PublishDate são do tipo DateTimeOffset, um novo tipo que foi adicionado no .NET Framework 3.5 para simplificar a trabalhar com exatas datas e horas, bem como fuso horário.

Título e conteúdo são um pouco diferentes que você poderia esperar. Título é do tipo TextSyndicationContent e conteúdo é o tipo de SyndicationContent base. Esses tipos (e o outro principal derivado tipo, XmlSyndicationContent) são usados para gerenciar as diferentes partes de feeds que possuem conteúdo, mas eles às vezes, variar o conteúdo que eles contêm. Por exemplo, a propriedade SyndicationItem.Content poderia ter texto sem formatação, alguma forma de XML (mesmo XHTML ou HTML) ou um link para algum tipo de conteúdo (portanto o UrlSyndicationContent tipo) de binário. SyndicationContent é uma camada necessária de indireção oferece suporte a todos os estes tipos diferentes de dados dentro de itens do feeds.

Assim que tiver este feed backup e em execução, POSSO fazer uma solicitação de agente de usuário para ele e o Internet Explorer é feliz pegar o feed e permitir que o usuário inscrever-se ele (como faria com qualquer agente do usuário leitor de feeds).

Outro motivo que muitos sites e serviços estão sendo movidos para Atom é devido Atom Publishing Protocol (AtomPub). Onde Atom é um formato para feeds, AtomPub é uma especificação para recuperar, criar e atualizar os recursos. É uma especificação criada sobre as restrições de REST, portanto, trabalhar com ele é simples uma vez entendido REST. Como a maioria da interação é feito com instâncias Atom, o formato também é bem conhecidas e compreendido.

Maioria das AtomPub centros em torno Atom feeds, mas há dois novos tipos de documento: documento e a categoria de serviço. O .NET Framework 3.5 SP1 adiciona suporte para AtomPub por meio de dois novos objetos que oferecem suporte a esses novos tipos de documento. (Você poderia implementar AtomPub com apenas o .NET Framework 3.5, mas SP1 adiciona recursos que facilitam muito o seu trabalho.)

Um documento de serviço AtomPub é um documento de metadados que informa um agente do usuário sobre quais espaços de trabalho um suporta de ponto de extremidade AtomPub específico. Um espaço de trabalho é um conjunto de recursos de membro, que são realmente hiperlinks para determinado Atom feeds. Enquanto o documento de serviço também pode especificar itens, como qual mídia tipos de cada feed oferece suporte (como imagens ou outros arquivos binários), todos os feeds espera suporte padrão entradas Atom.

A especificação de AtomPub também especifica como usar a interface uniforme em cada feed (recurso de membro). Você pode ver esse mapeamento na Figura 5 .

A Figura 5 AtomPub Application of the interface uniforme
Recurso Método de interface uniforme Descrição
Documento de serviço GET Depois que o URI é conhecido por um agente de usuário, o documento de serviço podem ser recuperado por meio de GET
Documento de categoria GET Usado para obter a representação da categoria
Coleção GET Obtém a representação — um Atom feed
Coleção POST Cria uma nova entrada de Atom
Membro GET Obtém um membro individual, que pode ser uma entrada Atom individual ou um arquivo binário
Membro PUT Modifica um membro
Membro DELETE Exclui um membro

Os tipos de adicionadas pelo SP1 são ServiceDocument (semelhante a SyndicationItem) e AtomPub10ServiceDocumentFormatter (que serve a mesma finalidade que SyndicationFeedFormatter). Também há um tipo chamado ResourceCollectionInfo para representar cada coleção do documento de serviço. Esse tipo tem um relacionamento para ServiceDocument um pouco semelhante à relação entre SyndicationFeed e SyndicationItem, pois ServiceDocument mantiver uma lista de ResourceCollectionInfos para gerar o conteúdo principal do próprio documento serviço.

Para oferecer suporte a AtomPub em minha empresa, primeiro preciso adicionar outro método para o meu Contrato:

[OperationContract]
  [WebGet(UriTemplate = "/servicedoc")]
  AtomPub10ServiceDocumentFormatter GetServiceDoc();

Em seguida, pode fornecer a implementação conforme mostrado na Figura 6 . Isso produzirá o documento de serviço mostrado na Figura 7 .

A Figura 6 Implementação de documento de AtomPub Service

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;
}

A Figura 7 definindo o serviço

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

Este documento de serviço se comunica que há um espaço de trabalho chamado principal que tenha duas coleções. Uma coleção tem o URI relativo de "alimentar" e usa o padrão tipo de mídia como sua entrada (o tipo de mídia para entradas Atom). A coleção contém binário arquivos, especificamente os arquivos de imagem (restritos aos tipos de mídia listados) e tem um URI de imagens. Fornecido neste documento, um agente de usuário pode interagir com facilidade com minha empresa AtomPub seguindo as regras estabelecidas na Figura 5 .

AtomPub é um padrão útil que pode ser aplicado a vários cenários diferentes, não apenas blogs e arquivos associados (como imagens).

Consumindo feeds

A API SyndicationFeed também pode trabalhar no lado do cliente para consumir um feed. Atual vários formatos de feed (e provavelmente haverá mais no futuro) tornar a isso uma tarefa não trivial usando código personalizado, para que este é um acréscimo muito bom para a biblioteca base do .NET Framework. Eis alguns código simples que demonstra o consumo de um feed:

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);
} 

Muitas empresas estão padronização tanto quanto possível ao redor AtomPub para criação de serviços e estruturas. Serviços de dados ADO.NET usa AtomPub para expor as entidades de dados. Por sua vez, serviços de dados ADO.NET é usado para todos os a tabela, blog e a funcionalidade de fila no Microsoft Azure. Windows Live Services está usando AtomPub para a maioria dos seus serviços expostos. O ponto aqui é que, mesmo se você não expor Atom ou AtomPub de quaisquer aplicativos que você está criando, as chances são muito altas que você precisará saber como interagir e consumir serviços AtomPub agora ou em algum momento no futuro próximo. Espera-se que mostrei você aqui ajudará você começar.

Serviços de dados ADO.NET ou WCF?

Serviços de dados ADO.NET e WCF no .NET Framework 3.5 dois fornecem maneiras facilmente expor serviços RESTful que geram compatível com padrões da Web feeds. Portanto, quando deve usar serviços de dados ADO.NET e quando deve você usar o suporte interno no WCF?

O WCF fornece funcionalidade para expor e chamar os pontos de extremidade de serviço. Com o WCF 3.5, pontos de extremidade de serviço podem ser padrão baseado em SOAP ou execute um estilo de interface do serviço RESTful simples. Para expor um ponto de extremidade RESTful, você anotar os métodos em sua classe de serviço com o UriTemplate usado para definir o identificador de recursos. URIs que correspondam ao que resultam de modelo em chamadas para o método, passando nos parâmetros do modelo. O conjunto de métodos com anotações em sua classe formam seu contrato de serviço.

Para retornar resultados de um serviço WCF como um feed RSS ou Atom-compatível, você cria dentro de seu método um objeto de SyndicationFeed contendo a lista de SyndicationItems que representa o conteúdo que você deseja retornar. Você, em seguida, passar esse SyndicationFeed na criação de um SyndicationFeedFormatter do tipo apropriado e retornar esse SyndicationFeedFormatter do seu método.

Serviços de dados ADO.NET está embutido no WCF e fornece um ponto de extremidade com base em REST queryable sobre um modelo de entidades, como um modelo exposto pela estrutura de entidades do Microsoft ou outra fonte de dados IQueryable. Com serviços de dados do ADO.NET, o modelo se torna o contrato de serviço. Esse modelo pode ser consultado por meio de URIs padrão que, em adição ao serviço raiz e de recurso caminho, incluem opções de consulta como filtragem, classificação, paginação e expansão de gráfico. Além disso, serviços de dados ADO.NET fornece recursos para controlar permissões de acesso, expor operações de serviço personalizado e personalizar como os recursos são acessados (por exemplo, para implementação da segurança baseada no usuário) por meio da interceptação de consulta.

Dados ADO.NET Services oferece suporte JSON e AtomPub especificações, incluindo a capacidade de fazer inserções, atualizações e exclui contra o serviço (como permitido) por meio de verbos HTTP padrão. Portanto, serviços de dados ADO.NET pode ser acessados de qualquer cliente HTTP.

Além disso, o Microsoft fornece um cliente de serviços de dados ADO.NET para o .NET Framework do cliente, o Silverlight e AJAX que fornece uma experiência com rigidez de tipos, com base em LINQ para consultar e atualizar dados em uma empresa de serviço de dados ADO.NET-compatível com (se o ponto de extremidade ser implementadas usando serviços de dados do ADO.NET ou uma implementação personalizada, como tabela Azure).

Portanto, se desejar expor um modelo queryable REST-com base em uma fonte de dados, como uma fonte de provedor de dados do ADO.NET ou IQueryable (incluindo coleções de memória) e retornar os resultados em um formato compatível com JSON ou AtomPub que pode ser consumido por meio de um cliente HTTP simples ou um cliente com rigidez de tipos, o ADO.NET Data Services fornece a funcionalidade a maioria para o valor mínimo de trabalho.

Por outro lado, se você quiser implementar um conjunto de métodos que criar manualmente um feed baseia a lógica de aplicativo personalizado, a funcionalidade interna no WCF torna fácil expor esses métodos como um serviço RESTful capaz de retornar o feed em formato RSS ou Atom-compatível.

—Michael Pizzo, arquiteto de segurança, programação de dados

Envie suas dúvidas e comentários para sstation@microsoft.com.

Jon Flanders é um consultor independente, alto-falante e instrutor para pluralsight. Ele especializada no BizTalk Server, Windows Workflow Foundation e o Windows Communication Foundation. Você pode acessar Jon em masteringbiztalk.com/blogs/Jon.