Este artigo foi traduzido por máquina.

OData e AtomPub

Criando um servidor AtomPub usando o WCF Data Services

Chris Sells

Baixe o código de exemplo

Se você não estiver familiarizado com ele, o protocolo de dados aberto (OData) é uma coisa de beleza. Compilações de OData (descrito em detalhes no odata.org de ) em benção baseado em HTTP de Atom para a publicação de dados; AtomPub para criar, atualizar e excluir dados; e o Microsoft Data EDM (modelo entidade) para definir os tipos de dados.

Se você tiver um cliente JavaScript, você pode obter os dados de back diretamente em JSON em vez do formato Atom, e se você tem algo mais — incluindo o Excel, Microsoft .NET Framework, PHP, AJAX e muito mais — há bibliotecas de cliente para formando OData solicitações e respostas OData de consumo. Se você estiver usando o .NET Framework no lado do servidor, a Microsoft também fornece uma biblioteca de fácil de usar, chamada de serviços de dados do WCF para expor os tipos do .NET Framework ou suportados pela Estrutura de Entidade Microsoft como OData origens de bancos de dados. Isso torna mais fácil expor seus dados através da Internet em uma forma baseada em HTTP e padrões.

Dito tudo isso, existem algumas coisas que pode ser que você deseja fazer com OData que não são bastante parte da experiência de imediato, como, por exemplo, integrando OData existentes com base em Atom e AtomPub leitores e gravadores. É o que vamos experimentar.

Blog de Simple

Por exemplo, imagine let’s que estou criando um sistema de seu blog simples (e, na verdade, esse trabalho baseia-se em mim reescrevendo o sistema de gerenciamento de conteúdo em sellsbrothers.com). Eu sou grande fã do primeiro modelo de suporte no Visual Studio 2010, portanto, eu criei um projeto do MVC do asp.net 2. 0, adicionar um EDM do ado.net arquivo chamado MyBlogDB.edmx e dispostos de uma entidade de postagem, conforme mostrado no do Figura 1.

Figura 1 A entidade de Post criada no Visual Studio 2010

Software de seu blog mais complicada deseja rastrear mais dados, mas os campos no do Figura 1 são as noções básicas. Quando eu com o botão direito na superfície de design, eu possa escolher Generate banco de dados de modelo, que mostra o arquivo SQL que será criado por mim (MyBlogDB.sql neste caso) e o SQL será gerado para criar o meu banco de dados. Clicando em ' Concluir ' criar o arquivo SQL e vincular o banco de dados para as entidades que criei no designer do EDM. Os bits importantes de SQL são mostrados em do Figura 2.

Do código do SQL resultantes de “ gerar banco de dados do modelo ”, a Figura 2

...
USE [MyBlogDB];
GO
...
-- Dropping existing tables
IF OBJECT_ID(N'[dbo].[Posts]', 'U') IS NOT NULL
    DROP TABLE [dbo].[Posts];
GO
...
-- Creating table 'Posts'
CREATE TABLE [dbo].[Posts] (
    [Id] int IDENTITY(1,1) NOT NULL,
    [Title] nvarchar(max)  NOT NULL,
    [PublishDate] datetime  NULL,
    [Content] nvarchar(max)  NOT NULL
);
GO
...
-- Creating primary key on [Id] in table 'Posts'
ALTER TABLE [dbo].[Posts]
ADD CONSTRAINT [PK_Posts]
    PRIMARY KEY CLUSTERED ([Id] ASC);
GO

Basicamente, estamos apenas criando uma única tabela de nossa única entidade, conforme o esperado e os campos de mapeamento para tipos de SQL. Observe que o PublishDate é definido como NULL, o que não é o padrão. Explicitamente escolhi essa definição no designer do EDM porque queria que ela seja OK para Don têm uma data de publicação (algumas ferramentas Don fornecem um por padrão).

Para executar esse SQL e crie o banco de dados é apenas uma questão do botão direito do mouse em SQL no editor de texto do Visual Studio e escolhendo Executar SQL. Ele pergunta para suas informações de conexão e o nome de banco de dados. Como esse é um novo banco de dados, você desejará que você digite o novo nome, por exemplo, MyBlogDB e clique em OK para criá-lo quando for solicitado. Quando o banco de dados tiver sido criado, você poderá explorar no Server Explorer, sob a conexão com o Visual Studio criou apenas para você.

