Arquivos de Configurações do ASP.NET 5?

Renato Haddad

Dn878001.060DE5057573180CEC6D227C6D3E2207(pt-br,MSDN.10).png

Novembro, 2014

A Microsoft lançou a versão preview do Visual Studio .Net 2015, .NET Framework 4.6 e, entre outras novidades está o fantástico ASP.NET 5. No entanto, como tudo é novidade e muitas pessoas me questionam como ficaram os arquivos de configurações da aplicação, resolvi escrever este artigo para esclarecer e compartilhar o conhecimento com todos.

Antes de mais nada, é importante ressaltar que a versão que estou usando é a Visual Studio Ultimate 2015 Preview, 14.0.22310.1 DP e do .NET Framework 4.5.53349. Tais informações você encontra no menu Help / About, conforme a figura 1.

Dn878001.8F34665595F4527F9158E4BDF75AE3D4(pt-br,MSDN.10).png

Figura 1 – Versão do VS Ultimate

Projeto ASP.NET 5

Vamos fazer um exemplo prático criando uma aplicação desde o início. Abra o VS 2015, selecione File / New Project (Ctrl + Shift + N). Na janela aberta, selecione a linguagem Visual C#, a categoria Web e nos templates, ASP.NET Web Application. O nome do projeto será artigoASPNET5, conforme a figura 2.

Dn878001.7F47B2EC0412574E386366FD1569E65D(pt-br,MSDN.10).png

Figura 2 – Novo projeto ASP.NET 5

Clique no botão OK, e em seguida teremos uma nova janela onde você tem dois novos templates, sendo: ASP.NET 5 Empty e ASP.NET 5 Starter Web. Este último é o que deve ser selecionado, conforme a figura 3. Note que os checkboxes das referências dos folders Web Forms, MVC e Web API não estão mais disponíveis devido ao novo formato do ASP.NET 5.

Dn878001.684CD115CD499BC0DEDFEBA3B9EB6745(pt-br,MSDN.10).png

Figura 3 – Template do projeto

Clique no botão OK e aguarde o VS criar o projeto. No Solution Explorer temos a pasta chamada “Solutions items”, o qual contém o arquivo global.json. A função dele é informar quais as pastas se referem ao projeto. Abra este arquivo e veja que o conteúdo é um json, conforme a figura 4, indicando as pastas para os fontes, neste caso o “src”. Aliás, todos os arquivos de configurações no ASP.NET 5 são no formato JSON. Acho isto ótimo, simples de se entender e qualquer pessoa de outra plataforma já conhece JSON. Já que o ASP.NET 5 poderá rodar em qualquer plataforma, nada melhor que o JSON.

Dn878001.ED06F4665AF2841329C0565576BC5B7C(pt-br,MSDN.10).png

Figura 4 – Estrutura do global.json

Na pasta “src” temos o projeto em si. O nome da pasta é wwwroot, o qual é definida no item webroot no arquivo project.json, vou detalhar isto em seguida. Veja na figura 5, o conteúdo do wwwroot, sendo o arquivo CSS básico do projeto (pasta css/site.css), a pasta lib que contém todas as bibliotecas instaladas por padrão (bootstrap, jquery, jquery-validation e jquery-validation-unobtrusive). Cabe ressaltar que cada pasta contém os respectivos arquivos CSS. JS, etc). E se eu quiser adicionar outros arquivos, como faço? Tudo agora é através de injeção de dependência nos arquivos de configuração, mais abaixo no artigo explico isto em detalhes.

Dn878001.4A8A350C39A7C00771D1B4D0D2D33571(pt-br,MSDN.10).png

Figura 5 – Pasta wwwroot

Agora temos a pasta Dependencies que contém referências de pacotes para o Bower e NPM (Node Package Manager), os quais são pacotes conhecidos no mercado, contendo pacotes de códigos a serem executados no cliente, por exemplo, JavaScript e CSS. Isto tudo é relativo à execução no cliente (cliente-side), e no lado do servidor (server-side), continuamos com os pacotes via Nuget. Veja na figura 6 a estrutura destas duas pastas no Solution Explorer.

Dn878001.9FBE5518D23ED8C77F4ABF5669CA91D2(pt-br,MSDN.10).png

Figura 6 – Dependências do Bower e NPM

