Paulo Morgado
Tudo sobre .NET

My Links

Blog Stats
  • Posts - 251
  • Stories - 4
  • Comments - 119
  • Trackbacks - 15
News
Subscreva o feed deste blogue Subscreva o feed dos meus artigos (Inglês) Subscreva o feed das minhas leituras (Inglês) Subscreva o feed das podcasts a que assisto (Inglês) páginas carregadas
Leitores Recentes
Top 5 Links
Localização dos Visitantes
O Meu Perfil
  • My profile on Naymz
  • My profile on Plaxo
  • My profile on Viadeo
  • Paulo Morgado's Rapleaf Score
  • Typemock fan
  • Meet the experts

Story Categories

Archives

Post Categories

Eventos

Thursday, October 09, 2008

O PDC deste ano é todo acerca da cloud (núvem – ou nebulosa, como eu lhe chamo) e a .NET Framework 4.0.

Ninguém da Microsoft me disse que os Windows Forms tinham os dias contados (antes pelo contrário) mas, olhando para  lista de sessões do PDC deste ano, só vejo WPF.

Portanto, a questão mantem-se: Será o fim dos Windows Forms?

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 1:39 AM | Feedback (4)

Monday, October 06, 2008

Esta versão adiciona o suporte para métodos estáticos e metódos não públicos à API AAA. Vejam as notas de lançamento.

Não me agrada muito a aproximação reflectiva ao teste de membros privados.

Com as novas adicões à API AAA, testar esta classe:

public class MyClass
{
    public string Public()
    {
        return this.Private();
    }

    private string Private()
    {
        throw new NotImplementedException();
    }
}

pode ser feito assim:

[TestMethod]
[Isolated]
public void PrivateTest()
{
    MyClass fake = Isolate.Fake.Instance<MyClass>();

    Isolate.WhenCalled(() => fake.Public()).CallOriginal();

    Isolate.NonPublic.WhenCalled(fake, "Private").WillReturn("FAKE");

    string fakePublic = fake.Public();

    Assert.AreEqual("FAKE", fakePublic);

    Isolate.Verify.WasCalledWithExactArguments(() => fake.Public());

    Isolate.Verify.NonPublic.WasCalled(fake, "Private");
}

Agradava-me mais que fosse assim:

[TestMethod]
[Isolated]
public void PrivateTest()
{
    MyClass fake = Isolate.Fake.Instance<MyClass>();

    MyClass_Accessor fakeAccessor = MyClass_Accessor.AttachShadow(fake);

    Isolate.WhenCalled(() => fakeAccessor.Private()).WillReturn("FAKE");

    Isolate.WhenCalled(() => fake.Public()).CallOriginal();

    string fakePublic = fake.Public();

    Assert.AreEqual("FAKE", fakePublic);

    Isolate.Verify.WasCalledWithExactArguments(() => fake.Public());

    Isolate.Verify.WasCalledWithExactArguments(() => fakeAccessor.Private());
}

Parece a mesma coisa mas não há nomes de métodos no código de teste.

Eles conseguiram fazê-lo para os Natural Mocks. Certamente que o conseguirão fazer para AAA.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:49 PM | Feedback (0)
 

Há algum tempo perguntaram-me se seria possível forjar parâmetros de saída usando o Typemock Isolator.

Na verdade é muito fácil de o fazer usand qualquer uma das APIs disponíveis.

Dada esta classe:

public class MyClass
{
    public bool MyMethod(string input, out int output1, out double output2)
    {
        throw new NotImplementedException();
    }
}

Usando a nova API AAA, é tão limpo omo:

[TestMethod]
[Isolated]
public void TestMethodIsolated()
{
    MyClass target = Isolate.Fake.Instance<MyClass>();

    string input = "test value";
    int expectedOutput1 = 1;
    double expectedOutput2 = 2;

    Isolate.WhenCalled(() => target.MyMethod(input, out expectedOutput1, out expectedOutput2)).WillReturn(true);

    int output1;
    double output2;
    bool result = target.MyMethod(input, out output1, out output2);

    Assert.IsTrue(result);
    Assert.AreEqual<int>(expectedOutput1, output1);
    Assert.AreEqual<double>(expectedOutput2, output2);
}

Usando Natural Mocks, é tão fácil como:

[TestMethod]
[VerifyMocks]
public void TestMethodNatural()
{
    MyClass target = RecorderManager.CreateMockedObject<MyClass>();

    string input = "test value";
    int expectedOutput1 = 1;
    double expectedOutput2 = 2;

    using (RecordExpectations recorder = RecorderManager.StartRecording())
    {
        recorder.ExpectAndReturn(target.MyMethod(input, out expectedOutput1, out expectedOutput2), true);
    }

    int output1;
    double output2;
    bool result = target.MyMethod(input, out output1, out output2);

    Assert.IsTrue(result);
    Assert.AreEqual<int>(expectedOutput1, output1);
    Assert.AreEqual<double>(expectedOutput2, output2);
}

Também é possível usando Reflective Mocks:

[TestMethod]
[VerifyMocks]
public void TestMethodReflective()
{
    MockObject<MyClass> targetMock = MockManager.MockObject<MyClass>();

    string input = "test value";
    int expectedOutput1 = 1;
    double expectedOutput2 = 2;

    targetMock.ExpectAndReturn(
        "MyMethod",
        new DynamicReturnValue(delegate(object[] parameters, object context)
            {
                parameters[1] = expectedOutput1;
                parameters[2] = expectedOutput2;
                return true;
            }));

    int output1;
    double output2;
    bool result = targetMock.Object.MyMethod(input, out output1, out output2);

    Assert.IsTrue(result);
    Assert.AreEqual<int>(expectedOutput1, output1);
    Assert.AreEqual<double>(expectedOutput2, output2);
}

Só é preciso escolher a API de que se gosta mais.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 10:05 PM | Feedback (0)

Tuesday, September 30, 2008

Monday, September 22, 2008

Mais uma vez estarei numa banca ATE no Tech·Ed EMEA 2008 Developers.

tal como já tinha dito acerca do PDC, o que gosto mais destes eventos é a convivência com as pessoas da Microsoft e com os outros participantes. Portanto, se se quiserem encontrar comigo, terei muito gosto em encontrar-me convosco.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 1:23 AM | Feedback (0)
 

O Luís acabou de dar a notícia acerca do nosso livro sobre LINQ com C#.

Foi com enorme honra que aceitei o convite do Luís para escrever este livro para a FCA, para quem ele já tinha publicado alguns livros [^] [^] [^].

Este será um livro de introdução em Português dirigido a quem quiser aprender LINQ com C#.

Tem sido um projecto divertido com grandes discuções (possíveis apenas porque meio oceano nos separa :) ).

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 12:57 AM | Feedback (0)

Thursday, September 04, 2008

Não é a primeira vez que tento mas, por uma razão ou outra, esta é a primeira vez que vou ao PDC (Microsoft’s Professional Developers Conference).

De acordo com o sítio do evento, “O PDC é projectado para arquitectos de software e programadores avançados. Se estão interessados no futuro da plataforma Microsoft, se são responsáveis pela estratégia tecnológica a vossa organização ou se são profissionais altamente qualificados que gostam de mergulhar o coração da plataforma, então o PDC é para vós!”. Se se revêm nesta descrição, não percam tempo e registem-se. O desconto Early Bird foi extendido até 8 de Setembro.

O que gosto mais destes eventos é a convivência com as pessoas da Microsoft e com os outros participantes. Portanto, se se quiserem encontrar comigo, terei muito gosto em encontrar-me convosco.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 1:53 AM | Feedback (0)

Friday, August 29, 2008

Thursday, August 28, 2008

Clone Detective for Visual Studio

O Clone Detective é uma ferramenta que integra com o Visual Studio e usa o ConQAT (Continuous Quality Assessment Toolkit) para analizar projectos C# e procurar código fonte duplicado.

Vejam os vídeos e vejam se esta é a ferramenta que procuravam.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:46 PM | Feedback (0)

Thursday, August 21, 2008

A Microsoft Press criou  um URL exclusivo para um desconto na subscrição da E-Reference Library para os MVPs passarem à comunidade, sem quaisquer limitações ou restrições.

Para criar uma subscrição experimental, deve ser usado o URL Experimental (http://microsofteref2.books24x7.com/promo.asp?ref=mvptry).

Qualquer membro da comunidade que subscreva a E-Reference Libraries através do URL de Subscrição (http://microsofteref2.books24x7.com/promo.asp?ref=mvpbuy) terá direito a um desconto de 40% numa subscrição de um ano.

Esta oferta termina a 30 de Setembro de 2008.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:46 PM | Feedback (0)
 

A equiopa do StyleCop anunciou a saída da versão 4.3 da ferramenta StyleCop. Podem obtê-la aqui.

Esta versão contem algumas correcções de erros, novas regras e documentação.

Também nesta versão, a lista de erros e avisos vai para a janela Errors List como acontece com os compiladores. Gostava que os erros e avisos também fossem para a janela Output.

A documentação do SDK para o desenvolvimento de regras próprias e integração com outros sistemas de build é esperada para breve.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 12:42 AM | Feedback (0)

Wednesday, August 20, 2008

Convenhamos, quem não conhece o .NET Reflector não pode afirmar que desenvolve em .NET.

Hoje, a Red Gate anunciou a aquisição do Lutz Roeder’s .NET Reflector.

Na nova página do .NET Reflector, a Red Gate afirma que “continuará a manter uma versão gratuita para o benefício da comunidade”.

Podem ler a entrevista com Lutz Roeder e James Moore (director geral de ferramentas de desenvolvimento .NET da Red Gate) na simple-talk.

O James ainda não sabe como melhorar o Reflector, mas eu sei. O Reflector necessita de importantes melhoramentos ao nível da usabilidade da interface com o utilizador. Vejamos se consigo arranjar uma lista:

  • Para mim, a pesquisa enquanto se digita não é uma boa ideia tal como está no Reflector.
  • Ainda no tema da pesquisa, pesquisa enquanto se digita já seria uma boa ideia para a janela de código.
  • Não consigo perceber porque mudar alguma opção dispara um refrescamento total da aplicação perdendo-se a janela de código.
  • Definições como a formatação de código, documentação ou números deveria ser possível apenas com o simples premir de um botão numa barra de botões.

Tenho a certeza que a Red Gate é mais do que capaz de tomar bem conta do .NET Reflector.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:54 PM | Feedback (0)
 

A Typemock lançou uma versão alfa do seu mais recente produto: Typemock Racer.

O Typemock Racer é a ferramenta que usa análise dinâmica e estática para encontrar bloqueios em código .NET que tinha sido anuncianda pelo Roy Osherove.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:45 PM | Feedback (0)
 

A Typemock lançou a versão 5.0 da sua ferramenta de testes unitários: Isolator. Vejam as notas de lançamento.

Esta mais recente versão vem com a nova API: Arrange Act Assert (Preparar – Executar - Validar):

Devo dizer que gostava mais de Isolator do que Isolate.

Também novidade nesta versão é a inclusão do ficheiro de ajuda no pacote de instalação.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:41 PM | Feedback (0)

Sunday, August 17, 2008

Enquanto instalava o SQL Server 2008 numa máquina virtual Virtual PC, fiquei sem espaço no disco virtual.

Pesquisei e encontrei esta ferramenta: VHD Resizer. É necessário registo para descarregar a ferramenta.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:16 PM | Feedback (0)

Tuesday, August 12, 2008

Monday, August 11, 2008

No passado apresentei um outro possível uso para a palavra-chave using: como dicas LINQ.

Tenhno vindo a pensar mais neste assunto e refinei a minha proposta.

var q = from person in personCollection using MyEnumerableExtensions
        group person by person.LastName into g using new MyOtherComparer()
        orderby g.Key using new MyComparer()
        select person;

A consulta acima seria traduzida para:

var q = MyEnumerableExtensions.OrderBy<string, Person>(
    MyEnumerableExtensions.GroupBy<string, Person>(
        personCollection,
        person => person.LastName,
        new MyComparer(),
    ),
    g => g.Key,
    mew MyOtherComparer()
);

O que acham disto?

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 2:02 AM | Feedback (0)
 

O C# 3.0 introduziu inicializadores de object and collection. É agora possível criar objectos e colecções pré-inicializados:

var person = new Person { FirstName = "Paulo", LastName = "Morgado" };

var persons = new List<Person> {
    new Person { FirstName = "Paulo", LastName = "Morgado" },
    new Person { FirstName = "Luís", LastName = "Abreu" }
};

var personDirectory = new Dictionary<string, Person> {
    { "Lisboa", new Person { FirstName = "Paulo", LastName = "Morgado" } },
    { "Funchal", new Person { FirstName = "Luís", LastName = "Abreu" } }
};

Não era bom podermos fazer o mesmo para objectos e colecções já existentes?

Que sintaxe seria usada? Algo deste género?

var person = new Person();
person = { FirstName = "Paulo", LastName = "Morgado" };

var persons = new List<Person>();
persons += {
    new Person { FirstName = "Paulo", LastName = "Morgado" },
    new Person { FirstName = "Luís", LastName = "Abreu" }
};

var personDirectory = new Dictionary<string, Person>();
personDirectory += {
    { "Lisboa", new Person { FirstName = "Paulo", LastName = "Morgado" } },
    { "Funchal", new Person { FirstName = "Luís", LastName = "Abreu" } }
};

O que pensam disto?

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 12:37 AM | Feedback (0)

Friday, August 08, 2008

De acordo com a página inicial das MSDN Subscriptions, devemos esperar que o Service Pack 1 do Visual Studio 2008 esteja disponível após o próximo dia 11 de Agosto de 2008.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 1:29 AM | Feedback (1)

Wednesday, August 06, 2008

Finalmente está aí o SQL Server 2008 e vem com a Entity Framework, o que quer dizer que o SP1 para o Visual Studio 2008 e a .NET Framework também deve estar a saír.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 11:52 PM | Feedback (0)

Monday, August 04, 2008

O ASP.NET disponibiliza três tipos de armazenamento de estado de sessao:

Provider Description
InProc

O estado de sessão é armazenado no cache ASP.NET.

SQLServer

O estado de sessão é armazenado numa base de dados SQL Server.

StateServer

O estado de sessão é armazenado é armazenado num serviço de armazenamento de estado.

Porque com o SQLServer e o StateServer o estado tem de atravessar a fronteira do AppDomain, tem de ser seriado antes de ser armazenado e desseriado quando carregado. Porque o estado tem de ser carregado e armazenado em cada pedido, só está disponível desde o evento PostAcquireRequestState até ao evento ReleaseRequestState. E, devido à seriação e desseriação, todos os objectos armazenados têm de ser seriáveis e qualquer referência mantida para um item do estado não será para o mesmo item após a desseriação do estado.

Por outro lado, com o InProc, o estado nunca será seriado ou desseriado, o que quer dizer que os objectos não necessitam de ser seriáveis e qualquer referência para um item do estado será sempre uma referência para um item do estado mesmo antes do evento PostAcquireRequestState e após o evento ReleaseRequestState.

Na prática, durante o desenvolvimento é usado o InProc e em produção é usado o SQLServer. Isto leva, muitas vezes, a erros aplicacionais que apenas se manifestam em ambiente de produção, com armazenar objectos não seriáveis no estado. Foi por isso que escrevi um provedor de armazenamento de estado em memória que seria e desseria os itens armazenados. Podem obter o código fonte aqui.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 2:29 AM | Feedback (0)
 

(Isto foi-me referido pelo Frans Bouma e explicado pelo Jon Skeet)

Imaginem este conjunto de classes:

public class A
{
    public virtual string P
    {
        get { return "A"; }
    }
}

public class B : A
{
}

public class C : B
{
    public override string P
    {
        get { return "C"; }
    }
}

E esta classe:

public static class Reporter
{
    public static void Report<T>(T target, Expression<Func<T, string>> expression)
    {
        Console.WriteLine("Expression: {0}", expression);
        Console.WriteLine("\tDeclaring Type: {0}", ((expression as LambdaExpression).Body as MemberExpression).Member.DeclaringType);
        Console.WriteLine("\tInvocation Result: {0} for {1}", expression.Compile().Invoke(target), target.GetType());
        Console.WriteLine();
    }
}

A classe acima escreve na consola a expressão Lambda, o tipo que declara a propriedade e o valor da propridedade para target e o tipo de target.

Vejamos o que acontece quando é usado o seguinte código C#:

Reporter.Report(new C(), (A a) => a.P);
Reporter.Report(new C(), (B b) => b.P);
Reporter.Report(new C(), (C c) => c.P);

Reporter.Report(new B(), (A a) => a.P);
Reporter.Report(new B(), (B b) => b.P);

Reporter.Report(new A(), (A a) => a.P);

O resultado será:

Expression: a => a.P
        Declaring Type: A
        Invocation Result: C for C

Expression: b => b.P
        Declaring Type: A
        Invocation Result: C for C

Expression: c => c.P
        Declaring Type: A
        Invocation Result: C for C

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for B

Expression: b => b.P
        Declaring Type: A
        Invocation Result: A for B

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for A

Por outro lado, se for usado o seguinte código Visual Basic:

Reporter.Report(New C(), Function(a As A) a.P)
Reporter.Report(New C(), Function(b As B) b.P)
Reporter.Report(New C(), Function(c As C) c.P)

Reporter.Report(New B(), Function(a As A) a.P)
Reporter.Report(New B(), Function(b As B) b.P)

Reporter.Report(New A(), Function(a As A) a.P)

O resultado será:

Expression: a => a.P
        Declaring Type: A
        Invocation Result: C for C

Expression: b => b.P
        Declaring Type: A
        Invocation Result: C for C

Expression: c => c.P
        Declaring Type: C
        Invocation Result: C for C

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for B

Expression: b => b.P
        Declaring Type: A
        Invocation Result: A for B

Expression: a => a.P
        Declaring Type: A
        Invocation Result: A for A

Porquê as diferenças? Por causa das diferenças nas especificações e compiladores das diferentes inguagens:

  • O compilador de C# gerará uma chamada virtual ao membro virtual na classe em que é declarado como virtual.
  • O compilador de Visual Basic gerará uma chamada virtual ao membro sobreposto na classe em que é implementado.

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 1:35 AM | Feedback (0)

Friday, August 01, 2008

Num dos ambientes em que trabalho não podem ser utilizados cookies porque as páginas correm em controlos web browser hospedados numa aplicação cliente e os cookies acabam por ser partilhados entre todos os browsers.

Felizmente, o ASP.NET permite-nos persistir alguns cookies como parte do URL.

Para persistir o cookie do identificador do estado de sessão no URL basta adicionar a seguinte configuração:

<configuration>
  <system.web>
    <sessionState cookieless="UseUri" />
  </system.web>
</configuration>

e obtemos URLs destes:

http://localhost/Cookieless/(S(jcmwek3ja0lvdpbwoacpjirv))/default.aspx

O modo como o IIS e o ASP.NET fazem isto é através da remoção da secção entre parentesis por parte do IIS e a adição do valor removido como um header HTTP de nome AspFilterSessionId ao pedido. Em seguinda, o ASP.NET extrai o cookie desse header HTTP.

Fiz esta página simples para demonstrar o funcionamente desta funcionalidade:

<%@ Page Language="C#" AutoEventWireup="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <table>
            <tr>
                <td>Raw URL</td>
                <td><%= Request.RawUrl %></td>
            </tr>
            <tr>
                <td>Cookiless Cookies<br />AspFilterSessionId Request HTTP Header</td>
                <td><%= Request.Headers["AspFilterSessionId"] %></td>
            </tr>
            <tr>
                <td>Session ID</td>
                <td><%= Session.SessionID %></td>
            </tr>
        </table>
    </div>
    </form>
</body>
</html>

Para o URL acima, obtemos a seguinte página:

Raw URL /Cookieless/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
S(jcmwek3ja0lvdpbwoacpjirv)
Session ID jcmwek3ja0lvdpbwoacpjirv

O IIS também efectua esta operação para os conteúdos estáticos como folhas de estilos.

Para o testar podemos adicionar um tema. Isto pode ser conseguido adicionando uma pasta Default abaixo da pasta App_Themes e adicionando-lhe o ficheiro Styles.css:

body
{
    background-color: Yellow;
}
table, tr, td
{
    border: thin solid black;
}

e definindo o tema como tema predefinido através da eguinte configuração:

<configuration> <system.web> <sessionState cookieless="UseUri" /> <pages theme="Default"/> </system.web> </configuration>

E, de repenete, a nossa página fica mais “bonita”:

Raw URL /Cookieless/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
S(jcmwek3ja0lvdpbwoacpjirv)
Session ID jcmwek3ja0lvdpbwoacpjirv

Se, por alguma razão, necessitamos de providenciar os nossos próprios identificadores de sessão, podemos implementar o nosso próprio gestor de identificadores de sessão.

Mas, se queremos tirar partido dos cookieless cookies, só há um modo: extender a classe SessionIDManager:

public class SessionIdManager : System.Web.SessionState.SessionIDManager
{
    public override string CreateSessionID(System.Web.HttpContext context)
    {
        string id = System.Guid.NewGuid().ToString("B");

        return id;
    }

    public override bool Validate(string id)
    {
        try
        {
            new System.Guid(id);
            return true;
        }
        catch
        {
            return false;
        }
    }
}

e configura o sistema de estado e sessão para o usar:

<configuration>
  <system.web>
    <sessionState cookieless="UseUri" sessionIDManagerType="SessionIdManager" />
    <pages theme="Default"/>
  </system.web>
</configuration>

E obtemos esta simpática página:

http://localhost/Cookieless/(S(%7b0861e55a-e29b-4b6f-825b-1e1d4c57f095%7d))/default.aspx

Raw URL /Cookieless/(S({0861e55a-e29b-4b6f-825b-1e1d4c57f095}))/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
 
Session ID {0861e55a-e29b-4b6f-825b-1e1d4c57f095}

Eh lá! O que é que se passou aqui?

Parece que o IIS não conseguiu transferir os cookies para o header HTTP apropriado mas ASP.NET conseguiu encontrar o recurso pedido. Por outro lado, o IIS não conseguiu encontrar o ficheiro http://localhost/Cookieless/(S(%7b0861e55a-e29b-4b6f-825b-1e1d4c57f095%7d))App_Themes/Default/Styles.css.

Isto acontece em todos estes ambientes:

Operating System IIS ASP.NET
Windows XP Pro SP3 5.1 2.0 SP1, 3.5
Windows Server 2003 R2 6 2.0 SP1, 3.5
Windows Server 2008 7 2.0 SP1, 3.5

Felizmente, com o IIS 7 podem-se definir módulos HTTP quando em modo integrated pipeline que serão executados para todos os pedidos feitos ao IIS.

O módulo nem precisa de fazer nada. Apenas precisa de existir:

public class Module : System.Web.IHttpModule
{
    public void Dispose()
    {
    }

    public void Init(System.Web.HttpApplication context)
    {
    }
}

e ser adicionado à configuração:

<configuration>
  <system.web>
    <sessionState cookieless="UseUri" sessionIDManagerType="SessionIdManager" />
    <pages theme="Default"/>
  </system.web>
  <system.webServer>
    <modules>
      <add name="Module" preCondition="integratedMode" type="Module" />
    </modules>
  </system.webServer>
</configuration>

E a nossa “linda” página está de volta:

Raw URL /Cookieless/default.aspx
Cookiless Cookies
AspFilterSessionId Request HTTP Header
S({0861e55a-e29b-4b6f-825b-1e1d4c57f095})
Session ID {0861e55a-e29b-4b6f-825b-1e1d4c57f095}

Sou só eu a pensar isto, ou há aqui qualquer coisa errada?

Foi por isso que submeti este erro no Microsoft Connect

[Cross-Posted de http://www.arquitecturadesoftware.org/blogs/paulomorgado/]

posted @ 2:17 AM | Feedback (0)