Pré compilação de views Razor no ASP.NET MVC 6

Imagine o cenário de uma aplicação ASP.NET MVC básica, com uma classe de modelo servindo dados para uma view, conforme código abaixo:

Agora, suponha que precisamos fazer alguma alteração simples, como mudar o namespace da classe de modelo, para maior organização do projeto. Passamos a classe HomeViewModel para dentro da pasta Home, debaixo do diretório Models, conforme figura abaixo:

Novo namespace
Novo namespace

Se tentarmos rodar a aplicação nesse momento, vamos obter erro de compilação e o build vai falhar, já que o namespace referenciado na controller não mais possui a classe HomeViewModel:

Erro de compilação
Erro de compilação

Esse é o resultado esperado. O compilador nos ajuda a detectar esse tipo de erro básico e aponta onde está o problema.

Depois de corrigido o namespace no controller, ainda obteremos erro ao rodar a aplicação, dessa vez em tempo de execução:

Erro em tempo de execução
Erro em tempo de execução

 

Você vem me dizer que o código não compila em tempo de execução?
Você vem me dizer que o código não compila em tempo de execução?

Isso ocorre, pois não atualizamos a referência do namespace do modelo no código da view.

Seria muito mais eficiente se o compilador nos informasse desse erro em tempo de compilação, da mesma forma que ocorreu na controller. No ASP.NET MVC 5, é possível alterar a configuração do arquivo .csproj, de forma a forçar a pré renderização da view, de modo que o compilador avise de qualquer erro em tempo de compilação. Basta adicionar a tag abaixo no código do arquivo .csproj:

<MvcBuildViews>true</MvcBuildViews>

Mas em uma aplicação ASP.NET MVC 6, o arquivo de projeto mudou para o formato JSON e já não temos mais o recurso de pré compilação da forma que existia nas versões anteriores do framework, conforme mostrado acima. Como fazer agora?

Utilizando o RazorPreCompileModule

O ASP.NET 5, antes conhecido como vNext, traz consigo o novo compilador do C#, chamado Roslyn. Com ele, a Microsoft disponibilizou formas do desenvolvedor alterar o comportamento de compilação de uma aplicação, através de interfaces e classe abstratas que podem sem implementadas ou estendidas para adicionarmos comportamento customizado.

No nosso caso, vamos criar uma classe chamada PreCompilacaoRazor, que herda da classe abstrata RazorPreCompilaModule, que por sua vez implementa a interface ICompileModule. Essa classe será responsável por realizar a pré renderização das views da nossa aplicação:

Observe que não é necessário declarar o módulo de compilação no nosso código. Basta adicionar o código acima em qualquer ponto do projeto, que o Roslyn se encarrega de encontrar qualquer classe que implemente a interface ICompileModule para aplicar os seus módulos.

Ao adicionarmos essa classe na aplicação, obtemos o comportamento desejado. Agora, o Roslyn informa erro em tempo de compilação ao tentarmos rodar a aplicação com erro no código da view e o build falha:

Erro de compilação na view
Erro de compilação na view

Observação: Esse recurso não funciona com a versão beta 1 das dlls do ASP.NET 5. Já foram lançadas as versões beta 3 com a versão mais recente do Visual Studio 2015 CTP 14.0.22609.0 D14REL. Inclusive, o template padrão de uma aplicação ASP.NET MVC 6 já está incluindo a classe para efetuar a pré compilação das views Razor.

O novo modelo de compilação como serviço introduzido com o ASP.NET 5 permite diversos recursos interessantes para as aplicações baseadas no .Net Framework. Vale muito a pena ficar atento às novidades e entender melhor o funcionamento do Roslyn.

SHOW ME THE CODE!!

https://github.com/marcellalves/pre-compilacao-view-razor-asp-net-mvc-6

Para saber mais sobre o assunto, leia também:

http://www.strathweb.com/2014/12/razor-views-pre-compilation-asp-net-5-mvc-6/