quarta-feira, 14 de dezembro de 2011

Problema no TFS após resolução de conflitos, como encontrar código ou texto perdido

Nunca tive grandes problemas com o TFS nomeadamente a resolver conflitos, mas ontem aconteceu que perdi um teste automático depois de resolver um conflito ao fazer GetLatest, o projeto permite check-out não-exclusivos e, sem perceber muito bem o que aconteceu, hoje ao fazer GetLatest, surpresa minha, o código do teste tinha desaparecido.

Sem investigar muito a razão do que aconteceu encontrei o meu teste no folder:
%TMP%\TFSTemp

Basta introduzir isto no Run no menu Iniciar do Windows para abrir o folder temporário onde o Team Foundation Server (client) guarda o ficheiro após a resolução de conflitos. Bastou-me fazer um find para encontrar o código desaparecido.

segunda-feira, 12 de dezembro de 2011

Função genérica para converter string num enumerado.

Uma  forma genérica para converter uma string num Enum, uso isto na forma de uma extensão.
Exemplo de utilização:
string s = "Primeiro";
PosicaoEnum teste = s.ToEnum<PosicaoEnum>();

public static T ToEnum<T>(this string s)
{
    T[] possibleValues = (T[]) Enum.GetValues(typeof(T));
    foreach(T val in possibleValues){
        string valString = val.ToString();
        if (valString == s)
        {
            return val;
        }
    }
    throw new ArgumentException(
        string.Format(
            "Cannot find \"{0}\" in the enum \"{1}\".",
            s, typeof(T).ToString()));
}

sexta-feira, 25 de novembro de 2011

Google Maps v3: Problema ao renderizar mapa oculto

Recentemente tive que implementar uma página com vários mapas do google, cada um dentro do seu separador (Tab).
O problema surgiu quando clico num separador, o mapa não renderiza como devia e não fica centrado na posição indicada.

A solução encontrada foi a seguinte:

Quando ocorre o clique no separador efectuar o seguinte:
  1. Guardar a posição.
  2. Disparar o evento resize para que o mapa redesenhe como devia.
  3. Centrar o mapa na posição que estava.

Aqui fica o código javascript com a solução.
function fixMap(map) {
    var center = map.getCenter();
    google.maps.event.trigger(map, "resize");
    map.setCenter(center);
}

quinta-feira, 24 de novembro de 2011

SharePoint 2010: Operador In, Caml

O SharePoint 2010 apresenta um novo operador nas Caml queries.
O operador em questão é o operador In que evita que tenhamos de escrever múltiplos Or.

Por exemplo, se tivermos o campo chamado Browser do tipo Text e quisermos procurar  os registos que têm  a palavra Firefox ou a palavra Chrome escrevemos a seguinte Caml query.

<Where>
  <In>
    <FieldRef Name='Browser' />
    <Values>
      <Value Type='Text'>Firefox</Value>
      <Value Type='Text'>Chrome</Value>
    </Values>
  </In>
</Where>

Como nem sempre as nossas queries são estáticas apresento uma forma de gerar o operador In dinamicamente através de uma coleção.

public static string InCaml(IEnumerable<string> items, string type, string name)
{
    string inFormat = "<Value Type='{0}'>{1}</Value>";

    var values = new StringBuilder();
    values.Append("<Values>");
    foreach (string item in items)
    {
        values.AppendFormat(inFormat, type, item);
    }
    values.Append("</Values>");

    var fieldRef = string.Format("<FieldRef Name='{0}' />", name);

    return string.Format("<In>{0}{1}</In>", fieldRef, values.ToString());
}


Exemplo de como chamar o método InCaml.

InCaml(new string[] { "Firefox""Chrome" }, "Text""Browser");

quinta-feira, 17 de novembro de 2011

Papercut - Servidor de SMTP

O Papercut é um servidor de SMTP que permite apenas receber e visualizar as mensagens.
É incrivelmente simples e prático, sendo bastante util para desenvolvimento de aplicações e não necessita de configurações.

quarta-feira, 16 de novembro de 2011

Deep compare de dois objectos em C#

Estava a implementar um teste e gostaria de comparar duas propriedades que eram classes complexas, no entanto é bastante complicado comparar todos os tipos de classes, sobretudo se forem colecções (IList, array, etc.). Após alguma pesquisa encontrei este projecto no codeplex que suporta a maioria dos tipos que uso no projecto:

