Arquivo da tag: .NET

#if(DEBUG) – Executando Windows Service pelo Visual Studio

Faz um tempo que eu venho desenvolvendo, eventualmente, Windows Services para fazer processamentos esporádicos, para requisições assíncronas e tal.
Eu acho legal Windows Service, para caralho, é muito util. Mas tem uma coisa que realmente me deixa #chatiada: executá-lo no Visual Studio. Não dá.
Ontem precisei criar um Windows Service, com um timer que disparava um eventindo para chamar um serviço, simples como a vida. Queria executar para ver rolando, pesquisei um pouco e se liga nisso…

Essa é a classe do serviço, parecida com a que eu tenho, perceba que meu OnStart chama um método publico da classe, onde inicia o timer e seta o evento quando o intervalo for atingido.

public partial class ServiceOfDeath : ServiceBase
{
	System.Timers.Timer aTimer;
 
	public ServiceOfDeath()
	{
		InitializeComponent();
	}
 
	protected override void OnStart(string[] args)
	{
		IniciarTimer();
	}
 
	public void IniciarTimer()
	{
		aTimer = new System.Timers.Timer(Convert.ToInt32(ConfigurationManager.AppSettings["MilisegundosDeIntervalo"]));
		aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
		aTimer.Start();
	}
 
	private void OnTimedEvent(object sender, ElapsedEventArgs e)
	{
		aTimer.Stop();
		new Liquidificador().Misturar();
		aTimer.Start();
	}
 
	protected override void OnStop()
	{
		aTimer.Stop();
	}
}

Daí na classe que é executada quando a aplicação é executada (Program.cs), fazemos o seguinte.

static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            #if (!DEBUG)
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] 
                { 
                    new ServiceOfDeath() 
                };
                ServiceBase.Run(ServicesToRun);
            #else
                ServiceOfDeath servicoDaMorte = new ServiceOfDeath();
                servicoDaMorte .IniciarTimer();
                //Thread eterna
                System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
            #endif
        }
    }

Ou seja, o #if(DEBUG) serve para o Visual Studio interpretar aquele código somente quando estiver em modo debug (não acredito que ainda não conhecia isso), dá um mundinho de possibilidades aí para quem quer debugar alguma coisa que o VS não executa. Acho melhor que ficar attachando processo, que é chatissimo.

Anotem essa para quando estiverem com um código macarronico em mãos! rs

Razor Helper – Menu dinâmico

O que falar do Razor que eu já considero tanto? rs
MVC é coisa linda demais, incrivelmente mais limpo, prático, rápido, etc etc. Não sei nem porque a Microsoft não já matou o WebForms.

Mas então.. estava montando um menuzinho dinâmico aqui de possíveis N gerações (?).
Mandei um helper para fazer o loop ad æternum, se liga só:

@helper MontarMenu(List<Menu> menus)
{
    foreach (Menu item in menus)
    {
        <li>
            <a href="item.Url">
                @item.Descricao
            </a>
 
            @if (item.Filhos != null && item.Filhos.Count > 0)
            {
                <ul>
                    @MontarMenu(item.Filhos)
                </ul>
            }
        </li>        
      }
}

Para chamar o lindão:

<div id="menucontainer">
	<ul id="menu">
		@if (ViewBag.Menu() != null && ViewBag.Menu().Count > 0)
		{
			@:@MontarMenu(ViewBag.Menu())
		}
	</ul>
</div>

Simples como a vida tem quer ser.
Amem.

E larguem o WebForms! :~

Could not load file or assembly ‘DotNetOpenAuth.Core’

Delicias a parte <3, estamos começando o ano com bug! Criei um projeto C# e depois transformei ele em MVC, fazer aquelas referencias na mão é hard. Fiquei com um erro chatão que não é nem um pouco auto explicável. O bendito era:
“Could not load file or assembly ‘DotNetOpenAuth.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)”

Para resolve-lo basta checkar o Copy Local como true na referencia do MVC.

Problema resolvido e happy new year!

Pingado – Monitoramento de webservices

SOA! Ando respirando isso, ai ai. Lembro a 2 anos atras quando eu queria pq queria viver isso day-by-day … Demorou, mas estou aqui, ein? Hehehehe. E ainda bem que demorou, hoje entendo a maturidade que um dev precisa ter para levar um projeto bacana nessa arquitetura .. seguimos aprendendo! But let’s go 🙂

