Notas de versão do ASP.NET and Web Tools para Visual Studio 2013

pela Microsoft

Este documento descreve a versão do ASP.NET and Web Tools para Visual Studio 2013.

Sumário

Novos recursos no ASP.NET and Web Tools para Visual Studio 2013

Notas de instalação

ASP.NET and Web Tools para Visual Studio 2013 são agrupadas no instalador do main e podem ser baixadas aqui.

Documentação

Tutoriais e outras informações sobre ASP.NET and Web Tools para Visual Studio 2013 estão disponíveis no site do ASP.NET.

Requisitos de software

ASP.NET and Web Tools requer Visual Studio 2013.

Novos recursos no ASP.NET and Web Tools para Visual Studio 2013

As seções a seguir descrevem os recursos que foram introduzidos na versão.

Um ASP.NET

Com o lançamento de Visual Studio 2013, demos um passo em direção à unificação da experiência de uso de tecnologias ASP.NET, para que você possa misturar e corresponder facilmente aos desejados. Por exemplo, você pode iniciar um projeto usando o MVC e adicionar facilmente Web Forms páginas ao projeto posteriormente ou realizar scaffold de APIs Web em um projeto Web Forms. Uma ASP.NET é tornar mais fácil para você, como desenvolvedor, fazer as coisas que você ama em ASP.NET. Não importa qual tecnologia você escolher, você pode ter confiança de que está se baseando na estrutura subjacente confiável do One ASP.NET.

Nova experiência de projeto Web

Aprimoramos a experiência de criação de novos projetos Web no Visual Studio 2013. Na caixa de diálogo Novo projeto Web ASP.NET, você pode selecionar o tipo de projeto desejado, configurar qualquer combinação de tecnologias (Web Forms, MVC, API Web), configurar opções de autenticação e adicionar um projeto de teste de unidade.

Novo projeto de ASP.NET

A nova caixa de diálogo permite que você altere as opções de autenticação padrão para muitos dos modelos. Por exemplo, ao criar um projeto de ASP.NET Web Forms, você pode selecionar qualquer uma das seguintes opções:

  • Sem Autenticação
  • Contas de usuário individuais (ASP.NET associação ou logon de provedor social)
  • Contas organizacionais (Active Directory em um aplicativo da Internet)
  • Autenticação do Windows (Active Directory em um aplicativo de intranet)

Opções de autenticação

Para obter mais informações sobre o novo processo de criação de projetos Web, consulte Criando projetos Web ASP.NET em Visual Studio 2013. Para obter mais informações sobre as novas opções de autenticação, consulte ASP.NET Identity mais adiante neste documento.

ASP.NET Scaffolding

ASP.NET Scaffolding é uma estrutura de geração de código para aplicativos Web ASP.NET. Isso facilita a adição de código clichê ao seu projeto que interage com um modelo de dados.

Nas versões anteriores do Visual Studio, o scaffolding era limitado a ASP.NET projetos MVC. Com Visual Studio 2013, agora você pode usar scaffolding para qualquer projeto de ASP.NET, incluindo Web Forms. Visual Studio 2013 atualmente não dá suporte à geração de páginas para um projeto Web Forms, mas você ainda pode usar scaffolding com Web Forms adicionando dependências MVC ao projeto. O suporte para gerar páginas para Web Forms será adicionado em uma atualização futura.

Ao usar scaffolding, garantimos que todas as dependências necessárias estejam instaladas no projeto. Por exemplo, se você começar com um projeto ASP.NET Web Forms e usar scaffolding para adicionar um Controlador de API Web, os pacotes e referências do NuGet necessários serão adicionados ao projeto automaticamente.

Para adicionar o scaffolding do MVC a um projeto Web Forms, adicione um novo item scaffolded e selecione Dependências do MVC 5 na janela de diálogo. Há duas opções para scaffolding MVC; Mínimo e Completo. Se você selecionar Mínimo, somente os pacotes NuGet e as referências para ASP.NET MVC serão adicionados ao seu projeto. Se você selecionar a opção Completo, as Dependências mínimas serão adicionadas, bem como os arquivos de conteúdo necessários para um projeto MVC.

O suporte para controladores assíncronos de scaffolding usa os novos recursos assíncronos do Entity Framework 6.

Para obter mais informações e tutoriais, consulte ASP.NET Visão geral do scaffolding.

O novo recurso Link do Navegador permite conectar vários navegadores ao Visual Studio e atualizá-los todos clicando em um botão na barra de ferramentas. Você pode conectar vários navegadores ao seu site de desenvolvimento, incluindo emuladores móveis, e clicar em atualizar para atualizar todos os navegadores ao mesmo tempo. O Link do Navegador também expõe uma API para permitir que os desenvolvedores escrevam extensões de Link do Navegador.

Captura de tela do menu do Visual Studio, com o ícone Atualizar realçado e Painel de Link do Navegador realçado no menu suspenso.

Ao permitir que os desenvolvedores aproveitem a API de Link do Navegador, torna-se possível criar cenários muito avançados que cruzam os limites entre o Visual Studio e qualquer navegador conectado. O Web Essentials aproveita a API para criar uma experiência integrada entre o Visual Studio e as ferramentas de desenvolvedor do navegador, o controle remoto de emuladores móveis e muito mais.

Aprimoramentos do Editor da Web do Visual Studio

Visual Studio 2013 inclui um novo editor de HTML para arquivos Razor e arquivos HTML em aplicativos Web. O novo editor de HTML fornece um único esquema unificado com base em HTML5. Ele tem preenchimento automático de chaves, interface do usuário do jQuery e atributo AngularJS IntelliSense, agrupamento intelliSense de atributo, ID e nome de classe Intellisense e outras melhorias, incluindo melhor desempenho, formatação e SmartTags.

A captura de tela a seguir demonstra como usar o atributo Bootstrap IntelliSense no editor de HTML.

IntelliSense no editor de HTML

Visual Studio 2013 também vem com editores CoffeeScript e LESS internos. O editor LESS vem com todos os recursos interessantes do editor CSS e tem o IntelliSense específico para variáveis e mixins em todos os documentos LESS na @import cadeia.

Suporte do Serviço de Aplicativo do Azure Aplicativos Web no Visual Studio