Para facilitar os testes, você pode adicionar dados diretamente na tabela clicando em postagens e escolha Show Table Data, que lhe dará uma grade pequena, como mostrado no do Figura 3.

De torna o teste easier a grade de dados de tabela de slides, a Figura 3

Ele não a melhor edição de experiência do mundo, mas é melhor do que escrever instruções SQL até que o que temos uma solução de ponta a ponta edição e em execução (virá-la, continue lendo!).

Agora que temos alguns dados, podemos fazer um pouco do asp.net de codificação para mostrá-la por meio da atualização HomeController.cs (leia mais sobre o MVC em asp.net/mvc/ de ):

...
namespace ODataBloggingSample.Controllers {
  [HandleError]
  public class HomeController : Controller {
    MyBlogDBContainer blogDB = new MyBlogDBContainer();

    public ActionResult Index() {
      return View(blogDB.Posts);
    }

    public ActionResult About() {
      return View();
    }
  }
}

Aqui tudo o que fiz foi criar uma instância da classe MyBlogDBContainer, que é a classe derivada de ObjectContext nível superior criada a partir do nosso arquivo de MyBlogDB.edmx vamos acesso nosso novo banco de dados. (Se você não estiver familiarizado com Estrutura de Entidade, você deve ter: consulte msdn.com/data/aa937723 de ). Quando o método de índice é chamado na classe HomeController, alguém está solicitando a home page do nosso novo aplicativo da Web, nós gostaríamos que você use para mostrar nossas novas postagens de blog, portanto, nós de roteiro a coleção de postagens do banco de dados a uma instância da exibição de Home/Index.aspx, podemos modificar da seguinte forma:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewPage<IEnumerable<ODataBloggingSample.Post>>" %>

<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    <% foreach (var post in Model) { %>
      <h1><%= post.Title %></h1>
      <div><%= post.Content %></div>
      <p><i>Posted <%= post.PublishDate %></i></p>
    <% } %>
</asp:Content>

Aqui, alteramos a classe base para levar a uma coleção do tipo de postagem gerado (juntamente com a classe MyBlogDBContainer) para modelar a nossa tabela de postagens. Além disso, é substituído home page do conteúdo com uma instrução foreach para Mostrar título do cada postagem, conteúdo e a data de publicação.

Isso é tudo o que precisamos. Agora quando executamos o projeto (Debug | Start Debugging), o navegador é iniciado e as postagens de blog são mostradas (apenas um lançar, a menos que você coloque mais do que isso no banco de dados), conforme mostrado no do Figura 4.

Figura 4 da página da Web concluída

Agora, eu lhe disse que tudo até este ponto, de modo que eu poderia dizer isso: O motivo pelo qual que OData é tão fabulosa é que, com um movimento de meu botão do mouse e dois shakes do meu teclado, pode expor uma interface de programação completa que posso acessar a partir de JavaScript, o .NET Framework, PHP e muito mais dados. Para ver essa mágica aconteça, clique com o botão direito no seu projeto no Solution Explorer, escolha Add | New Item, escolha o serviço de dados do WCF, selecione um nome (usei odata.svc) e clique em Adicionar. Você obterá é um esqueleto de código em um arquivo (odata.svc.cs neste caso) que, ignorando a segurança apenas agora, gostaríamos que fazer se pareça com o seguinte:

using System.Data.Services;
using System.Data.Services.Common;
using ODataBloggingSample;

namespace ODataBloggingSample {
  public class odata : DataService<MyBlogDBContainer> {
    public static void InitializeService(DataServiceConfiguration config) {
      config.SetEntitySetAccessRule("*", EntitySetRights.All);
      config.DataServiceBehavior.MaxProtocolVersion =  
        DataServiceProtocolVersion.V2;
    }
  }
}

Observe que podemos já lançada em MyBlogDBContainer — nossa classe de acesso de nível superior do banco de dados — como o parâmetro do modelo para a classe DataService, que é o núcleo dos serviços de dados do WCF no lado do servidor (consulte msdn.com/data/bb931106 de ). A classe DataService nos expor facilmente o nosso banco de dados via HTTP com base no verbo permite criar, ler, atualizar e excluir operações de (CRUD Create) definidas no protocolo OData. O tipo passado para o DataService é examinado para propriedades públicas que expõem coleções. No nosso exemplo, a classe de contexto do objeto gerado pelo Estrutura de Entidade contém a coleção de postagens que se ajuste a Bill está perfeitamente:

