Arquivo mensais:junho 2009

Firefox 3.5 disponível!!!

Foi lançado hoje a nova versão deste formidável navegador.
http://www.getfirefox.com

Além de maior suporte aos padrões web mais atuais (HTML 5, CSS 2.1), aumentou bastante o desempenho, crucial para visitar sites Ajax:

O Firefox mais rápido de todos

As coisas mudam rapidamente na web, por isso melhoramos o motor do Firefox para assegurar que você possa acompanhá-las: o Firefox 3.5 é duas vezes mais rápido que o Firefox 3 e dez vezes mais rápido que o Firefox 2.* Dessa forma, aplicações Web como emails e sites de fotos estarão mais rápidas e sem atrasos.

Meu uso indica que está tão rápido quanto o Chrome: super ligeiro! Agora tenho a velocidade do Chrome e os plugins indispensáeis do Firefox, como o Firebug.

Embarcando código JavaScript

Ao se criar um Server Control em Asp.NET, e queremos que ele contenha lógica a ser executada no cliente recorremos ao Javascript.

Uma das maneiras de se incluir código Javascript no controle é este:

protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);
    if (!Page.ClientScript.IsClientScriptBlockRegistered("algumid"))
    {
        string script = @"
function MinhaFuncaoJS()
{
    ...
    ...
    ...
}
...
...
...
function OutraFuncaoJS()
{
    ...
    ...
    ...
}
";
        Page.ClientScript.RegisterClientScriptBlock(
            this.GetType(),
            "algumid",
            script,
            true);
    }
}

O que não é muito bom por alguns motivos, entre outros:

  • se torna difícil reutilizar código Javascript;
  • deve-se tomar cuidado ao incluir mais de um controle na página, pois acaba-se incluindo o mesmo código Javascript mais de uma vez na página;
  • é mais fácil cometer equívocos no código Javascript.

A maneira de se contornar isto é embarcando o código Javascript na aplicação – ou embedding the script resource.

Para tanto você apenas cria o arquivo contendo o script, por exemplo MeuProjeto/minhasfuncoes.js, o inclui no projeto e, através de suas propriedades, configura o item Build Action como Embedded Resource.

Propriedade para embarcar o arquivo

Modifique esta propriedade para Embedded

Isto inclui o script na DLL gerada na compilação. Para acessá-lo é preciso registrá-lo no AssemblyInfo.cs:

[assembly: WebResource("MeuProjeto.minhasfuncoes.js", "text/javascript")]

E depois em cada controle que irá utilizar o script:

protected override void OnPreRender(EventArgs e)
{
    Page.ClientScript.RegisterClientScriptResource(
        typeof(GeoImage),
        "MeuProjeto.minhasfuncoes.js");
    base.OnPreRender(e);
}

E pronto! O sistema irá incluir o script em sua página através de um handler WebResource.axd.

Ah! Se for necessário misturar recursos, tais como incluir o url de uma imagem embarcada em um javascript embarcado, coloque a opção PerformSubstitution:

[assembly: WebResource("MeuProjeto.minhasfuncoes.js", "text/javascript", PerformSubstitution =true)]
[assembly: WebResource("MeuProjeto.imagens.delete.png", "image/png")]

E para inserir a url da imagem em seu javascript basta incluir:

 <%= WebResource("MeuProjeto.imagens.delete.png")%>

.Net Assembly versioning

Estou enviando vários deploys de um sistema para produção.  Quem realmente deve colocar no ar é o pessoal encarregado do servidor. Como me assegurar que a aplicação mais atual já está no ar?

Podemos utilizar a versão do assembly do projeto para isto. Existe um atributo em .Net que marca a versão de sua aplicação. Este atributo é o AssemblyVersion.

Por default ele é marcado da seguinte maneira, no arquivo AssemblyInfo.cs:

[assembly:AssemblyVersion("1.0.*")]

A versão sempre segue o seguinte padrão:

<major version>.<minor version>.<build number>.<revision>

O que o asterisco faz é incrementar automaticamente o build number e revision. E, embora não esteja explícito na página da MSDN, no CodeProject tem a informação de que o build number gerado é o número de dias desde 1° de fevereiro janeiro de 2000, e o revision o número de segundos desde a meia noite divido por dois.

Daí é só utilizar o seguinte método:

public static string GetSystemVersion(HttpServerUtility server)
{
    string projectName = "NameOfYourProjectThatNamesYourDLL";
    Assembly assembly = Assembly.Load(projectName);
    return assembly.GetName().Version.ToString();
}

Coloque o valor gerado pelo método em algum lugar do sistema que você tenha acesso. Para calcular a data exata de build do assembly use este site: http://www.timeanddate.com/date/timeadd.html

PS: Este é o post 666. Creepy…..

Não consegue listar os Databases no SQL Management Studio?

O MS SQL Management Studio (SMS) é uma ferramenta excelente para gerenciar seus bancos de dados. Isto não quer dizer que ele não tenha seus problemas.

O pior deles é que, ao se tentar listar os bancos de dados do sistema, e você não tiver permissão para visualizar um deles, o SMS graciosamente te apresentará esta mensagem de erro:

Failed to retrieve data for this request. (Microsoft.SqlServer.Management.Sdk.Sfc)

Additional information:
An exception occured while executing a Transact-SQL statement or batch.
(Microsoft.SqlServer.ConnectionInfo)
The server principal “Seiti” is not able to access the database “AlgumBanco” under the current security context. (Microsoft SQL Server, Error: 916)

Como então listar os bancos de dados? Não sou o único nem serei o último a enfrentar este problema, então é claro que alguém já blogou sobre isto e o resolveu, inclusive mais de uma pessoa.

O problema consiste-se nas informações que são apresentadas no Object Explorer Details – para visualizá-lo tecle F7. Note as colunas que existem na visualização padrão: Name, Policy Health State, Recovery Model, Compatibilty Level , Collation e Owner.

Observe a coluna Collation. O SMS lista os bancos e verifica as informações que devem constar no Object Explorer Details.  Você não tem permissão sobre um dos bancos listados. Mas para saber o collation do banco deve-se ter permissões sobre o mesmo. O SMS entra em pânico, interrompe tudo, deixa de fazer o que deveria e mostra a mensagem de erro acima. Simples.

Como resolver? Clique com o direito sobre os nones das colunas e remova o Collation. O SMS ficará feliz da vida e fará o que devia fazer.

Desenvolvedor Web

Creio que qualquer pessoa da área já ficou em dúvida de como definir o próprio trabalho.  Programador,  engenheiro de sistemas,  arquiteto de software, desenvolvedor etc.

A fronteira entre um e outro é tênue, principalmente quando você integra uma equipe pequena, e se vê trabalhando no esboço do projeto, coleta de requisitos, definição de funcionalidades, estabelecimento de layout, modelando o banco de dados e o diagrama de classes e finalmente programando tudo isso, tendo de criar e modificar códigos em diferentes linguagens e domínios: C#, SQL, JavaScript, CSS, HTML  etc. A velha história de ter de cobrar o escanteio, cabecear e defender o gol.

Programador

Na comunidade  existe um certo preconceito quanto a se definir como programador.  O fato de ser um termo genérico demais, abrigando tanto o infeliz que aprendeu PHP faz uma semana e o líder de equipe de desenvolvimento, contribui para isto. Fora a infame piada que sempre contam quando você diz que é programador: “Ah! Então você vive de progamas?” entre outras variações.

Uma boa definição para o meu trabalho, que passei a utilizar para nomeá-lo,  é Web Developer ou Desenvolvedor Web.

Web Developer

E, afinal, o que é , faz ou se espera de um Desenvolvedor Web? Segundo a Wikipedia:

A web developer is a software developer or software engineer who is specifically engaged in the development of World Wide Web applications, or distributed network applications that are run over the HTTP protocol from a web server to a web browser.

Desta curta definição pode-se apreender que um desenvolvedor web deve conhecer e ter domínio em:

  • programar em linguagens ditas de servidor - C#, Java, PHP, Ruby etc. -  e de cliente – JavaScript/ActionScript/ECMAScript;
  • manipular elementos DOM;
  • editar elementos CSS;
  • escrever textos usando HTML;
  • entender o HTTP;
  • configurar um webserver.

E com programar em eu digo que deve-se ter destreza em ao menos um,  mas conhecer vários (se existirem, claro)  frameworks para cada linguagem.

Claro que não precisa se resumir a isto. Um bom desenvolvedor deve ter conhecimentos que vão desde redes de computadores a boas práticas em programação e padrões de projeto.

No fundo, no fundo

Eu uso Desenvolvedor Web para rotular meu trabalho por ser um termo cool o suficiente para constar no cartão de visita (ou moo cards para os descolados), mas lá no fundo eu sei que sou apenas um mero digitador, e meu trabalho consiste em martelar as teclas do computador (e às vezes ter vontade de martelar o computador…).