http://comparenetobjects.codeplex.com/releases/view/47978

Este utilitário está todo implementado numa classe e usa reflection para correr as propriedades todas e é bastante fácil de usar com as opções default:

CompareObjects comparer = new CompareObjects();
return comparer.Compare(obj1, obj2);

domingo, 13 de novembro de 2011

Javascript: Converter uma string num array de caracteres

Em javascript para converter uma string num array de caracteres usamos o método split em que passamos por parametro uma string vazia.

Exemplo: 
"123456789".split("")

Resultado:
["1", "2", "3", "4", "5", "6", "7", "8", "9"]


quinta-feira, 10 de novembro de 2011

Parse do request no evento IDispatchMessageInspector.AfterReceiveRequest

Uma das melhores funcionalidades dos WCF WebServices é sua flexibilidade e capacidade de adicionar código nosso em quase qualquer parte do ciclo de vida do Request. Uma das hipoteses é usar um "inspector" de mensagens para, por exemplo, validar segurança ou alterar conteúdos de um Request.

Quando o pedido é recebido ainda não está deserializado para a respectiva classe .Net, achei problemático fazer esta deserialização. Após alguma investigação uma das formas que encontrei foi usar a classe TypedMessageConverter.

Nota: atenção que ao deserializar a mensagem é preciso criar uma cópia da Message usando este código:
MessageBuffer msgBuffer = message.CreateBufferedCopy(MaxMessageSize);
mais detalhes: http://social.msdn.microsoft.com/Forums/en/wcf/thread/cfef6695-8f6d-468f-9db5-8a27ee5a4b8f

Depois é possível deserializar o body da message com um método genérico:

public static T ParseBody(Message message)
{            TypedMessageConverter converter =
                  TypedMessageConverter.Create(typeof(T), message.Headers.Action);
            T body = (T)converter.FromMessage(message);
            return body;
}
mais detalhes: http://social.msdn.microsoft.com/Forums/en/wcf/thread/fd7f8df9-4a83-4285-be91-b9adb0c1888a

domingo, 30 de outubro de 2011

SharePoint 2010: Esconder a Ribbon dos utilizadores anónimos

No SharePoint 2010, para esconder a ribbon dos utilizadores anónimos é necessário utilizar o controlo LoginView do ASP.net.

No AnonymousTemplate colocasse a seguinte regra de CSS #s4-ribbonrow { display: none;} para esconder a ribbon.
Exemplo:
    <asp:LoginView ID="Loginview1" runat="server">
        <AnonymousTemplate>
            <style type="text/css">
                #s4-ribbonrow
                {
                    display: none;
                }
            </style>
        </AnonymousTemplate>
    </asp:LoginView>

quarta-feira, 19 de outubro de 2011

Lentidão no arranque do Firefox 7.0.1

Tenho notado alguma lentidão a abrir e a usar o Firefox 7.0.1, após alguma pesquisa no google a sugestão que funcionou para mim foi ir às Opções » Avançado » Geral » Desactivar Usar Aceleração por hardware quando disponível.

Realmente parece mais rápido tanto a abrir como a usar.

quinta-feira, 25 de agosto de 2011

Enumerações repetidas ao adicionar uma Service Reference no Visual Studio 2010.

Estava a criar um WCF WebService e estava a gerar enumerações duplicadas, exemplo:  enum Tipo, enum Tipo2, enum Tipo3, etc.
Reparei que cada uma desta enumerações na Reference.cs tinha um namespace diferente. Após alguns testes, esta combinação funcionou para mim:

[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.teste.pt/exemplo/Tipo", IsNullable = true)]
[DataContract(Namespace = "http://www.teste.pt/exemplo/Tipo")]
[XmlTypeAttribute(Namespace="http://www.teste.pt/exemplo/Tipo")]
 public enum Tipo { ... }

O último atributo parece ter sido o que corrigiu a situação, as outras duas já existiam. Isto ainda precisa de mais uns testes mas pode ajudar alguém.

sexta-feira, 5 de agosto de 2011

Boot a partir de uma VM (apenas VHD).

Usar VMs normalmente pode ser um problema se o host não tiver recursos suficientes ou se pretendemos mais rapidez, um colega encontrou o seguinte blog que explica como criar uma VM na tecnologia VHD (usada pelo Virtual PC e Hyper-V por exemplo), e usar essa VM para fazer um boot alternativo ao Sistema Operativo instalado (Win7 64bits).
http://technet.microsoft.com/en-us/edge/ff944958

Desta forma usamos os recursos todos do host e, o melhor, podemos correr o ficheiro da VM a partir de um disco duro externo e ainda ter acesso aos discos que já existem na máquina.

Infelizmente não encontrei forma de converter VMs feitas para Virtual Box para VHD.

[Update]
Obrigado ao utilizador anónimo pela dica, vou experimentar este comando para transformar VMs feitas para VirtualBox para VHD...
Via cmd
VBoxManage clonehd source.vdi target.vhd --format vhd

quinta-feira, 4 de agosto de 2011

SharePoint reserved querystring parameters

Para quem já teve más experiências a usar parâmetros num url para uma página customizada no SharePoint deixo um blog que indica algumas keywords reservadas para a construção de urls.
http://blogs.technet.com/b/stefan_gossner/archive/2009/01/30/querystring-parameters-you-should-not-use-in-your-sharepoint-application.aspx

Além das que o autor indica, também não aconselho muito usar a letra "k" como parâmetro porque é usada pelas webparts de resultados de pesquisa do SharePoint.
  • FeatureId
  • ListTemplate
  • List
  • ID
  • VersionNo
  • ContentTypeId
  • RootFolder
  • View
  • FolderCTID
  • Mode
  • Type

terça-feira, 2 de agosto de 2011

.NET: Codificação de caracteres XML inválidos numa string

Para quêm precisa de codificar strings xml tem uma alternativa para quem não quer fazer replace dos caracteres.
O método para fazer a codificação é SecurityElement.Escape localizado no namespace System.Security.


Exemplo: 
tagText = SecurityElement.Escape(tagText);

Fonte: http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape.aspx

segunda-feira, 31 de janeiro de 2011

Alterar conteúdos de um WSP

Por vezes podem ser necessárias pequenas alterações aos conteúdos de um WSP. Na última situação que encontrei tive que remover uma feature de um WSP resultante de uma exportação de um modelo de um sub-site, que estava a impedir a criação de novos sub-site baseados nessa custom site template porque tinha removido uma das features de um projecto sharepoint de webparts.

A solução mais fácil que encontrei foi:
  • Extrair os conteúdos da custom site template (wsp) com o 7-zip
  • Fiz um find pela guid que estava a ser referenciada (mas não utilizada)
  • Alterei o ficheiro ONET.xml e voltei a empacotar tudo de usando o IZARc
Para re-criar o ficheiro WSP:
  • Abrir o IZARc, seleccionar a opção Novo 
  • Escolher o nome do ficheiro que vamos gerar (.cab) e Open
  • Seleccionar os conteúdos todos tal como estavam no WSP e antes de dar o OK ir às options e seleccionar a opção "incluir sub-pastas", o tipo de arquivo deve ser CAB e as restantes opções por omissão.
  • Assim que se dá o OK o arquivo .cab é criado e basta sair do IZARc, mudar a extensão e/ou nome do ficheiro para o prentendido .wsp e está pronto para ser deployed.

quinta-feira, 20 de janeiro de 2011

SharePoint 2010 Calculated Fields

Está disponível no MSDN um artigo bastante completo sobre como usar os calculated fields no SharePoint 2010:
http://msdn.microsoft.com/en-us/library/bb862071.aspx

Por exemplo, é bastante fácil concatenar duas propriedades:
=[Primeiro Nome]&[Segundo Nome]

SharePoint Inspector Tool

Está disponível no codeplex uma ferramenta muito útil para quem desenvolve para SharePoint, funciona bem com o SharePoint 2010. Vale a pena experimentar:
http://spi.codeplex.com/

Para ver os sites numa WebApplication em SharePoint 2010 está disponível em:
Farm > Services > Microsfot Sharepoint Foundation Web Application > WebSites

Esta ferramenta até permite ver os Event Receivers das listas e remove-los caso seja necessário.
Para adiconar Event Receivers recomendo a ferramenta disponível no seguinte blog:
http://weblogs.asp.net/vikram/archive/2009/01/07/Sharepoint-Adding-event-handler-to-the-list-with-the-help-of-a-generic-event-handler.aspx