Como o ASP.NET 5 inovou em muitos aspectos, agora existe o conceito de injeção de dependência das bibliotecas. Para quem usa o Nuget já era fácil instalar pacotes, e agora ficou muito mais simples, acredite. Vamos fazer um teste para adicionar pacotes no Bower. Abra o arquivo bower.json e observe que temos a lista de bibliotecas/pacotes no elemento “dependencies” do json. Esta lista expressa exatamente os pacotes listados dentro da pasta Dependencies/Bower.

E, como instalar um pacote chamado RequireJS? Já que todos os arquivos de configurações do ASP.NET 5 são estruturados no formato JSON, basta adicionar um novo elemento em “dependencies”. Na figura 7 temos as referências atuais.

Dn878001.F7E360C8F6A4D0C1A078110B0864B9A7(pt-br,MSDN.10).png

Figura 7 – Pacotes instalados no Bower

No último elemento de dependencies, digite uma vírgula, e na próxima linha digite entre aspas o “requirejs”, conforme a figura 8.

Dn878001.42D934283969953EC984806E45086989(pt-br,MSDN.10).png

Figura 8 – Novo pacote requirejs

E, como não poderia ser diferente, temos o intellisense para nos mostrar quais pacotes e versões existem. Portanto, adicione o “:” e ao listar as versões, selecione a 2.1.15, conforme a figura 9.

Dn878001.9E037413847D312873A8EB2F62813B3D(pt-br,MSDN.10).png

Figura 9 – Versões no intellisense

Até este momento o arquivo não está salvo. Sendo assim, ao salvar o arquivo CTRL + S, observe no Solution Explorer, na pasta Bower que o requirejs aparece na lista, porém ainda não está instalado. O próximo passo é restaurar os pacotes, então, clique com o botão direito na pasta Bower, selecione Restore Package e aguarde a instalação, conforme a figura 10.

Dn878001.B4C4F8C997CAFF62929B3AE383ED4A9E(pt-br,MSDN.10).png

Figura 10 – Instalação do pacote

Cabe ressaltar que este processo para instalar ficou tão simples, quanto para desinstalar, o qual basta excluir a referência do pacote no arquivo .json.

Esta mesma ideia vale para os pacotes NPM, os quais usam Grunt e Gulp. O arquivo que gerencia o NPM é o package.json. Este tópico de NPM é tema para outro artigo, vou focar na configuração do ASP.NET 5.

Configuração do Projeto

O arquivo project.json contém diversos elementos de configuração por categoria. Veja uma lista com as explicações:

Weebroot – define a propriedade que será a pasta pública no servidor IIS, caso use o Visual Studio.

“weebroot” : “wwwroot”

Dependencies - aqui temos todas as referências de bibliotecas necessárias para o projeto no estilo nome e versão, os quais serão carregadas em tempo de execução. Sendo assim, quando você desejar referenciar uma nova biblioteca, insira o nome e selecione a versão. Claro que existe o intellisense também, e podem ser pacotes do Nuget, códigos fontes, etc.