Em Visual Studio 2013 com o SDK do Azure para .NET 2.2, você pode usar o Servidor Explorer para interagir diretamente com seus aplicativos Web remotos. Você pode entrar em sua conta do Azure, criar novos aplicativos Web, configurar aplicativos, exibir logs em tempo real e muito mais. Em breve, após o lançamento do SDK 2.2, você poderá ser executado no modo de depuração remotamente no Azure. A maioria dos novos recursos para Serviço de Aplicativo do Azure Aplicativos Web também funcionam no Visual Studio 2012 quando você instala a versão atual do SDK do Azure para .NET.

Para saber mais, consulte os recursos a seguir:

Aprimoramentos de publicação na Web

Visual Studio 2013 inclui recursos novos e aprimorados de Publicação na Web. Veja algumas opções:

Para obter mais informações sobre ASP.NET implantação da Web, consulte o site ASP.NET.

NuGet 2.7

O NuGet 2.7 inclui um conjunto avançado de novos recursos que são descritos detalhadamente em Notas de Versão do NuGet 2.7.

Esta versão do NuGet também remove a necessidade de fornecer consentimento explícito para o recurso de restauração de pacote do NuGet baixar pacotes. O consentimento (e a caixa de seleção associada na caixa de diálogo de preferências do NuGet) agora é concedido instalando o NuGet. Agora, a restauração do pacote simplesmente funciona por padrão.

Web Forms do ASP.NET

Um ASP.NET

Os modelos de projeto Web Forms integram-se perfeitamente à nova experiência do One ASP.NET. Você pode adicionar suporte a MVC e API Web ao projeto Web Forms e configurar a autenticação usando o assistente de criação de projeto one ASP.NET. Para obter mais informações, consulte Criando projetos Web ASP.NET no Visual Studio 2013.

ASP.NET Identity

Os modelos de projeto Web Forms dão suporte à nova estrutura de identidade ASP.NET. Além disso, os modelos agora dão suporte à criação de um projeto de intranet Web Forms. Para obter mais informações, consulte Métodos de autenticação na criação de projetos Web ASP.NET no Visual Studio 2013.

Bootstrap

Os modelos de Web Forms usam Bootstrap para fornecer uma aparência elegante e responsiva que você pode personalizar facilmente. Para obter mais informações, consulte Bootstrap nos modelos de projeto Web Visual Studio 2013.

ASP.NET MVC 5

Um ASP.NET

Os modelos de projeto do Web MVC integram-se perfeitamente à nova experiência do One ASP.NET. Você pode personalizar seu projeto do MVC e configurar a autenticação usando o assistente de criação de projeto one ASP.NET. Um tutorial introdutório para ASP.NET MVC 5 pode ser encontrado em Introdução com ASP.NET MVC 5.

Para obter informações sobre como atualizar projetos do MVC 4 para o MVC 5, consulte How to Upgrade an ASP.NET MVC 4 and Web API Project to ASP.NET MVC 5 and Web API 2.

ASP.NET Identity

Os modelos de projeto do MVC foram atualizados para usar ASP.NET Identity para autenticação e gerenciamento de identidades. Um tutorial com a autenticação do Facebook e do Google e a nova API de associação podem ser encontrados em Criar um aplicativo MVC 5 ASP.NET com Facebook e Google OAuth2 e Logon do OpenID e Criar um aplicativo MVC ASP.NET com autenticação e banco de dados SQL e implantar em Serviço de Aplicativo do Azure.

Bootstrap

O modelo de projeto do MVC foi atualizado para usar o Bootstrap para fornecer uma aparência elegante e responsiva que você pode personalizar facilmente. Para obter mais informações, consulte Bootstrap nos modelos de projeto Web Visual Studio 2013.

Filtros de autenticação

Os filtros de autenticação são um novo tipo de filtro em ASP.NET MVC que são executados antes dos filtros de autorização no pipeline do ASP.NET MVC e permitem que você especifique a lógica de autenticação por ação, por controlador ou globalmente para todos os controladores. Os filtros de autenticação processam credenciais na solicitação e fornecem uma entidade de segurança correspondente. Os filtros de autenticação também podem adicionar desafios de autenticação em resposta a solicitações não autorizadas.

Substituições de filtro

Agora você pode substituir quais filtros se aplicam a um determinado método de ação ou controlador especificando um filtro de substituição. Os filtros de substituição especificam um conjunto de tipos de filtro que não devem ser executados para um determinado escopo (ação ou controlador). Isso permite configurar filtros que se aplicam globalmente, mas, em seguida, excluir determinados filtros globais da aplicação a ações ou controladores específicos.

Roteamento de atributo

ASP.NET MVC agora dá suporte ao roteamento de atributos, graças a uma contribuição de Tim McCall, autor de http://attributerouting.net. Com o roteamento de atributo, você pode especificar suas rotas anotando suas ações e controladores.

ASP.NET Web API 2

Roteamento de atributo

ASP.NET Web API agora dá suporte ao roteamento de atributos, graças a uma contribuição de Tim McCall, autor de http://attributerouting.net. Com o roteamento de atributo, você pode especificar suas rotas de API Web anotando suas ações e controladores desta forma:

[RoutePrefix("orders")] 
public class OrdersController : ApiController 
{ 
    [Route("{id}")] 
    public Order Get(int id) { } 
    [Route("{id}/approve")] 
    public Order Approve(int id) { } 
}

O roteamento de atributo oferece mais controle sobre os URIs em sua API Web. Por exemplo, você pode definir facilmente uma hierarquia de recursos usando um único controlador de API:

public class MoviesController : ApiController 
{ 
    [Route("movies")] 
    public IEnumerable<Movie> Get() { } 
    [Route("actors/{actorId}/movies")] 
    public IEnumerable<Movie> GetByActor(int actorId) { } 
    [Route("directors/{directorId}/movies")] 
    public IEnumerable<Movie> GetByDirector(int directorId) { } 
}

O roteamento de atributo também fornece uma sintaxe conveniente para especificar parâmetros opcionais, valores padrão e restrições de rota:

// Optional parameter
[Route("people/{name?}")]
// Default value
[Route("people/{name=Dan}")]
// Constraint: Alphabetic characters only. 
[Route("people/{name:alpha}")]

Para obter mais informações sobre o roteamento de atributos, consulte Roteamento de atributos na API Web 2.

OAuth 2.0

Os modelos de projeto API Web e Aplicativo de Página Única agora dão suporte à autorização usando o OAuth 2.0. O OAuth 2.0 é uma estrutura para autorizar o acesso do cliente a recursos protegidos. Ele funciona para uma variedade de clientes, incluindo navegadores e dispositivos móveis.

O suporte para OAuth 2.0 baseia-se no novo middleware de segurança fornecido pelos Componentes OWIN da Microsoft para autenticação de portador e implementação da função de servidor de autorização. Como alternativa, os clientes podem ser autorizados usando um servidor de autorização organizacional, como o Azure Active Directory ou o ADFS no Windows Server 2012 R2.

Melhorias do OData

Suporte para $select, $expand, $batch e $value

ASP.NET Web API OData agora tem suporte total para $select, $expand e $value. Você também pode usar $batch para solicitar envio em lote e processamento de conjuntos de alterações.

As opções $select e $expand permitem alterar a forma dos dados retornados de um ponto de extremidade OData. Para obter mais informações, consulte Introdução ao suporte $select e $expand no OData da API Web.

Extensibilidade aprimorada

Os formatadores OData agora são extensíveis. Você pode adicionar metadados de entrada atom, dar suporte a entradas de link de fluxo e mídia nomeadas, adicionar anotações de instância e personalizar como os links são gerados.

Suporte sem tipo

Agora você pode criar serviços OData sem precisar definir tipos CLR para seus tipos de entidade. Em vez disso, seus controladores OData podem usar ou retornar instâncias de IEdmObject, que são os formatadores OData serializar/desserializar.

Reutilizar um modelo existente

Se você já tiver um EDM (modelo de dados de entidade) existente, agora poderá reutilizá-lo diretamente, em vez de precisar criar um novo. Por exemplo, se você estiver usando o Entity Framework, poderá usar o EDM que o EF compila para você.

Solicitar envio em lote

O envio em lote de solicitações combina várias operações em uma única solicitação HTTP POST, para reduzir o tráfego de rede e fornecer uma interface do usuário mais suave e menos tagarela. ASP.NET Web API agora dá suporte a várias estratégias para solicitar envio em lote:

  • Use o ponto de extremidade $batch de um serviço OData.
  • Empacotar várias solicitações em uma única solicitação mime de várias partes.
  • Use um formato de envio em lote personalizado.

Para habilitar o envio em lote de solicitações, basta adicionar uma rota com um manipulador de envio em lote à configuração da API Web:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
        config.Routes.MapHttpBatchRoute( 
            routeName: "WebApiBatch", 
            routeTemplate: "api/batch", 
            batchHandler: new DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer)); 
    } 
}

Você também pode controlar se as solicitações ou executadas sequencialmente ou em qualquer ordem.

Cliente de ASP.NET Web API portátil

Agora você pode usar o cliente ASP.NET Web API para criar bibliotecas de classes portáteis que funcionam em sua Windows Store e aplicativos Windows Phone 8. Você também pode criar formatadores portáteis que podem ser compartilhados entre o cliente e o servidor.

Capacidade de teste aprimorada

A API Web 2 facilita muito o teste de unidade dos controladores de API. Basta instanciar seu controlador de API com sua mensagem de solicitação e configuração e, em seguida, chamar o método de ação que você deseja testar. Também é fácil simular a classe UrlHelper para métodos de ação que executam a geração de link.

IHttpActionResult

Agora você pode implementar IHttpActionResult para encapsular o resultado de seus métodos de ação da API Web. Um IHttpActionResult retornado de um método de ação da API Web é executado pelo runtime ASP.NET Web API para produzir a mensagem de resposta resultante. Um IHttpActionResult pode ser retornado de qualquer ação de API Web para simplificar o teste de unidade da implementação da API Web. Para conveniência, várias implementações de IHttpActionResult são fornecidas prontas para uso, incluindo resultados para retornar códigos de status específicos, conteúdo formatado ou respostas negociadas por conteúdo.

HttpRequestContext

O novo HttpRequestContext rastreia qualquer estado vinculado à solicitação, mas não está disponível imediatamente na solicitação. Por exemplo, você pode usar o HttpRequestContext para obter dados de rota, a entidade de segurança associada à solicitação, o certificado do cliente, o UrlHelper e a raiz do caminho virtual. Você pode criar facilmente um HttpRequestContext para fins de teste de unidade.

Como a entidade de segurança da solicitação é fluida com a solicitação em vez de depender de Thread.CurrentPrincipal, a entidade de segurança agora está disponível durante todo o tempo de vida da solicitação enquanto ela está no pipeline da API Web.

CORS

Graças a outra grande contribuição de Brock Allen, ASP.NET agora dá suporte total ao CORS (Cross Origin Request Sharing).

A segurança do navegador impede que uma página da Web envie solicitações do AJAX para outro domínio. CORS é um padrão W3C que permite que um servidor relaxe a política de mesma origem. Usando o CORS, um servidor pode explicitamente permitir algumas solicitações entre origens e rejeitar outras.

A API Web 2 agora dá suporte ao CORS, incluindo o tratamento automático de solicitações de pré-voo. Para saber mais, confira Permitindo solicitações entre origens na ASP.NET Web API.

Filtros de autenticação

Os filtros de autenticação são um novo tipo de filtro em ASP.NET Web API que são executados antes dos filtros de autorização no pipeline de ASP.NET Web API e permitem que você especifique a lógica de autenticação por ação, por controlador ou globalmente para todos os controladores. Os filtros de autenticação processam credenciais na solicitação e fornecem uma entidade de segurança correspondente. Os filtros de autenticação também podem adicionar desafios de autenticação em resposta a solicitações não autorizadas.

Substituições de filtro

Agora você pode substituir quais filtros se aplicam a um determinado método de ação ou controlador, especificando um filtro de substituição. Os filtros de substituição especificam um conjunto de tipos de filtro que não devem ser executados para um determinado escopo (ação ou controlador). Isso permite que você adicione filtros globais, mas exclua alguns de ações ou controladores específicos.

Integração OWIN

ASP.NET Web API agora dá suporte total ao OWIN e pode ser executado em qualquer host compatível com OWIN. Também está incluído um HostAuthenticationFilter que fornece integração com o sistema de autenticação OWIN.