Google Local Business Center update

Li um post interessante no meu RSS Reader:

http://googleblog.blogspot.com/2009/06/local-business-center-dashboard-opens.html

Atualizaram o serviço e incluíram mais opções. Se você não conhece, o Google Local Business Center, ou Google LBC,  permite ao proprietário de uma empresa que apareça  no mapa do Google Maps,  editar os dados apresentados.

Assim pode-se atualizar o telefone de contato, adicionar informações e tudo mais. Para isto é necessário provar que você é realmente responsável pela empresa, e aí entra em campo, em uma das opções,  o velho e conhecido correio.  Aquele do envelope e selo, lembra?

Bom, parece que existem indicadores interessantes para aqueles que possuem empresas com localização física:

  • Impressions: The number of times the business listing appeared as a result on a Google.com search or Google Maps search in a given period.
  • Actions: The number of times people interacted with the listing; for example, the number of times they clicked through to the business’ website or requested driving directions to the business.
  • Top search queries: Which queries led customers to the business listing; for example, are they finding the listing for a cafe by searching for “tea” or “coffee”?
  • Zip codes where driving directions come from: Which zip codes customers are coming from when they request directions to your location.

Em resumo, são estatísticas geradas pelo próprio Google e seu sistema
Google Maps, quando seu uso faz referência à sua empresa. Eu diria que
servem para complementar o Google Analytics.

Explicit construction of entity type ‘###’ in query is not allowed

Estava eu programando, feliz da vida, quando percebi subitamente que felicidade e programação não se misturam muito bem. Surge então esta mensagem de erro:

A construção explícita do tipo de entidade ‘###’ na consulta não é permitida.

ou, em bom inglês Google friendly:

Explicit construction of entity type ‘###’ in query is not allowed

O código que gerou a mensagem pouco agradável foi este:

var res =
    from m in MyDataContext.INSCRICAOs
    group m by m.PESSOA into p
    select new MAILING()
    {
        idMailingTexto = idMailingTexto,
        nomPessoa = p.First().PESSOA.nomPessoa,
        eMail = p.First().PESSOA.eMail,
        flaEnviado = false,
    };

Minha intenção é de, a partir de dados extraídos da tabela INSCRICAO, criar entradas na tabela MAILING, usando o Linq To SQL (sem sermões sobre formas normais em banco de dados, por favor). Mas o Linq não deixa eu criar estes objetos MAILING, não a partir de uma consulta do próprio Linq.

O problema, que descobri ser um feature (como se traduz isto para o português?) parece ser antigo, e a resposta é esta:

This check was added because it was supposed to be there from the beginning and was missing.  Constructing entity instances manually as a projection pollutes the cache with potentially malformed objects, leading to confused programmers and lots of bug reports for us. In addition, it is ambiguous whether projected entities should be in the cache or changed tracked at all. The usage pattern for entities is that they are created outside of queries and inserted into tables via the DataContext and then later retrieved via queries, never created by queries.

Para mim isto é nivelar por baixo, mas enfim. O jeito foi criar um objeto idêntico ao existente, que chamei de MAILINGCLONE:

public class MAILINGCLONE
{
    public int idMailingTexto { get; set; }
    public string nomPessoa { get; set; }
    public string eMail { get; set; }
    public bool flaEnviado { get; set; }
    public DateTime datAtualiza { get; set; }
}

E trocar a consulta para:

var res =
    from m in MyDataContext.INSCRICAOs
    group m by m.PESSOA into p
    select new MAILINGCLONE()
    {
        idMailingTexto = idMailingTexto,
        nomPessoa = p.First().PESSOA.nomPessoa,
        eMail = p.First().PESSOA.eMail,
        flaEnviado = false
    };

Isto até que não doeu. O que dói no coração é trocar isto:

dc.MAILINGs.InsertAllOnSubmit(mails);
dc.SubmitChanges();

por isto:

foreach (MAILINGCLONE mc in mails)
{
    MAILING m = new MAILING()
    {
        idMailingTexto = mc.idMailingTexto,
        nomPessoa = mc.nomPessoa,
        eMail = mc.eMail,
        flaEnviado = mc.flaEnviado,
        codPessoa = mc.codPessoa,
        datAtualiza = DateTime.Now
    };
    dc.MAILINGs.InsertOnSubmit(m);
}
dc.SubmitChanges();