"dependencies": {
        "EntityFramework.SqlServer": "7.0.0-beta1",
        "EntityFramework.Commands": "7.0.0-beta1",
        "Microsoft.AspNet.Mvc": "6.0.0-beta1",
        //"Microsoft.AspNet.Mvc.WebApiCompatShim": "6.0.0-beta1",
        "Microsoft.AspNet.Diagnostics": "1.0.0-beta1",
        "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-beta1",
        "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-beta1",
        "Microsoft.AspNet.Security.Cookies": "1.0.0-beta1",
        "Microsoft.AspNet.Server.IIS": "1.0.0-beta1",
        "Microsoft.AspNet.Server.WebListener": "1.0.0-beta1",
        "Microsoft.AspNet.StaticFiles": "1.0.0-beta1",
        "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta1",
        "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-beta1",
        "Microsoft.Framework.Logging": "1.0.0-beta1",
        "Microsoft.Framework.Logging.Console": "1.0.0-beta1",
        "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta1"

Commands – como todos sabem, o ASP.NET 5 pode ser executado em diversas plataformas como Windows, Linux e Mac. E, para isto você pode usar linhas de comando (powershell) para executar comandos em si. Neste elemento de commands, temos os nomes dos comandos que serão executados pelo comando k.cmd. Na lista a seguir, você pode executar o “k web”, “k gen” e o “k ef”.

"commands": {
        "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000",
        "gen": "Microsoft.Framework.CodeGeneration",
        "ef":  "EntityFramework.Commands"

Frameworks – define quais versões de frameworks serão compilados e as respectivas configurações.

"frameworks": {
        "aspnet50": { },
        "aspnetcore50": { }

Veja um exemplo para compilar para Desktop (aspnet50) ou Core CLR (aspnetcore50).

{
  "frameworks": {
    "aspnet50": {},
    "aspnetcore50": {
      "dependencies": {
        "System.Collections": "4.0.0.0",
        "System.Collections.Concurrent": "4.0.0.0",
        "System.ComponentModel": "4.0.0.0",
        "System.Linq": "4.0.0.0",
        "System.Reflection": "4.0.10.0",
        "System.Runtime": "4.0.20.0",
        "System.Runtime.InteropServices": "4.0.10.0",
        "System.Threading": "4.0.0.0",
        "System.Threading.Tasks": "4.0.0.0"
      }
    }
  }
}

Estas demais seções exclude e packExclude definem quais fontes serão compilados.

"exclude": [
        "wwwroot",
        "node_modules",
        "bower_components"
    ],
"packExclude": [
        "node_modules",
        "bower_components",
        "**.kproj",
        "**.user",
        "**.vspscc"

Scripts – quando utilizamos os comandos kpm (K Package Manager) devemos rodar os scripts definidos nesta seção.

"scripts": {
        "postrestore": [ "npm install" ],
        "prepare": [ "grunt bower:install" ]
}

Pasta References

A famosa pasta references contém duas referências de ASP.NET 5.0 e o ASP.NET Core 5.0. As duas são praticamente iguais, mas a ASP.NET 5.0 tem algumas classes a mais, pois afinal, depende de onde você irá executar o projeto.

Acesso a Dados com o Entity Framework

Em projetos ASP.NET 4.5 ou anterior tínhamos o arquivo Web.config que contém todas as chaves utilizadas no projeto. Agora, no ASP.NET 5 temos o arquivo de configuração config.json, o qual é nele que você deve adicionar todas as referências de chaves a serem usadas na aplicação. Abra este arquivo e veja que temos dois elementos importantes, o Data e o EntityFramework. O Data define a string de conexão para o banco de dados através da chave ConnectionString. E o EntityFramework faz a referência a esta chave através do ApplicationDbContext, o qual referencia na chave ConnectioStringKey a string de conexão definida em ConnectionString. Isto é o padrão do Entity Framework no ASP.NET 5. Claro que você pode adicionar outras chaves para outras conexões com bancos de dados diferentes, mas isto é tópico para outro artigo.

{
    "Data": {
        "DefaultConnection": { 
            "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-artigoASPNET5-8c577f64-e471-4ffd-bd84-20c4a43cc75a;Trusted_Connection=True;MultipleActiveResultSets=true"
        }
    },
    "EntityFramework": {
        "ApplicationDbContext": {
            "ConnectionStringKey": "Data:DefaultConnection:ConnectionString"
        }
    }
}

Classe de Inicialização

Como é que o ASP.NET 5 sabe quais configurações devem ser aplicadas? Abra o arquivo Startup.cs e note que no construtor da classe já existe a referência ao arquivo config.json através do .AddJsonFile. Em seguida, temos o AddEnvironmentVariables para adicionar chaves de ambiente ao projeto. Existem outras opções como AddCommandLine (para executar linhas de comando), Set para adicionar um hashvalue (chave, valor), etc. Basicamente é aqui que você aponta para os arquivos de configurações que deseja inicializar logo quando a aplicação é carregada.

namespace artigoASPNET5
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            // Setup configuration sources.
            Configuration = new Configuration()
                .AddJsonFile("config.json")
                .AddEnvironmentVariables();
        }

        public IConfiguration Configuration { get; set; }

O método ConfigureServices é chamado em tempo de execução. Nele inserimos as configurações para o serviço do Entity Framework, por exemplo, informando o SQL Server (AddSqlServer), quais são os contextos (AddDbContext) o qual é uma Action que dispara um delegate de qualquer classe que herde de DbContext. Veja que o <ApplicationDbContext> é a classe que nativamente herda de IdentityDbContext, para gerenciar os usuários cadastrados na aplicação. Isto está diretamente relacionado ao AddDefaultIdentity, mas já adianto que na documentação deste VS Preview, consta que até a versão final isto poderá mudar.

// This method gets called by the runtime.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add EF services to the services container.
            services.AddEntityFramework(Configuration)
                .AddSqlServer()
                .AddDbContext<ApplicationDbContext>();

            // Add Identity services to the services container.
services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>(Configuration);

Em relação ao MVC e Web API, você deve adicionar os respectivos AddMVC e AddWebApiConventions, que são os serviços para tais. Cabe ressaltar que nas versões anteriores do ASP.NET 5, uma classe pode herdar de Controller ou de ApiController (para Web API), mas isto acabou, não existe mais esta distinção no ASP.NET 5, basta herdar de Controller que a mesma poderá ser usada para retornar XML ou JSON de uma requisição de serviços de uma Action.

// Add MVC services to the services container.
            services.AddMvc();

            // Uncomment the following line to add Web API servcies which makes it easier to port Web API 2 controllers.
            // You need to add Microsoft.AspNet.Mvc.WebApiCompatShim package to project.json
            // services.AddWebApiConventions();

        }

Este método é chamado após o anterior (ConfigureServices), ou seja, configure todo o ambiente (banco, contexto, MVC) e depois execute este método. Aqui praticamente temos configurações para o ambiente de desenvolvimento e produção. Por exemplo, veja o AddConsole que configura o pipeline do HTTP para fazer log no console. Depois existe um if que verifica se o ambiente é de desenvolvimento (Development) ou não. Se for, configure todo o ambiente para desenvolvimento, por exemplo, o default são UseBrowserLink(), UseErrorPage (captura erros no pipeline do HTTP), UseDatabaseErrorPage (captura os erros de database). Existem vários outros, pois app é do tipo IApplicationBuilder, então a lista é grande, por exemplo, UseCookieAuthentication, UseDefaultFiles, UseDirectoryBrowser, UseErrorHandler, UseIdentity, UseWelcomePage, UseMigrationsEndPoint. Veja então, que neste ponto você pode e deve configurar todo o ambiente da aplicação.

// Configure is called after ConfigureServices is called.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
        {
            // Configure the HTTP request pipeline.
            // Add the console logger.
            loggerfactory.AddConsole();

            // Add the following to the request pipeline only in development environment.
            if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
            {
                app.UseBrowserLink();
                app.UseErrorPage(ErrorPageOptions.ShowAll);
                app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
            }
            else
            {
                // Add Error handling middleware which catches all application specific errors and
                // send the request to the following path or controller action.
                app.UseErrorHandler("/Home/Error");
            }

            // Add static files to the request pipeline.
            app.UseStaticFiles();

            // Add cookie-based authentication to the request pipeline.
            app.UseIdentity();

A seguir você tem uma configuração conhecida para aplicações MVC, é a famosa rota, tanto para a aplicação MVC, quanto para Web Api.

// Add MVC to the request pipeline.
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller}/{action}/{id?}",
                    defaults: new { controller = "Home", action = "Index" });

                // Uncomment the following line to add a route for porting Web API 2 controllers.
                // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
            });
        }
    }
}