...
namespace ODataBloggingSample {
  ...
  public partial class MyBlogDBContainer : ObjectContext {
    ...
    public ObjectSet<Post> Posts {...}
   ...
  }

  ...
  public partial class Post : EntityObject {
    ...
    public global::System.Int32 Id { get { ... } set { ... } }
    public global::System.String Title { get { ... } set { ... } }
    public Nullable<global::System.DateTime> PublishDate { 
      get { ... } set { ... } }
    public global::System.String Content { get { ... } set { ... } }
    ...
  }
}

Observe que o gerado MyBlogDBContainer expõe um ObjectSet (que é apenas um tipo de coleção) chamado de postagens que contém as instâncias do tipo de postagem. Além disso, o tipo de postagem é definido para fornecer o mapeamento entre o ID, título, PublishDate e propriedades de conteúdo para as colunas subjacentes na tabela de postagens que criamos anteriormente.

Com odata.svc in-loco, podemos pode navegar para o documento de serviço expõe nossas propriedades de coleção de contexto de objeto usando o nome do arquivo de ponto de extremidade de serviço de dados na URL, por exemplo, localhost:54423/odata.svc:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<service xml:base="http://localhost:54423/odata.svc/" xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app">
    <workspace>
     <atom:title>Default</atom:title>
      <collection>
        <atom:title>Posts</atom:title>
      </collection>
    </workspace>
</service>

Esse arquivo inteiro é definido pela especificação AtomPub (ietf.org/rfc/rfc5023.txt ). Retirá-lo um nível mais profundo, podemos ver nossas postagens expostas como um conjunto de entradas de Atom no localhost:54423/odata.svc/Posts, conforme mostrado no do Figura 5.

De postagens, exposto como um conjunto de entradas de Atom, a Figura 5

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<feed xml:base="http://localhost:54423/odata.svc/"
  xmlns:d="https://schemas.microsoft.com/ado/2007/08/dataservices"
  xmlns:m=
    "https://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
  xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Posts</title>
  <id>http://localhost:54423/odata.svc/Posts</id>
  <updated>2010-03-15T00:26:40Z</updated>
  <link rel="self" title="Posts" href="Posts" />
  <entry>
    <id>http://localhost:54423/odata.svc/Posts(1)</id>
    <title type="text" />
    <updated>2010-03-15T00:26:40Z</updated>
    <author>
      <name />
    </author>
    <link rel="edit" title="Post" href="Posts(1)" />
    <category term="MyBlogDB.Post"
      scheme=
        "https://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <content type="application/xml">
      <m:properties>
        <d:Id m:type="Edm.Int32">1</d:Id>
        <d:Title>My first blog post</d:Title>
        <d:PublishDate m:type=
          "Edm.DateTime">2010-03-14T00:00:00</d:PublishDate>
        <d:Content>Hi! How are you?</d:Content>
      </m:properties>
    </content>
  </entry>
</feed>

Este arquivo é quase completamente sem formatação-baunilha Atom (ietf.org/rfc/rfc4287.txt ), exceto para os URIs baseados na Microsoft, que são usados para a camada OData funcionalidade em Atom. Especificamente, você desejará observar o elemento “ propriedades ” dentro do elemento “ conteúdo ”. Você irá reconhecer essas propriedades como as mesmas que definiu anteriormente a entidade de postagem e a tabela correspondente de postagens. Esses dados estão contidos no envelope, definido pelo Atom e expostos por meio de comentários CRUD, quais propriamente ditas são definidas pelo AtomPub e
permite a criação, leitura, atualização e exclusão por meio de métodos HTTP POST, GET, PUT e DELETE, respectivamente. O problema é que isso não é muito simples-baunilha-Atom suficiente. Por exemplo, se nós navegar odata.svc/Posts em um leitor de Atom, como o Internet Explorer 8, o título e conteúdo Don vêm por meio de corretamente, conforme mostrado no do Figura 6.

Figura 6 de postagens de blogs do leitor Atom de exibição mostra que o título e conteúdo estão ausentes

Você pode ver que os dados estejam lá (Observe a data está correta e a categoria está sendo exibida), mas o título e conteúdo não sejam vistas. Isso ocorre porque os lugares em que o Internet Explorer está procurando por título e conteúdo — a “ título ” e “ conteúdos ” elementos em cada entrada logicamente — Don contêm o que espera estarão lá. O elemento “ título ” está em branco e o elemento “ conteúdo ” está em um formato que o Internet Explorer não reconhece. O formato que o Internet Explorer realmente gostaria de ver tem esta aparência:

<feed ...>
  <title type="text">Posts</title>
  <id>http://localhost:54423/atompub.svc/Posts</id>
  <updated>2010-03-15T00:42:32Z</updated>
  <link rel="self" title="Posts" href="Posts" />
  <entry>
    <id>http://localhost:54423/atompub.svc/Posts(1)</id>
    <title type="text">My first blog post</title>
    <updated>2010-03-15T00:42:32Z</updated>
    ...
    <content type="html">Hi! How are you?</content>
    <published>2010-03-14T00:00:00-08:00</published>
  </entry>
</feed>

Observe que o elemento “ título ” o que costumava ser incluída na propriedade title do elemento OData “ propriedades ” no elemento “ conteúdo ”, o elemento “ conteúdo ” foi substituído com a propriedade de conteúdo e o elemento “ publicado ” foi adicionado do valor da propriedade PublishDate. Quando esses dados são exibidos no Internet Explorer, podemos obter algo muito mais informações, como o que nós gostaríamos de ter, como mostrado no do Figura 7.

A Figura 7 de Ajustar o formato XML resulta na exibição correta do título e conteúdo

Devo mencionar que é somente para oferecer suporte a ferramentas de blog tem um compromisso, mesmo com. Internet Explorer não está esperando ver uma lista de clientes ou uma nota fiscal, está esperando ver os títulos e publicar as datas e conteúdo em HTML. Às vezes, faz sentido fazer esse mapeamento para a lista de clientes e notas fiscais em que, nesse caso a Microsoft possui um recurso de serviços de dados do WCF chamado “ feeds amigável ” (consulte blogs.msdn.com/astoriateam/archive/ 2008/09/28/making-feeds-friendly.aspx de ). Ele não bastante faz tudo, no entanto (especificamente, ele não remapear o elemento de “ conteúdo ” Atom), pois a equipe de serviços de dados do WCF deseja certificar-se de que mesmo “ amigável ” feeds ainda funcionam com várias bibliotecas de cliente. O objetivo é facilitar as alimentações OData, abandonar não OData em favor de Atom/AtomPub.

Nesse caso, entretanto, estamos abandonando OData e usar apenas os serviços de dados do WCF como nosso ponto de extremidade AtomPub, que requer um mapeamento entre Atom e OData, conforme mostrado no do Figura 8.

A Figura 8 de mapeamento entre Atom e OData

O truque é como podemos obter esse mapeamento de acontecer? É claro que temos os dados, mas precisamos para mapear novamente a Atom propriedades para que os leitores Atom (e criadores) saibam onde os dados é enfiados imediatamente. O motivo para isso é para que os serviços de dados do WCF ainda pode fazer o mapeamento para tipos do .NET Framework ou por meio do Estrutura de Entidade, nossos bancos de dados. Tudo o que precisamos fazer é um mapeamento de na porta de pouca de Atom/AtomPub OData para/de.

O código de exemplo que acompanha este artigo tem alguns códigos para injetar o pipeline do WCF que permite exatamente esse tipo de transformação de dados de mensagem. Você poderá lê-lo à vontade (check-out de ODataBlogging.cs), mas vou mostrar a você como usá-lo.

Primeiro, crie uma nova empresa de serviços de dados do WCF exatamente como fez antes, mas com um nome diferente (usei atompub.svc). Ligar a classe de contexto de objeto de nível superior e a exposição qualquer entidade define você deseja, exatamente como antes, mas também marca o serviço de classe com ODataBloggingServiceBehavior, desta forma:

...
using ODataBlogging;

namespace ODataBloggingSample {
  [ODataBloggingServiceBehavior(typeof(MyBlogDBContainer))]
  [EntityAtomMapping("Posts", "PublishDate", "published")]
  public class atompub : DataService<MyBlogDBContainer> {
    public static void InitializeService(DataServiceConfiguration config) {
      config.SetEntitySetAccessRule("*", EntitySetRights.All);
      config.DataServiceBehavior.MaxProtocolVersion = 
        DataServiceProtocolVersion.V2;
    }
  }
}

