Forçando o WWW na url com Url Rewriting

09/21/2010 21:21:00 By Felipe Pessoto

Uma dica para padronizar as urls do seu site, que hoje são muito importantes por causa do SEO.

Para forçar sempre o WWW, basta adicionar a rule no system.webServer -> rules:

<rule name="Add WWW prefix" >
<match url="(.*)" ignoreCase="true" />
<conditions>
<add input="{HTTP_HOST}" pattern="^domain\.com" />
</conditions>
<action type="Redirect" url="http://www.domain.com/{R:1}"
redirectType="Permanent" />
</rule>

ou caso prefira sempre remover o WWW

<rule name="Remove WWW prefix" >
<match url="(.*)" ignoreCase="true" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.domain\.com" />
</conditions>
<action type="Redirect" url="http://domain.com/{R:1}"
redirectType="Permanent" />
</rule>

Corrigindo RangeValidator e CompareValidator em browsers não IE

06/28/2010 23:28:00 By Felipe Pessoto

Os validator RangeValidator e CompareValidator permitem validar se o texto digitado pode ser convertido para um certo tipo, como DateTime. Porém em browsers não IE ocorre um erro de javascript quando se usa datas com 2 dígitos no ano. Para corrigir isto pode-se usar o seguinte javascript para sobrescrever o método original:

function ValidatorConvert(op, dataType, val) {
    function GetFullYear(year) {
        var twoDigitCutoffYear = val.cutoffyear % 100;
        var cutoffYearCentury = val.cutoffyear - twoDigitCutoffYear;
        return ((year > twoDigitCutoffYear) ? (cutoffYearCentury - 100 + year) : (cutoffYearCentury + year));
    }
    var num, cleanInput, m, exp;
    if (dataType == "Integer") {
        exp = /^\s*[-\+]?\d+\s*$/;
        if (op.match(exp) == null)
            return null;
        num = parseInt(op, 10);
        return (isNaN(num) ? null : num);
    }
    else if (dataType == "Double") {
        exp = new RegExp("^\\s*([-\\+])?(\\d*)\\" + val.decimalchar + "?(\\d*)\\s*$");
        m = op.match(exp);
        if (m == null)
            return null;
        if (m[2].length == 0 && m[3].length == 0)
            return null;
        cleanInput = (m[1] != null ? m[1] : "") + (m[2].length > 0 ? m[2] : "0") + (m[3].length > 0 ? "." + m[3] : "");
        num = parseFloat(cleanInput);
        return (isNaN(num) ? null : num);
    }
    else if (dataType == "Currency") {
        var hasDigits = (val.digits > 0);
        var beginGroupSize, subsequentGroupSize;
        var groupSizeNum = parseInt(val.groupsize, 10);
        if (!isNaN(groupSizeNum) && groupSizeNum > 0) {
            beginGroupSize = "{1," + groupSizeNum + "}";
            subsequentGroupSize = "{" + groupSizeNum + "}";
        }
        else {
            beginGroupSize = subsequentGroupSize = "+";
        }
        exp = new RegExp("^\\s*([-\\+])?((\\d" + beginGroupSize + "(\\" + val.groupchar + "\\d" + subsequentGroupSize + ")+)|\\d*)"
                        + (hasDigits ? "\\" + val.decimalchar + "?(\\d{0," + val.digits + "})" : "")
                        + "\\s*$");
        m = op.match(exp);
        if (m == null)
            return null;
        if (m[2].length == 0 && hasDigits && m[5].length == 0)
            return null;
        cleanInput = (m[1] != null ? m[1] : "") + m[2].replace(new RegExp("(\\" + val.groupchar + ")", "g"), "") + ((hasDigits && m[5].length > 0) ? "." + m[5] : "");
        num = parseFloat(cleanInput);
        return (isNaN(num) ? null : num);
    }
    else if (dataType == "Date") {
        var yearFirstExp = new RegExp("^\\s*((\\d{4})|(\\d{2}))([-/]|\\. ?)(\\d{1,2})\\4(\\d{1,2})\\s*$");
        m = op.match(yearFirstExp);
        var day, month, year;
        if (m != null && m.length > 2 && m[2] && (m[2].length == 4 || val.dateorder == "ymd")) {
            day = m[6];
            month = m[5];
            year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10))
        }
        else {
            if (val.dateorder == "ymd") {
                return null;
            }
            var yearLastExp = new RegExp("^\\s*(\\d{1,2})([-/]|\\. ?)(\\d{1,2})\\2((\\d{4})|(\\d{2}))\\s*$");
            m = op.match(yearLastExp);
            if (m == null) {
                return null;
            }
            if (val.dateorder == "mdy") {
                day = m[3];
                month = m[1];
            }
            else {
                day = m[1];
                month = m[3];
            }
            year = (m[5] && m[5].length == 4) ? m[5] : GetFullYear(parseInt(m[6], 10))
        }
 
        if (Number(year) > 0 && Number(month) > 0 && Number(day) > 0) {
            month -= 1;
            var date = new Date(year, month, day);
            if (year < 100) {
                date.setFullYear(year);
            }
            return (typeof (date) == "object" && year == date.getFullYear() && month == date.getMonth() && day == date.getDate()) ? date.valueOf() : null;
        }
        else
            return null;
    }
    else {
        return op.toString();
    }
}