Pronto, chegou a hora de executar a aplicação, então, pressione F5 e veja o resultado no browser, conforme a figura 11.

Dn878001.EE1C93C9FEA476F5BC48B8A0C53AA068(pt-br,MSDN.10).png

Figura 11 – Projeto em execução

Conclusão

É sempre bom ver a evolução de uma tecnologia como .NET, C#, VB.NET desde o início, tive a oportunidade de acompanhar todas as versões, e creio que atualmente este .NET 4.6 e o ASP.NET 5 abrem um mercado gigantesco a todos, justamente pelo modelo de execução em qualquer plataforma. E, se você não quiser usar o Visual Studio como ferramenta, já existem outras no mercado como o Sublime, para um mundo que não tem o VS.

Portanto, dedicação e estudos das novas tecnologias é importante, afinal, sabemos que há toneladas de projetos a serem criados ou aprimorados.

Agradeço a oportunidade de poder compartilhar o conhecimento deste artigo. Qualquer dúvida e preparação de times de desenvolvimento, por favor me contate.

Sobre o Autor

Renato Haddad (rehaddad@msn.comwww.renatohaddad.com ) é MVP, MCPD e MCTS, palestrante em eventos da Microsoft em diversos países, ministra treinamentos focados em produtividade com o VS.NET 2013/2015, ASP.NET 4/5, Entity Framework, Reporting Services, Windows Phone e Windows 8. Visite o blog http://weblogs.asp.net/renatohaddad.

Mostrar: