Alterando a pasta de pacotes default do NuGet

Por default, o NuGet cria uma pasta “packages” na raiz da solução para colocar os pacotes baixados da internet. Se quiser que os pacotes sejam criados em uma pasta específica o procedimento é o seguinte:

1. Criar um arquivo nuget.config no nível da solução ou algum nível acima
Suponhamos que temos uma aplicação chamada MinhaAplicacao e dentro dela, tenho uma outra solução chamada WebAdmin, e que as pastas estão estruturadas da seguinte forma:

$\MinhaAplicacao\Main\Source\WebAdmin\MinhaAplicacao.WebAdmin.sln

Esta solução utiliza pacotes do NuGet, baixados ao criar o projeto do MVC 3. Existe uma pasta packages no mesmo nível da solution.

$\MinhaAplicacao\Main\Source\WebAdmin\packages

Para mudar isso, criarmos o arquivo no caminho:

$\MinhaAplicacao\Main\Source\nuget.config

Desta forma, ele  servirá para todas as solutions que estarão abaixo da pasta Source.

2. Especificar no arquivo nuget.config o caminho das referências.

Os assemblies do nosso projeto devem ficar na pasta SharedBinaries, dentro da pasta Main. Então, o nosso arquivo ficou assim:

<?xml version="1.0"?>
<settings>
  <repositoryPath>..\SharedBinaries\</repositoryPath>
</settings>

Com isso, estamos falando para o NuGet baixar os pacotes para $\MinhaAplicacao\Main\SharedBinaries\

3. Mover os pacotes existentes e alterar o arquivo repositories.config

Movemos todos arquivos dentro da pasta packages que havia dentro da nossa solution para SharedBinaries (não movemos a pasta packages). O arquivo repositories.config ficou assim:

<?xml version="1.0" encoding="utf-8"?>
<repositories>
  <repository path="..\Source\WebAdmin\Takenet.ChargingGateway.WebAdmin\packages.config" />
</repositories>

Resumindo tudo, nossa estrutura ficou assim:

$\MinhaAplicacao\Main\SharedBinaries\repositories.config
 $\MinhaAplicacao\Main\SharedBinaries\EntityFramework.4.1.10331.0\
 $\MinhaAplicacao\Main\SharedBinaries\jQuery.1.5.1\
 $\MinhaAplicacao\Main\SharedBinaries\jQuery.UI.Combined.1.8.11\
 $\MinhaAplicacao\Main\SharedBinaries\jQuery.Validation.1.8.0\
 $\MinhaAplicacao\Main\SharedBinaries\jQuery.vsdoc.1.5.1\
 $\MinhaAplicacao\Main\Source\nuget.config
 $\MinhaAplicacao\Main\Source\WebAdmin\packages.config

Obs: NuGet versão 1.4.20701.9038

Anúncios

Windows 8 vai suportar nativamente XAML

Ao divulgar mês passado o Windows 8 e suas aplicações construídas em HTML5 + JS , a Microsoft deixou muitos dos seus desenvolvedores .NET preocupados: iria a Microsoft abandonar o modelo .NET de desenvolvimento de aplicações e focar somente nas tecnologias Web? A Microsoft não diz nada, apenas fala para os desenvolvedores esperaram o evento BUILD em setembro desde ano, onde todas as respostas seriam dadas.

Só que algumas pessoas analisaram os arquivos de builds do Windows 8 que vazaram na Web e descobriram algumas coisas:

  • O Windows 8 virá com a versão 4.5 do .NET Framework
  • Haverá uma nova API do Windows chamada WinRT
  • E um nova camada de UI será disponibilizada para a construção de aplicativos gráficos, chamada Jupiter, baseada em XAML
Ou seja, o XAML saiu dos domínios do WPF (.NET),  Silverlight e WP7 e passa a ser um elemento nativo do sistema operacional.
Mais informações nos links abaixo:

Modelo de Domínio Anêmico

Segue um artigo interessante que fala sobre algo que o autor chama de modelo de domínio anêmico: São classes de dados que não possuem comportamento implementado, mas apenas os atributos de dados. Ele critica o isolamento completo da funcionalidade das classes em camadas de aplicação, pois isso tornaria o código muito procedural, indo contra os princípios da orientação a objetos:

http://martinfowler.com/bliki/AnemicDomainModel.html

É interessante refletir sobre isso pois vai contra o que várias ferramentas de geração de código oferecem, como .NetTiers, EF, etc.

Weak references no C#

Se houver na sua aplicação objetos que consomem muita memória (imagens, sons, resultados de consultas grandes ao banco de dados, etc) mas que podem ser facilmente construídos novamente, pode ser interessante utilizar Weak references para mantê-los, e desta forma, diminuir o consumo de memória da aplicação.

Um objeto criado com este tipo de referência pode ser coletado pelo Garbage Collector a qualquer momento, mas como o GC não realiza a coleta sempre (a coleta pode ser feita imediatamente após a criação da referência ou vários minutos depois), a utilização destas referências é útil.

Exemplo de código:

// Field da classe
private WeakReference objWeakReference;

// Construtor
public ClasseTeste()
{
  // Considerando que objetos da ClasseA consomem muita memória
   ClasseA obj = CriaClasseA();
   objWeakReference = new WeakReference(obj);
}
(...)
public void UtilizaClasseA()
{
  ClasseA obj = objWeakReference.Target as ClasseA;

  // Se obj não tiver sido coletado, o seu valor não será nulo
  if (obj == null)
  {
    obj = CriaClasseA();
    objWeakReference .Target = obj;
  }
  (...)
}

Uma das formas de utilizar mais interessantes é quando se constrói cache de objetos utilizando dicionários. No artigo do link abaixo, o autor explica como construir um dicionário genérico para armazenar os objetos com referências fracas:

http://blogs.msdn.com/b/jaredpar/archive/2009/03/03/building-a-weakreference-hashtable.aspx

Adicionando permissões a políticas controladas pelo domínio

Recentemente precisei desinstalar o SQL Server 2008 Express que estava na minha máquina, pois não usava e o serviço ficava ocupando recursos do computador. Ao executar o utilitário de desinstalação, recebi uma mensagem informando que não tinha permissões suficientes para executar a operação, mesmo sendo administrador local da máquina. O setup do SQL Server solicitava duas permissões:

  • Back up files and directories
  • Manage auditing and security log
Como era administrador da máquina, fui checar o por quê de não ter as permissões. Fui em Administrative Tools -> Local Security Policy -> Security Settings -> Local Policies -> Users Rights Assignment. Para a primeira permissão foi só abrir o item e adicionar meu usuário a lista de permitidos. Já para a segunda não era possível alterar, pois era uma política controlada pelo domínio. Pedi então ao rapaz do Help Desk para desinstalar o software para mim, só que ele também não possuía a tal permissão… Seria necessário solicitar ao administrador do domínio a alteração da política, o que poderia demorar, e como o que eu estava querendo fazer era algo simples (desinstalar um software), resolvi pesquisar por uma alternativa.
Algumas das políticas do Windows ficam no registro e nestes casos é fácil sobrescrever os valores do domínio, pois basta alterar o valor da chave correspondente com a ferramenta regedit. É claro que é necessário ser administrador da máquina para isso. Existe uma planilha da própria Microsoft com todas as políticas e suas chaves correspondentes no registro. O problema é que as políticas em Users Rights Assignment não ficam no registro do Windows. Neste caso, a solução que encontrei foi utilizar a ferramenta ntrights.exe. Esta ferramenta faz parte do Windows Server 2003 Resource Kit Tools , mas aparentemente funciona no Windows 7. Com isso, bastou executar o seguinte comando:
ntrights.exe -u dominio\usuario +r SeSecurityPrivilege
O valor SeSecurityPrivilege é o nome da política descrita como Manage auditing and security log. Por fim, bastou fazer logoff e o login novamente no Windows que o usuário estava com as permissões requeridas. Lembrando que este comando só deve funcionar se o usuário for administrador da máquina e somente para políticas locais. Isso não altera o domínio local, mas apenas adiciona permissões às existentes que foram definidas pelo AD na sua máquina.

Tutorial WPF MVVM no Youtube

Passei o dia inteiro de hoje na internet buscando exemplos, documentos e tutoriais para entender melhor a arquitetura MVVM (Model View View-Model) que é utilizada no Windows Presentation Foundation (WPF). Conceitualmente é fácil de entender, principalmente se você já trabalhou com outros padrões como o MVC (Model View Controler). Mas pra quem vem do Windows Forms, pode ser uma mudança de cultura significativa.