IEqualityComparer facilitado

02/25/2010 23:16:00 By Felipe Pessoto

Quando usamos o Linq temos alguns extension methods muito úteis como Distinct e Except. Porém para fazer uma comparação customizada é necessário criar uma classe que herde de IEqualityComparer<T> e passar uma instancia como parâmetro, o que considero muito sujo, principalmente se cada comparar for de um jeito.

Encontrei uma solução no blog do Brendan Enrick, porém pra mim não funcionou. não sei se fiz algo errado, mas o LINQ sempre chamava primeiro o GetHashCode, que se não fosse igual já retornava false sem nem passar pelo Equals. Alterei para aceitar uma Func que será usada no GetHashCode também, assim só precisamos dessa classe e podemos fazer a chamada da seguinte forma:

List<MyObject> x = myCollection.Except(otherCollection, (x, y) => x.Codigo == y.Codigo, z => z.Codigo).ToList();

Onde "(x, y) => x.Codigo == y.Codigo" é nossa comparação, e  z => z.Codigo o GetHashCode. Assim usamos o Except ou Distinct da mesma maneira que o Where, First, Any, etc

Código:

public static class InterfaceEnumerableExtension
{
     public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first,
     IEnumerable<TSource> second, Func<TSource, TSource, bool> comparer, Func<TSource, int> hashFunction)
     {
         return first.Except(second, new LambdaComparer<TSource>(comparer, hashFunction));
     }
 }

public class LambdaComparer<T> : IEqualityComparer<T>
{
     private readonly Func<T, T, bool> lambdaComparer;
     private readonly Func<T, int> lambdaHash;

     public LambdaComparer(Func<T, T, bool> lambdaComparer, Func<T, int> lambdaHash)
     {
         if (lambdaComparer == null)
             throw new ArgumentNullException("lambdaComparer");
         if (lambdaHash == null)
             throw new ArgumentNullException("lambdaHash");

         this.lambdaComparer = lambdaComparer;
         this.lambdaHash = lambdaHash;
     }

     public bool Equals(T x, T y)
     {
         return lambdaComparer(x, y);
     }

     public int GetHashCode(T obj)
     {
         return lambdaHash(obj);
     }
}

 

Desafio V - Retornando tipos anônimos

01/13/2010 09:41:00 By Felipe Pessoto

Os tipos anônimos introduzidos no C# 3.0 para facilitar o uso do LINQ agilizam o desenvolvimento, evitando que tenhamos que declarar uma classe em casos específicos.

Mas esses tipos tem alguma limitações, intencionais, por exemplo, não podemos usar os tipos gerados como retorno ou parâmetro de um método. Até porque os tipos gerados são internal.

O desafio é retornar um tipo anônimo e usá-lo no seu código, sem usar Reflection. Não tem uso prático, já que não é uma boa prática fazer isso, mas serve como exercício.

 

Para adiantar, vou postar o método que faz o retorno:

public static object RetornaAnonimo()
{
    return new {Id = 1, Nome = "João"};
}

 

Agora resta conseguir usar o tipo numa chamada. Ex.:

var retorno = RetornaAnonimo();
...

 

Desafio IV - Sobrecarga de métodos

09/24/2009 23:10:00 By Felipe Pessoto

Considerando o seguinte código, qual será o resultado?

class Program
{
      static void Main()
      {
           Derived c = new Derived();
           c.Metodo(1);
      }
}

public class Base
{
      public void Metodo(int a)
      {
           Console.WriteLine("Int32 / " + a.GetType());
      }
}

public class Derived:Base
{
      public void Metodo(object a)
      {
          Console.WriteLine("Object / " + a.GetType());
      }
}