A vida não é só flores e amor, preciso medir a disponibilidade de um projeto … preciso de alertas para manter essa disponibilidade caso ela esteja em risco. Como tudo é serviço, uma das maneiras que pensei em manter o espirito de escoteiro (SEMPRE ALERTA!) é pingando os benditos! Incrivelmente não achei nada free para fazer isso, estou cheia de coisas para testar (windows 8, visual studio 2012, github, frameworks, etc.) entao resolvi dar um start nisso. Vamos ver até onde vou!

FIRST STEP, instalar esse ambiente que quero testar.

Windows 8 tá muito rápido e a usabilidade dele tá maneira. É meio chato de inicio porque já estamos no modo automatico com a barra de inicialização e tal, mas uma semaninha usando como usuario n00b e já estou bem familiarizada. Ele é bonitão e não achei nada contra ainda além de ter que ter conta na live. Bug todo mundo tem então … pls, don’t tell me that gave a blue screen.

http://www.reddit.com/r/windows8/comments/1d3dok/why_dont_people_like_windows_8/
http://www.techradar.com/reviews/pc-mac/software/operating-systems/windows-8-1093002/review
http://www.reddit.com/r/windows8/comments/168ybd/windows_8_is_a_fantastic_os_why_do_so_many_people/

Visual Studio 2012: IDE mais sensacional não ha! Acho que é ela quem mantém meu relacionamento sério com o .NET. Dá um look http://msdn.microsoft.com/en-us/library/vstudio/bb386063.aspx.

Cadastrinho maroto no Github. Eu havia feito um teste já acompanhando o curso da Code School: Try Git. Recomendo, é free e objetivo.

Instalei também o plugin para o VS.

E claro, meu tema preferido do VS. Aqui tem mais: http://studiostyl.es/.

Ambiente semi pronto, proximo post tem codigo com farinha.

Consumindo webservice com basic autenthication – WCF

Nunca tinha feito isso na minha vida, WCF tem mais configuração do que há dados no Google, potaqueparola.
Estou consumindo um webservice externo onde foi descrito que precisavamos enviar a cada chamada o header de autenticação básica com usuario e senha em Base 64, e esses dados deveriam ser concatenados separados por :.
Ou seja:

Usuario: teste
Senha: 123123

Concatenado: teste:123123
Criptografado: dGVzdGU6MTIzMTIz (by http://ostermiller.org/calc/encode.html)

E o header: Authorization: Basic dGVzdGU6MTIzMTIz

Acontece que isso é autenticação padrão em serviços, ou sejammmm, para usar isso no WCF precisamos apenas configurar o binding do client para o modo de segurança necessaria (varia de acordo com o serviço, claro), no meu caso , Transport e o tipo de credencial básica (Basic authentication, hãm hãm):

<basicHttpBinding>
	<binding name="meuBindingLindao">
	  <security mode="Transport">
		<transport clientCredentialType="Basic" />
	  </security>
	</binding>
</basicHttpBinding>

E setar o usuario e senha na chamada:

WebServiceClient cliente= new WebServiceClient();
cliente.ClientCredentials.UserName.UserName = "usuario";
cliente.ClientCredentials.UserName.Password = "senha";

Mais moleza que isso só .. sei la. Away!

WCF com .config comunitário – Configuração de hosteamento

Estou com um projeto orientado a infinitos serviços, claro que fizemos as configurações do WCF em granularidade, deixando os bindings e behaviors num .config partilhado entre todos (teoricamente como eles conversam entre si, as configurações são as mesmas).

Acontece que começou a estourar o buffer, sendo que todos estavam consumindo pelo mesma configuração de binding. Notei então que os expositores de serviço estavam hosteados com binding “padrões” aqueles sem nomes. Ou seja:

Não esqueça de configurar o binding default dos seus serviços expostos (caso esteja usando, claro). 🙂

<bindings>
			<basicHttpBinding>
				<binding closeTimeout="00:00:30" 
          openTimeout="00:00:30" receiveTimeout="00:00:30" sendTimeout="00:00:30" 
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
          maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" 
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" 
          useDefaultWebProxy="true"> 
					<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16384" 
            maxBytesPerRead="4096" maxNameTableCharCount="16384" /> 
					<security mode="None">
						<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
						<message clientCredentialType="UserName" algorithmSuite="Default" />
					</security>
				</binding>
			</basicHttpBinding>
</bindings>

MVC Helper customizado (paginação)

Paginação! Me dá uma agonia quando usam alguma artimanha em html/javascript pra “paginar”, quem será que eles querem enganar carregando tudo na primeira página e depois dando um tapinha pra nao ficar com muita barra de rolagem?
Paginação é importante também para diminuir o peso na pagina, carregar tudo do banco de uma vez é péssimo .. tem gente que tem internet ruim, acho triste pensar tão pouco no usuário. 🙁

Enfim, como eu tenho trabalhado bastante nos ultimos tempos com MVC 3 e eu acho a coisa mais linda do mundo aqueles helpers do razor, implementei um helperzinho para me ajudar com paginação! Iupi!

O helper nada mais é que uma classe estática com métodos estáticos que recebem o System.Web.Mvc.HtmlHelper, assim referenciamos a biblioteca no system.web.webPages.razor e conseguimos usa-la pelo helper do Razor, vulgo @Html.

Vamos ao meu exemplinho!

namespace raposa
{
	public static class paginacaoOfDeath
	{
		public static MvcHtmlString CriarPaginacao(this HtmlHelper helper, int quantidadeDePaginas, int paginaAtual)
		{
			return new MvcHtmlString("HTML DA PAGINAÇÃO");
		}
	}
}

No Web.config das views eu adiciono referência da biblioteca do meu helper maneirão.

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="raposa" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

Depois para usar ..

@Html.CriarPaginacao(500, 1)

AWAY!

Microsoft.Web.Helpers – FileUpload – N upload de arquivo(s)

Quão chato é ficar toda hora fazendo relacionamento 1 para N nas telas? PQP. Todo dia a mesma coisa.
Estava eu aqui fazendo essa coisa maravilinda de Deus mais uma vez again novamente, porém o helper do MVC 3 não possui o FileUpload (pelo menos não achei).
Dei uma pesquisada rápida e achei um helper da Microsoft especifico para isso, vulgo Microsoft Web Helper. Adicionei pelo NuGet pesquisando por “microsoft-web-helpers”.

Na ViewModel, declarei uma IEnumerable de HttpPostedFileBase para receber os arquivos.
E na view, simplesmente um

@Microsoft.Web.Helpers.FileUpload.GetHtml(
name: “nomeDoObjeto.nomeDaPropriedade”,
addText: “Adicionar anexo”,
includeFormTag: false
)

E ele já cria (ou não, de acordo com sua parametrização na linha acima) a possibilidade de adicionar N inputs file. I’m in love <3

Fluent NHibernate + MySQL

Foi paixão a primeira vista quando eu li/vi sobre ORM (Mapeamento Objeto Relacional), metade da pedreiragem diária ia escafeder da galáxia, já pensou? Coisa linda .. até aparecer os lados mais chatos disso: performance, xml, performance, relação (principalmente) many-to-many, performance.
Ainda fico meio na dúvida de quando aplicar, se vale a pena e tudo mais, mas uma das primeiras coisas que avalio quando vou iniciar o desenvolvimento com algum ORM é como ele persiste e busca os relacionamentos no banco, que é coisa básica, não acho que tem que dar trabalho (já tive MUITO problema com o entity framework e com o linq to sql, depois comento aqui). Soube do Fluent NHibernate (sem xml! fuck yeah!), não foi diferente, fiz um many-to-many, usei um lazy loading .. bom, vamos lá.

Levando em conta que já temos o ambiente configurado (MySQL instalado, Fluent disponível e etc – os links para os downloads estão no fim do post, tudo gratuito!), criaremos um “Console Application” e adicionaremos as seguintes referencias sobre o NHibernate Fluent e conexao com o MySQL.

Para configurar a sessão com o banco de dados (o código é bem intuitivo mas, caso queira verificar exemplos com outros bancos, tem na própria wiki do Fluent).

1
2
3
4
5
6
7
8
9
10
11
public static ISession ObterSessao()
{
    return Fluently.Configure()
        .Database(
            MySQLConfiguration.Standard.ConnectionString(c =&gt; c.Server("localhost").Database("weblabz").Username("root")
        ).ShowSql())
        .Mappings(m =&gt; m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
        .ExposeConfiguration(c =&gt; new SchemaExport(c).Create(true, true))
        .BuildSessionFactory()
        .OpenSession();
}

O “ShowSql”, na linha 6, mostra todos as querys sql executadas, colocaremos para melhor visualização do que está ocorrendo na nossa aplicação.
E com o código da linha 8, nossas entidades mapeadas virarão entidades no banco de dados. NÃO DEVEMOS ESQUECER que sempre que executamos ele irar dropar e criar novamente as tabelas!!

Criamos agora nossas entidades ..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Livro
{
    public virtual int Id { get; private set; }
    public virtual string Nome { get; set; }
    public virtual string Editora { get; set; }
    public virtual int AnoLancamento { get; set; }
    public virtual IList Autores { get; private set; }
 
    public Livro()
    {
        this.Autores = new List();
    }
}
 
public class Autor
{
    public virtual int Id { get; private set; }
    public virtual string Nome { get; set; }
    public virtual IList
 Livros { get; private set; }
 
    public Autor()
    {
        this.Livros = new List
();
    }
 
    public virtual void AdicionarLivro(Livro LivroAdd)
    {
        LivroAdd.Autores.Add(this);
        this.Livros.Add(LivroAdd);
    }
}

.. e seus respectivos mapeamentos.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class LivroMap : ClassMap
 
{
    public LivroMap()
    {
        Id(l =&gt; l.Id);
        Map(l =&gt; l.Nome)
            .Not.Nullable()
            .Length(200);
        Map(l =&gt; l.Editora)
            .Not.Nullable()
            .Length(200);
        Map(l =&gt; l.AnoLancamento)
            .Nullable();
 
        HasManyToMany(l =&gt; l.Autores)
            .Cascade.All()
            .Inverse()
            .Table("AutorXLivro");
    }
}
 
public class AutorMap : ClassMap
{
    public AutorMap()
    {
        Id(a =&gt; a.Id);
        Map(a =&gt; a.Nome)
            .Not.Nullable()
            .Length(200);
 
        HasManyToMany(a =&gt; a.Livros)
            .Cascade.All()
            .Table("AutorXLivro");
    }
}

Reparem que eu deixo a classe Autor como “responsável” pelo relacionamento com Livro, criando um método onde, quando adicionado um Livro para o mesmo, tal Autor também é adicionado ao Livro e adicionando o Inverse ao nosso HasManyToMany de Autores em Livro, que faz com que a outra ponta do relacionamento que persista os dados.

Agora a testada ..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
static void Main(string[] args)
{
    try
    {
        var ObjetoParaSalvar = SimularObjetosParaSalvar();
 
        var Sessao = MySQLSessao.ObterSessao();
        var Transacao = Sessao.BeginTransaction();
        Sessao.SaveOrUpdate(ObjetoParaSalvar);
 
        Console.Write(":)");
 
        Transacao.Commit();
    }
    catch (Exception ex)
    {
        Console.Write(String.Format("{0} - {1} :(", ex.Message, (ex.InnerException).Message));
    }
 
    Console.ReadKey();
}
 
private static Autor SimularObjetosParaSalvar()
{
    var AutorDouglas = new Autor { Nome = "Douglas Adams" };
    var LivroMochileiro = new Livro {
        Nome = "Guia do Mochileiro das Galáxias",
        Editora = "Sextante",
        AnoLancamento = 2004
    };
    var AutoraLeticia = new Autor { Nome = "Leticia Verta" };
    var LivroRestaurante = new Livro {
        Nome = "O Restaurante no Fim do Mundo",
        Editora = "Sextante",
        AnoLancamento = 2004
    };
 
    AutorDouglas.AdicionarLivro(LivroMochileiro);
    AutorDouglas.AdicionarLivro(LivroRestaurante);
    AutoraLeticia.AdicionarLivro(LivroRestaurante);
 
    return AutorDouglas;
}

Não é necessário salvar um objeto por vez, visto que, como todos os objetos que criamos são relacionados entre si, tudo será salvo em cascata. Jóia, não?

Agora mãos a massa, de início a ferramenta parece meio engessada mas é só impressão (ou não). Open your mind! 😉

Bjokas

LINKS:

MySQL 5.1 – http://dev.mysql.com/downloads/mysql/5.1.html

Fluent NHibernate – http://fluentnhibernate.org/downloads

MySQL Connector/NET – http://leticiaverta.com/agregados/MySql.Data.dll

Fonte do projeto – http://leticiaverta.com/agregados/FluentNHibernateMySQL_WebLabz.rar