Com a integração do OWIN, você pode auto-hospedar a API Web em seu próprio processo junto com outro middleware OWIN, como o SignalR. Para obter mais informações, consulte Usar o OWIN para Self-Host ASP.NET Web API.

ASP.NET SignalR 2.0

As seções a seguir descrevem os recursos do SignalR 2.0.

Para obter um exemplo de como atualizar um projeto 1.x existente para o SignalR 2.0, consulte Atualizando um projeto do SignalR 1.x.

Criado em OWIN

O SignalR 2.0 foi criado completamente no OWIN (a Open Web Interface para .NET). Essa alteração torna o processo de instalação do SignalR muito mais consistente entre aplicativos SignalR hospedados na Web e auto-hospedados, mas também exigiu várias alterações de API.

MapHubs e MapConnection agora são MapSignalR

Para compatibilidade com os padrões OWIN, esses métodos foram renomeados para MapSignalR. MapSignalR chamado sem parâmetros mapeará todos os hubs (assim como MapHubs na versão 1.x); para mapear objetos PersistentConnection individuais, especifique o tipo de conexão como o parâmetro de tipo e a extensão de URL para a conexão como o primeiro argumento.

O MapSignalR método é chamado em uma classe de inicialização Owin. Visual Studio 2013 contém um novo modelo para uma classe de inicialização Owin; para usar esse modelo, faça o seguinte:

  1. Clique com o botão direito do mouse no projeto
  2. Selecione Adicionar, Novo Item...
  3. Selecione Classe de inicialização Owin. Nomeie a nova classe Startup.cs.

Em um aplicativo Web, a classe de inicialização Owin que contém o MapSignalR método é adicionada ao processo de inicialização do Owin usando uma entrada no nó de configurações do aplicativo do arquivo Web.Config, conforme mostrado abaixo.

Em um aplicativo auto-hospedado, a classe Startup é passada como o parâmetro de tipo do WebApp.Start método .

Mapeando hubs e conexões no SignalR 1.x (do arquivo de aplicativo global em um aplicativo Web):

protected void Application_Start(object sender, EventArgs e) 
{
    // Map all hubs to "/signalr"
    RouteTable.Routes.MapHubs();
    // Map the Echo PersistentConnection to "/echo"
    RouteTable.Routes.MapConnection<myconnection>("echo", "/echo");
}

Mapeando hubs e conexões no SignalR 2.0 (de um arquivo de classe de inicialização Owin):

using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(MyWebApplication.Startup))]

namespace MyWebApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Map all hubs to "/signalr"
            app.MapSignalR();
            // Map the Echo PersistentConnection to "/echo"
            app.MapSignalR<echoconnection>("/echo");
        }
    }
}

Em um aplicativo auto-hospedado, a classe Startup é passada como o parâmetro de tipo para o WebApp.Start método , conforme mostrado abaixo.

string url = "http://localhost:8080";
using (WebApp.Start<startup>(url))
{
    Console.WriteLine("Server running on {0}", url);
    Console.ReadLine();
}

Suporte entre domínios

No SignalR 1.x, as solicitações entre domínios eram controladas por um único sinalizador EnableCrossDomain. Esse sinalizador controlava as solicitações JSONP e CORS. Para maior flexibilidade, todo o suporte a CORS foi removido do componente de servidor do SignalR (os clientes JavaScript ainda usam CORS normalmente se for detectado que o navegador dá suporte a ele), e o novo middleware OWIN foi disponibilizado para dar suporte a esses cenários.

No SignalR 2.0, se o JSONP for necessário no cliente (para dar suporte a solicitações entre domínios em navegadores mais antigos), ele precisará ser habilitado explicitamente definindo EnableJSONP o HubConfiguration objeto como true, conforme mostrado abaixo. O JSONP é desabilitado por padrão, pois é menos seguro que o CORS.

Para adicionar o novo middleware CORS no SignalR 2.0, adicione a Microsoft.Owin.Cors biblioteca ao projeto e chame UseCors antes do middleware do SignalR, conforme mostrado na seção abaixo.

Adicionando Microsoft.Owin.Cors ao seu projeto: para instalar essa biblioteca, execute o seguinte comando no Console do Gerenciador de Pacotes:

Install-Package Microsoft.Owin.Cors

Esse comando adicionará a versão 2.0.0 do pacote ao seu projeto.

Chamando UseCors

Os snippets de código a seguir demonstram como implementar conexões entre domínios no SignalR 1.x e 2.0.

Implementando solicitações entre domínios no SignalR 1.x (do arquivo de aplicativo global)

protected void Application_Start(object sender, EventArgs e) 
{
    var hubConfiguration = new HubConfiguration();
    hubConfiguration.EnableCrossDomain = true;
    RouteTable.Routes.MapHubs(hubConfiguration);
}

Implementando solicitações entre domínios no SignalR 2.0 (de um arquivo de código C#)

O código a seguir demonstra como habilitar CORS ou JSONP em um projeto do SignalR 2.0. Este exemplo de código usa Map e RunSignalR , em vez de MapSignalR, para que o middleware CORS seja executado apenas para as solicitações do SignalR que exigem suporte a CORS (em vez de para todo o tráfego no caminho especificado em MapSignalR.) Map também pode ser usado para qualquer outro middleware que precise ser executado para um prefixo de URL específico, em vez de para todo o aplicativo.

using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Owin;

[assembly: OwinStartup(typeof(MyWebApplication.Startup))]

namespace MyWebApplication
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Branch the pipeline here for requests that start with "/signalr"
            app.Map("/signalr", map =>
            {
                // Setup the CORS middleware to run before SignalR.
                // By default this will allow all origins. You can 
                // configure the set of origins and/or http verbs by
                // providing a cors options with a different policy.
                map.UseCors(CorsOptions.AllowAll);
                var hubConfiguration = new HubConfiguration 
                {
                    // You can enable JSONP by uncommenting line below.
                    // JSONP requests are insecure but some older browsers (and some
                    // versions of IE) require JSONP to work cross domain
                    // EnableJSONP = true
                };
                // Run the SignalR pipeline. We're not using MapSignalR
                // since this branch already runs under the "/signalr"
                // path.
                map.RunSignalR(hubConfiguration);
            });
        }
    }
}