Isso faz o mapeamento de Atom/AtomPub chegando — por exemplo, “ título, ” “ ” e conteúdos “ publicados ” elementos — para a correspondente OData Formatar através do elemento aninhado “ propriedades ” dentro do elemento “ conteúdo ”.Por padrão, se os nomes de entidades corresponde ao (ignorando o caso), em seguida, o mapeamento (e o tipo coerção) simplesmente acontecerá.Por exemplo, quando uma entidade é exposta que contém uma propriedade Title (como o nossa entidade Post), ele é mapeado para o elemento de “ título ” Atom.

Por outro lado, se não houver nenhum mapeamento automático, você pode substituir esse comportamento, fornecendo um mapeamento explícito com base no nome da entidade, como fizemos para mapear a propriedade PublishDate para os objetos na coleção “ postagens ” para a propriedade átomo “ publicado ”.Esses dois atributos são suficientes para ativar o nosso OData alimentar em um feed Atom, fornecendo-no modo de exibição completo dos dados, conforme mostrado no do Figura 7.

Esse mapeamento não é unidirecional; ele suporta todos os métodos HTTP, portanto, você pode usar o protocolo AtomPub para criar, atualizar e excluir itens da coleção de postagens bem como lê-las.Isso significa que você pode configurar uma ferramenta como o Windows Live gravador (WLW), que suporta AtomPub como um API do blog, e usá-lo para edição de rich text do suas postagens.Por exemplo, dado o ponto de extremidade do atompub.svc em WLW, você poderia escolher Blogs | adicionar a conta de blogue e preencha as seguintes opções nas caixas de diálogo que se seguem:

  • O serviço de blog que você usa?Outro serviço de blogue
  • Endereço da Web do seu blog: http:// < servidor >>: << porta >> /atompub.svc
  • Nome de usuário: < nome_do_usuário >> (necessária e deve ser implementado em seu ponto de extremidade AtomPub usando técnicas padrão do HTTP)
  • Senha: < senha >>
  • Tipo de blog que você está usando: Atom Publishing Protocol
  • URL do documento de serviço: http:// < servidor >>: << porta >> /atompub.svc
  • Apelido do blog: << tudo o que você gosta >>

Clique em Concluir e você tem um editor de rich text para gerenciar suas postagens de blog, como mostrado no do Figura 9.

A Figura 9 de mapeamento de Atom/OData facilita a criação de um editor de Rich Text para gerenciar suas postagens no Blog

Aqui estamos tiver obtido o mecanismo de serviços de dados, que oferece suporte a funcionalidade completa do CRUD, propriedades de remessa no elemento “ conteúdo ” Atom e tiver feito um pouco de mapeamento para torná-lo a dar suporte a Atom ol' simples e AtomPub, muito.

A biblioteca de amostra pequena que usei para que isso funcione (que criei Phani Raj, um engenheiro de software da Microsoft na equipe de serviços de dados do WCF), faz o mínimo de barest e ele nunca será tudo o que precisa para criar um blogue real.Aqui está uma lista da parte superior da minha cabeça das coisas que ainda precisa de suporte na verdade apenas Atom e AtomPub:

  • Mapeando os Atom autor elemento subelementos, como nome, email e uri.
  • Tratamento de imagens (embora WLW permite o FTP, portanto, isso pode ser o suficiente).
  • Expor recursos para tornar WLW reconhecer esses recursos.

Se você estiver interessado em empurrando nesse experimento ainda mais, Joe Cheng, um membro da equipe WLW, escreveu uma série de postagens no blog sobre o suporte de AtomPub no WLW inspirou esse trabalho em primeiro lugar: jcheng.wordpress.com/2007/10/15/How-WLW-speaks-AtomPub-Introduction.

Aproveite!

Chris Sells é um gerente de programas da Microsoft na divisão de plataforma comercial. Ele escreveu vários livros, incluindo o com co-autoria “ programação WPF ” (O’Reilly Media, 2007), “ Windows Forms 2. 0 Programming ” (Addison-Wesley Professional, 2006) e “ ATL Internals ” (Addison-Wesley Professional, 1999). Em seu tempo livre, ele hospeda várias conferências e faz com que um pest de si mesmo nas listas de discussão em equipe Microsoft internos do produto. Obter mais informações sobre Sells e seus vários projetos, estão disponíveis em sellsbrothers.comde .

Meus agradecimentos aos seguinte especialista técnico para revisar este artigo:*** Pablo Castro***