Resumindo a missa, o MVVM prega a divisão de sua aplicação WPF em três camadas:

  • Model – Modelo de dados, suas entidades de domínio. Podem ser entidades POCO ou geradas por alguma ferramenta a partir da base de dados. No meu caso, estou utilizando as entidades geradas pelo Entity Framework;
  • View – A interface gráfica da tela, escrita em XAML. Não deve conter NENHUMA regra de negócio implementada, apenas exibição. A View também não deve conhecer nada do modelo;
  • View-Model – Faz a ligação entre o modelo e a view. Contém a implementação das regras de negócio, expõe as propriedades, listas, comandos e demais recursos utilizados pela View.
As vantagens deste modelo são a grande organização no código, diminuição do acoplamento e com isso, aumento da reutilização, possibilidade de equipes paralelas trabalhando em uma tela sem necessidade de trocas de informação (ex: designers não precisam conhecer o modelo detalhadamente para desenhar a tela), dentre outras.
Voltando ao assunto, depois de ler e ver muita coisa, encontrei uma série de vídeos no youtube onde o apresentador implementa do zero uma aplicação WPF / MVVM, juntamente com Entity Framework e WCF. Muito bom e didático o exemplo, e cobre basicamente tudo que é necessário para se trabalhar com este padrão. São no total 8 vídeos, sendo que o link para o primeiro segue abaixo.

Depois é só seguir os links relacionados do youtube ou ir nos vídeos do usuário (em http://www.youtube.com/user/rainerstropek).

No último vídeo, ele demonstra a reutilização do ViewModel para recriar a mesma aplicação em Silverlight (que utiliza XAML). Muito interessante!

Envio de logs por e-mail com a EntLib

Utilizando o Logging Application Block da Enterprise Library, é possível configurar sua aplicação para enviar e-mails em casos de logs específicos. Isso é feito de forma transparente para a aplicação, através dos filtros de log que são definidos no arquivo de configuração. O e-mail é uma forma ativa de log, que não depende de alguém que fique monitorando os logs da aplicação. Mas é importante saber quando deve-se enviar e-mails, para que não sejam geradas muitas mensagem, o que tornaria o monitoramento ineficiente.

Com a EntLib, é possível escolher a maneira de se logar (listener de log) pela severidade e pela categoria dos logs. Em algumas aplicações críticas, pode-se configurar o serviço para enviar um e-mail com detalhes do log em casos de falhas de severidade Critical (a mais severa). Podem ser consideradas críticas as falhas que a aplicação não consegue se recuperar. Os demais logs podem ser armazenados no banco de dados ou arquivos.

Portanto, será enviado um e-mail se em algum trecho do código houver uma chamada de log como no exemplo abaixo:

Logger.Write(string.Format("A critical failure occurred: {0} - Stack: {1}", ex.Message, ex.StackTrace), "Start", 0, 0, TraceEventType.Critical, "AppContext");

Para configurar, é necessário adicionar no arquivo de configuração o listener de e-mail, na seção loggingConfiguration:

    <listeners>
      <add toAddress="alerta@dominio.com.br" fromAddress="aplicacao@dominio.com.br"
        subjectLineStarter="[" subjectLineEnder="] Application Log"
        smtpServer="mail.dominio.com.br" smtpPort="587" formatter="Text Formatter"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.EmailTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        traceOutputOptions="None" filter="Critical" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.EmailTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

        name="Email TraceListener" />
        (...)
    </listeners>

Note que na propriedade filter, o valor configurado está Critical. Para adequar o texto do log ao formato do e-mail, definimos um formatter:

    <formatters>
      <add template="Log date (local): {timestamp(local:yyyy-MM-dd HH:mm:ss.fff)}Category: {category}Operation: {title}Server: {machine}Parameters: {dictionary({key}={value};)}Message: {message}"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        name="Text Formatter" />
        (...)
    </formatters>

Se o servidor exiger autenticação, é necessário adicionar as credenciais de acesso no arquivo de configuração, dentro da seção system.net:

  <system.net>
    <mailSettings>
      <smtp from="aplicacao@dominio.com.br">
        <network host="mail.dominio.com.br" port="587" userName="aplicacao" password="123456" />
      </smtp>
    </mailSettings>
  </system.net>