Suporte para iOS e Android por meio de MonoTouch e MonoDroid

O suporte foi adicionado para clientes iOS e Android usando componentes MonoTouch e MonoDroid da biblioteca Xamarin. Para obter mais informações sobre como usá-los, consulte Usando componentes do Xamarin. Esses componentes estarão disponíveis no Repositório Xamarin quando a versão do SignalR RTW estiver disponível.

### Cliente .NET portátil

Para facilitar melhor o desenvolvimento multiplataforma, os clientes Silverlight, WinRT e Windows Phone foram substituídos por um único cliente .NET portátil que dá suporte às seguintes plataformas:

  • NET 4.5
  • Silverlight 5
  • WinRT (.NET para aplicativos da Windows Store)
  • Windows Phone 8

Novo pacote de Self-Host

Agora há um pacote NuGet para facilitar a introdução ao SignalR Self-Host (aplicativos SignalR hospedados em um processo ou em outro aplicativo, em vez de serem hospedados em um servidor Web). Para atualizar um projeto de auto-host criado com o SignalR 1.x, remova o pacote Microsoft.AspNet.SignalR.Owin e adicione o pacote Microsoft.AspNet.SignalR.SelfHost. Para obter mais informações sobre como começar a usar o pacote de auto-host, consulte Tutorial: Auto-host do SignalR.

Suporte ao servidor compatível com versões anteriores

Nas versões anteriores do SignalR, as versões do pacote SignalR usadas no cliente e no servidor precisavam ser idênticas. Para dar suporte a aplicativos de cliente grosso que seriam difíceis de atualizar, o SignalR 2.0 agora dá suporte ao uso de uma versão mais recente do servidor com um cliente mais antigo. Observação: o SignalR 2.0 não dá suporte a servidores criados com versões mais antigas com clientes mais recentes.

Suporte de servidor removido para .NET 4.0

O SignalR 2.0 retirou o suporte para interoperabilidade do servidor com o .NET 4.0. O .NET 4.5 deve ser usado com servidores SignalR 2.0. Ainda há um cliente .NET 4.0 para o SignalR 2.0.

Enviar uma mensagem para uma lista de clientes e grupos

No SignalR 2.0, é possível enviar uma mensagem usando uma lista de IDs de cliente e grupo. Os snippets de código a seguir demonstram como fazer isso.

Enviar uma mensagem para uma lista de clientes e grupos usando PersistentConnection

using Microsoft.AspNet.SignalR;
using System.Collections.Generic;
public class ChatConnection : PersistentConnection
{
    static List<string> ConnectionIds = new List<string>();
    static List<string> groups = new List<string>{"chatGroup", "chatGroup2"};
    protected override System.Threading.Tasks.Task OnReceived(IRequest request, string connectionId, string data)
    {
        Connection.Send(ConnectionIds, data);
        Groups.Send(groups, data);
        return base.OnReceived(request, connectionId, data);
    }
    protected override System.Threading.Tasks.Task OnConnected(IRequest request, string connectionId)
    {
        ConnectionIds.Add(connectionId);
        Groups.Add(connectionId, "chatGroup");
        return base.OnConnected(request, connectionId);
    }
    protected override System.Threading.Tasks.Task OnDisconnected(IRequest request, string connectionId)
    {
        ConnectionIds.Remove(connectionId);
        return base.OnDisconnected(request, connectionId);
    }
}

Enviar uma mensagem para uma lista de clientes e grupos usando Hubs

using Microsoft.AspNet.SignalR;
using System.Collections.Generic;
public class ChatHub : Hub
{
    static List<string> ConnectionIds = new List<string>();
    static List<string> groups = new List<string> { "chatGroup", "chatGroup2" };
    public void Send(string name, string message)
    {
        // Call the broadcastMessage method to update clients.
        Clients.Clients(ConnectionIds).broadcastMessage(name, message);
        Clients.Groups(groups).broadcastMessage(name, message);
    }
    public override System.Threading.Tasks.Task OnConnected()
    {
        ConnectionIds.Add(Context.ConnectionId);
        Groups.Add(Context.ConnectionId, "chatGroup");
        return base.OnConnected();
    }
    public override System.Threading.Tasks.Task OnDisconnected()
    {
        ConnectionIds.Remove(Context.ConnectionId);
        return base.OnDisconnected();
    }
}

Enviar uma mensagem para um usuário específico

Esse recurso permite que os usuários especifiquem qual é a userId baseada em um IRequest por meio de uma nova interface IUserIdProvider:

A interface IUserIdProvider

public interface IUserIdProvider
{
    string GetUserId(IRequest request);
}

Por padrão, haverá uma implementação que usa o IPrincipal.Identity.Name do usuário como o nome de usuário.

Nos hubs, você poderá enviar mensagens para esses usuários por meio de uma nova API:

Usando a API Clients.User

public class MyHub : Hub
{
    public void Send(string userId, string message)
    {
        Clients.User(userId).send(message);
    }
}

Melhor suporte ao tratamento de erros

Os usuários agora podem lançar HubException de qualquer invocação de hub. O construtor do HubException pode receber uma mensagem de cadeia de caracteres e um objeto dados de erro extra. O SignalR serializará automaticamente a exceção e a enviará ao cliente em que ela será usada para rejeitar/falhar a invocação do método hub.

A configuração mostrar exceções de hub detalhadas não tem nenhuma influência no HubException que está sendo enviado de volta ao cliente ou não; ele é sempre enviado.

Código do lado do servidor demonstrando o envio de um HubException para o cliente

public class MyHub : Hub
{
    public void Send(string message)
    {
        if(message.Contains("<script>"))
        {
            throw new HubException("This message will flow to the client", new { user = Context.User.Identity.Name, message = message });
        }

        Clients.All.send(message);
    }
}

Código do cliente JavaScript demonstrando a resposta a um HubException enviado do servidor

myHub.server.send("<script>")
            .fail(function (e) {
                if (e.source === 'HubException') {
                    console.log(e.message + ' : ' + e.data.user);
                }
            });

Código do cliente .NET demonstrando a resposta a um HubException enviado do servidor

try
{
    await myHub.Invoke("Send", "<script>");
}
catch(HubException ex)
{
    Conosle.WriteLine(ex.Message);
}

Teste de unidade mais fácil de hubs

O SignalR 2.0 inclui uma interface chamada IHubCallerConnectionContext em Hubs que facilita a criação de invocações simuladas do lado do cliente. Os snippets de código a seguir demonstram o uso dessa interface com cintos de teste populares xUnit.net e moq.

Teste de unidade do SignalR com xUnit.net

[Fact]
public void HubsAreMockableViaDynamic()
{
    bool sendCalled = false;
    var hub = new MyHub();
    var mockClients = new Mock<IHubCallerConnectionContext>();
    hub.Clients = mockClients.Object;
    dynamic all = new ExpandoObject();
    all.send = new Action<string>(message =>
    {
        sendCalled = true;
    });
    mockClients.Setup(m => m.All).Returns((ExpandoObject)all);
    hub.Send("foo");
    Assert.True(sendCalled);
}

Teste de unidade do SignalR com moq

[Fact]
public interface IClientContract
{
    void send(string message);
}
public void HubsAreMockableViaType()
{
    var hub = new MyHub();
    var mockClients = new Mock<IHubCallerConnectionContext>();
    var all = new Mock<IClientContract>();
    hub.Clients = mockClients.Object;
    all.Setup(m => m.send(It.IsAny<string>())).Verifiable();
    mockClients.Setup(m => m.All).Returns(all.Object);
    hub.Send("foo");
    all.VerifyAll();

Tratamento de erros do JavaScript

No SignalR 2.0, todos os retornos de chamada de tratamento de erro javaScript retornam objetos de erro JavaScript em vez de cadeias de caracteres brutas. Isso permite que o SignalR flua informações mais avançadas para seus manipuladores de erros. Você pode obter a exceção interna da source propriedade do erro.

Código do cliente JavaScript que manipula a exceção Start.Fail

connection.start().fail(function(e) {
    console.log('The error is: ' + e.message);
});

ASP.NET Identity

Novo sistema de associação de ASP.NET

ASP.NET Identity é o novo sistema de associação para aplicativos ASP.NET. ASP.NET Identity facilita a integração de dados de perfil específicos do usuário aos dados do aplicativo. ASP.NET Identity também permite que você escolha o modelo de persistência para perfis de usuário em seu aplicativo. Você pode armazenar os dados em um banco de dados do SQL Server ou outro dispositivo de armazenamento de dados, incluindo dispositivos de armazenamento de dados NoSQL como Tabelas de Armazenamento do Azure. Para obter mais informações, consulte Contas de usuário individuais em Criando projetos Web ASP.NET no Visual Studio 2013.

Autenticação baseada em declarações

ASP.NET agora dá suporte à autenticação baseada em declarações, em que a identidade do usuário é representada como um conjunto de declarações de um emissor confiável. Os usuários podem ser autenticados usando um nome de usuário e senha mantidos em um banco de dados de aplicativo ou usando provedores de identidade social (por exemplo: Contas da Microsoft, Facebook, Google, Twitter) ou usando contas organizacionais por meio do Azure Active Directory ou Serviços de Federação do Active Directory (AD FS) (ADFS).

Integração com o Azure Active Directory e Windows Server Active Directory

Agora você pode criar ASP.NET projetos que usam o Azure Active Directory ou Windows Server Active Directory (AD) para autenticação. Para obter mais informações, consulte Contas organizacionais em Criando projetos Web ASP.NET no Visual Studio 2013.

Integração OWIN

ASP.NET autenticação agora é baseada no middleware OWIN que pode ser usado em qualquer host baseado em OWIN. Para obter mais informações sobre o OWIN, consulte a seção Componentes Microsoft OWIN a seguir.

Componentes do Microsoft OWIN

Open Web Interface for .NET (OWIN) define uma abstração entre servidores Web .NET e aplicativos Web. O OWIN separa o aplicativo Web do servidor, tornando os aplicativos Web independentes do host. Por exemplo, você pode hospedar um aplicativo Web baseado em OWIN no IIS ou hospedá-lo automaticamente em um processo personalizado.

As alterações introduzidas nos componentes do Microsoft OWIN (também conhecido como projeto Katana) incluem novos componentes de servidor e host, novas bibliotecas auxiliares e middleware e um novo middleware de autenticação.

Para obter mais informações sobre OWIN e Katana, consulte Novidades em OWIN e Katana.

Observação: os aplicativos OWIN não podem ser executados no modo clássico do IIS; eles devem ser executados no modo integrado.

Observação: os aplicativos OWIN devem ser executados com confiança total.

Novos servidores e hosts

Com essa versão, novos componentes foram adicionados para habilitar cenários de auto-host. Esses componentes incluem os seguintes pacotes NuGet:

  • Microsoft.Owin.Host.HttpListener. Fornece um servidor OWIN que usa HttpListener para escutar solicitações HTTP e direcioná-las para o pipeline OWIN.
  • Microsoft.Owin.Hosting Fornece uma biblioteca para desenvolvedores que desejam auto-hospedar um pipeline OWIN em um processo personalizado, como um aplicativo de console ou serviço windows.
  • OwinHost. Fornece um executável autônomo que encapsula Microsoft.Owin.Hosting e permite que você hospede automaticamente um pipeline OWIN sem precisar escrever um aplicativo host personalizado.

Além disso, o pacote agora permite que o Microsoft.Owin.Host.SystemWeb middleware forneça dicas para o servidor SystemWeb , indicando que o middleware deve ser chamado durante um estágio de pipeline de ASP.NET específico. Esse recurso é particularmente útil para o middleware de autenticação, que deve ser executado no início do pipeline ASP.NET.

Bibliotecas auxiliares e middleware

Embora você possa escrever componentes OWIN usando apenas as definições de função e tipo da especificação OWIN, o novo Microsoft.Owin pacote fornece um conjunto mais amigável de abstrações. Esse pacote combina vários pacotes anteriores (por exemplo, Owin.Extensions, , Owin.Types) em um único modelo de objeto bem estruturado que pode ser facilmente usado por outros componentes OWIN. Na verdade, a maioria dos componentes do Microsoft OWIN agora usa esse pacote.

Observação

Os aplicativos OWIN não podem ser executados no modo clássico do IIS; eles devem ser executados no modo integrado.

Observação

Os aplicativos OWIN devem ser executados com confiança total.

Esta versão também inclui o pacote Microsoft.Owin.Diagnostics, que inclui middleware para validar um aplicativo OWIN em execução, além de middleware de página de erro para ajudar a investigar falhas.

Componentes de autenticação

Os componentes de autenticação a seguir estão disponíveis.

  • Microsoft.Owin.Security.ActiveDirectory. Habilita a autenticação usando serviços de diretório locais ou baseados em nuvem.
  • Microsoft.Owin.Security.Cookies Habilita a autenticação usando cookies. Esse pacote foi chamado Microsoft.Owin.Security.Formsanteriormente de .
  • Microsoft.Owin.Security.Facebook Habilita a autenticação usando o serviço baseado em OAuth do Facebook.
  • Microsoft.Owin.Security.Google Habilita a autenticação usando o serviço baseado em OpenID do Google.
  • Microsoft.Owin.Security.Jwt Habilita a autenticação usando tokens JWT.
  • Microsoft.Owin.Security.MicrosoftAccount Habilita a autenticação usando contas da Microsoft.
  • Microsoft.Owin.Security.OAuth. Fornece um servidor de autorização OAuth, bem como um middleware para autenticar tokens de portador.
  • Microsoft.Owin.Security.Twitter Habilita a autenticação usando o serviço baseado em OAuth do Twitter.

Esta versão também inclui o Microsoft.Owin.Cors pacote , que contém middleware para processar solicitações HTTP entre origens.

Observação

O suporte para assinatura JWT foi removido na versão final do Visual Studio 2013.

Entity Framework 6

Para obter uma lista de novos recursos e outras alterações no Entity Framework 6, consulte Histórico de versão do Entity Framework.

ASP.NET Razor 3

ASP.NET Razor 3 inclui os seguintes novos recursos:

  • Suporte para edição de tabulação. Anteriormente, o comando Formatar Documento , o recuo automático e a formatação automática no Visual Studio não funcionavam corretamente ao usar a opção Manter Guias . Essa alteração corrige a formatação do Visual Studio para código Razor para formatação de guia.
  • Suporte para regras de reescrita de URL ao gerar links.
  • Remoção do atributo transparente de segurança.

    Observação

    Essa é uma alteração interruptiva e torna o Razor 3 incompatível com o MVC4 e anterior, enquanto o Razor 2 é incompatível com MVC5 ou assemblies compilados em MVC5.

=======

Suspensão do aplicativo ASP.NET

ASP.NET Suspensão de Aplicativos é um recurso de alteração de jogo no .NET Framework 4.5.1 que altera radicalmente a experiência do usuário e o modelo econômico para hospedar um grande número de sites de ASP.NET em um único computador. Para obter mais informações, consulte ASP.NET Suspensão de Aplicativo – hospedagem web compartilhada responsiva do .NET.

Problemas conhecidos e alterações interruptivas

Esta seção descreve problemas conhecidos e alterações interruptivas no ASP.NET and Web Tools para Visual Studio 2013.

NuGet

  • A nova restauração de pacote não funciona no Mono ao usar o arquivo SLN – será corrigida em um próximo download nuget.exe e na atualização do pacote NuGet.CommandLine .
  • A nova restauração de pacote não funciona com projetos Wix – será corrigida em um próximo nuget.exe download e na atualização do pacote NuGet.CommandLine .

ASP.NET Web API

  1. ODataQueryOptions<T>.ApplyTo(IQueryable) não retorna IQueryable<T> sempre, pois adicionamos suporte para $select e $expand.

    Nossos exemplos anteriores para ODataQueryOptions<T> sempre converteram o valor retornado de ApplyTo para IQueryable<T>. Isso funcionou anteriormente porque as opções de consulta com suporte anteriores ($filter, $orderby, , $skip$top) não alteram a forma da consulta. Agora que damos suporte $select e $expand o valor retornado de ApplyTo nem sempre será IQueryable<T> .

    // Sample ODataQueryOptions<T> usage from earlier
    public IQueryable<Customer> Get(ODataQueryOptions<Customer> query)
    {
        IQueryable<customer> result="query.ApplyTo(_customers)" as iqueryable<customer>; return result;
    }
    

    Se você estiver usando o código de exemplo anterior, ele continuará funcionando se o cliente não enviar $select e $expand. No entanto, se você quiser dar suporte $select e $expand precisar alterar esse código para isso.

    public IHttpActionResult Get(ODataQueryOptions<Customer> query)
    {
        IQueryable result = query.ApplyTo(_customers);
        return Ok(result, result.GetType());
    }
     
    private IHttpActionResult Ok(object content, Type type)
    {
        Type resultType = typeof(OkNegotiatedContentResult<>).MakeGenericType(type);
        return Activator.CreateInstance(resultType, content, this) as IHttpActionResult;
    }
    
  2. Request.Url ou RequestContext.Url é nulo durante uma solicitação em lote

    Em um cenário de envio em lote, o UrlHelper é nulo quando acessado de Request.Url ou RequestContext.Url.

    A solução alternativa para esse problema é criar uma nova instância do UrlHelper, como no exemplo a seguir:

    Criando uma nova instância do UrlHelper

    if (RequestContext.Url == null)
    {
        RequestContext.Url = new UrlHelper(Request);
    }
    

ASP.NET MVC

  1. Ao usar o MVC5 e o OrgAuth, se você tiver exibições que fazem a validação AntiForgerToken, poderá encontrar o seguinte erro ao postar dados na exibição:

    Erro:

    Erro de servidor no aplicativo '/'.

    Uma declaração do tipo http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier ou https://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider não estava presente na ClaimsIdentity fornecida. Para habilitar o suporte a tokens anti-falsificação com autenticação baseada em declarações, verifique se o provedor de declarações configurado está fornecendo essas duas declarações nas instâncias ClaimsIdentity geradas. Se o provedor de declarações configurado usar um tipo de declaração diferente como um identificador exclusivo, ele poderá ser configurado definindo a propriedade estática AntiForgeryConfig.UniqueClaimTypeIdentifier.

    Solução alternativa:

    Adicione a seguinte linha em Global.asax para corrigi-la:

    AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;

    Isso será corrigido para a próxima versão.

  2. Depois de atualizar um aplicativo MVC4 para MVC5, crie a solução e inicie-a. Você deve ver o seguinte erro:

    [A] System.Web.WebPages.Razor.Configuration.HostSection não pode ser convertido em [B]System.Web.WebPages.Razor.Configuration.HostSection. O tipo A se origina de 'System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' no contexto 'Default' no local 'C:\windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.WebPages.Razor\v4.0_2.0.0.0__31bf3856ad364e35\System.Web.WebPages.Razor.dll'. O tipo B se origina de 'System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' no contexto 'Default' no local 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\6d05bbd0\e8b5908e\assembly\dl3\c9cbca63\f8910382_6273ce01\System.Web.WebPages.Razor.dll'.

    Para corrigir o erro acima, abra todos os arquivos de Web.config (incluindo os da pasta Exibições) em seu projeto e faça o seguinte:

    1. Atualize todas as ocorrências da versão "4.0.0.0" de "System.Web.Mvc" para "5.0.0.0".

    2. Atualize todas as ocorrências da versão "2.0.0.0" de "System.Web.Helpers", "System.Web.WebPages" e "System.Web.WebPages.Razor" para "3.0.0.0"

      Por exemplo, depois de fazer as alterações acima, as associações de assembly devem ter esta aparência:

      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
        </dependentAssembly>
        <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
        </dependentAssembly>
        <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
        </dependentAssembly>
        <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="5.0.0.0" />
      </dependentAssembly>
      

      Para obter informações sobre como atualizar projetos do MVC 4 para o MVC 5, consulte How to Upgrade an ASP.NET MVC 4 and Web API Project to ASP.NET MVC 5 and Web API 2.

  3. Ao usar a validação do lado do cliente com a Validação Unobtrusive jQuery, às vezes, a mensagem de validação é incorreta para um elemento de entrada HTML com type='number'. O erro de validação de um valor necessário ("O campo Idade é necessário") é mostrado quando um número inválido é inserido em vez da mensagem correta de que um número válido é necessário.

    Esse problema geralmente é encontrado com código scaffolded para um modelo com uma propriedade de inteiro nas exibições Criar e Editar.

    Para contornar esse problema, altere o auxiliar do editor de:

    @Html.EditorFor(person => person.Age)

    Para:

    @Html.TextBoxFor(person => person.Age)

  4. ASP.NET MVC 5 não dá mais suporte à confiança parcial. Os projetos vinculados aos binários MVC ou WebAPI devem remover o atributo SecurityTransparent e o atributo AllowPartiallyTrustedCallers . A remoção desses atributos eliminará erros do compilador, como o seguinte.

    Attempt by security transparent method ‘MyComponent' to access security critical type 'System.Web.Mvc.MvcHtmlString' failed. Assembly 'PagedList.Mvc, Version=4.3.0.0, Culture=neutral, PublicKeyToken=abbb863e9397c5e1' is marked with the AllowPartiallyTrustedCallersAttribute, and uses the level 2 security transparency model. Level 2 transparency causes all methods in AllowPartiallyTrustedCallers assemblies to become security transparent by default, which may be the cause of this exception.

    Observe que, como efeito colateral disso, você não pode usar assemblies 4.0 e 5.0 no mesmo aplicativo. Você precisa atualizar todos eles para 5.0.

Modelo spa com autorização do Facebook pode causar instabilidade no IE enquanto o site está hospedado na zona da intranet

O modelo SPA fornece logon externo com o Facebook. Quando o projeto criado com o modelo está em execução localmente, a entrada pode causar falha no IE.

Solução:

  1. Hospedar o site na zona da Internet; Ou

  2. Teste o cenário em um navegador diferente do IE.

Scaffolding de Web Forms

Web Forms Scaffolding foi removido do VS2013 e estará disponível em uma atualização futura para o Visual Studio. No entanto, você ainda pode usar scaffolding em um projeto Web Forms adicionando dependências MVC e gerando scaffolding para MVC. Seu projeto conterá uma combinação de Web Forms e MVC.

Para adicionar o MVC ao projeto Web Forms, adicione um novo item scaffolded e selecione Dependências do MVC 5. Selecione Mínimo ou Completo, dependendo se você precisa de todos os arquivos de conteúdo, como scripts. Em seguida, adicione um item scaffolded para MVC, que criará exibições e um controlador em seu projeto.

Scaffolding de MVC e API Web – ERRO HTTP 404, Não Encontrado

Se um erro for encontrado ao adicionar um item scaffolded a um projeto, é possível que seu projeto seja deixado em um estado inconsistente. Algumas das alterações feitas serão revertidas, mas outras alterações, como os pacotes NuGet instalados, não serão revertidas. Se as alterações de configuração de roteamento forem revertidas, os usuários receberão um erro HTTP 404 ao navegar para itens com scaffolded.

Solução alternativa:

  • Para corrigir esse erro para MVC, adicione um novo item scaffolded e selecione Dependências do MVC 5 (Mínimo ou Completo). Esse processo adicionará todas as alterações necessárias ao seu projeto.

  • Para corrigir esse erro para a API Web:

    1. Adicione a classe WebApiConfig ao seu projeto.

      public static class WebApiConfig
      {
          public static void Register(HttpConfiguration config)
          {
              config.MapHttpAttributeRoutes();
              config.Routes.MapHttpRoute(
                  name: "DefaultApi",
                  routeTemplate: "api/{controller}/{id}",
                  defaults: new { id = RouteParameter.Optional }
              );
          }
      }
      
      Public Module WebApiConfig
          Public Sub Register(ByVal config As HttpConfiguration)
              config.MapHttpAttributeRoutes()
              config.Routes.MapHttpRoute(
                name:="DefaultApi",
                routeTemplate:="api/{controller}/{id}",
                defaults:=New With {.id = RouteParameter.Optional}
              )
          End Sub
      End Module
      
    2. Configure WebApiConfig.Register no método Application_Start em Global.asax da seguinte maneira:

      public class WebApiApplication : System.Web.HttpApplication
      {
          protected void Application_Start()
          {
              GlobalConfiguration.Configure(WebApiConfig.Register);    
          }
      }
      
      Public Class WebApiApplication
           Inherits System.Web.HttpApplication
       
           Sub Application_Start()     
             GlobalConfiguration.Configure(AddressOf WebApiConfig.Register)       
           End Sub
      End Class