It’s not the first time I try but, for one reason or another, this is the first time I will go to the PDC (Microsoft’s Professional Developers Conference).

According to the site “The PDC is designed for leading-edge developers and software architects. If you’re interested in the future of the Microsoft platform, you’re responsible for the technical strategy in your organization, or you’re a highly skilled developer who likes to delve deep into the heart of the platform, then the PDC is for you!”. If you fit this description, hurry up and register. Early bird discount has been extended until September 8th.

What I like most of these events is networking with Microsoft staff and other attendees. So, if you want to meet me, I’ll be glad to meet you.

Posted by Paulo Morgado | with no comments

Clone Detective for Visual Studio

Clone Detective is a tool that integrates with Visual Studio and uses the ConQAT (Continuous Quality Assessment Toolkit) to analyze C# projects and search for duplicated source code.

Watch the videos and see if this is the tool you were looking for.

Microsoft Press has created an exclusive discount URL for the E-Reference Library that MVPs can pass along to the broader community without any limitations or restrictions.

To create a trial subscription, community referrals should use the Trial URL (http://microsofteref2.books24x7.com/promo.asp?ref=mvptry).

Any community referrals who subscribe to E-Reference Libraries through the Subscription URL (http://microsofteref2.books24x7.com/promo.asp?ref=mvpbuy) will receive a 40% discount on a one-year subscription.

This discount offer ends on September 30, 2008.

Posted by Paulo Morgado | with no comments
Filed under: , ,

The StyleCop team announced the release of a version 4.3 of the StyleCop tool. You can get it from here.

On this version there are some bug fixes, new rules and documentation.

Also in this version, the list of errors and warnings goes to the Errors List window like with the compilers. I whish that the errors and warnings would also be sent to the Output window.

SDK documentation on how to author custom rules and integrate the tool with custom build environments is expected soon.

Let’s face it, if you don’t know .NET Reflector, you can never claim to be a .NET developer.

Today Red Gate announced the acquisition of Lutz Roeder’s .NET Reflector.

On .NET Reflector’s page, Red Gate states that “will continue to maintain a free version for the benefit of the community”.

You can read an interview with Lutz Roeder and James Moore (general manager of .NET Developer Tools at Red Gate) at simple-talk.

James doesn’t know yet how to improve Reflector, but I do. Reflector needs a major improvement on UI usability and performance. Let’s see if I can come up with a list:

  • For me, search as you type is not a good idea as it is in Reflector.
  • Still in the search theme, search as you type would be nice for the active code window.
  • I cannot understand why changing any of the options fires a total repaint and lost of the view of the active code item.
  • Settings like code, documentation and number formatting should possible to change on the fly with a simple toolbar click.

I’m sure Red Gate is more than capable of taking good care of .NET Reflector.

Posted by Paulo Morgado | with no comments

Typemock has released an alpha version of its newest product: Typemock Racer.

Typemock Racer is the tool that uses dynamic and static analysis to find deadlocks in .NET code that had been previously announced by Roy Osherove.

Posted by Paulo Morgado | with no comments
Filed under: , , , ,

Typemock has released version 5.0 of its unit testing tool: Isolator. Check out the release notes.

This new version comes with a new API: Arrange Act Assert:

I’ll have to say that I liked Isolator better over Isolate.

Also new in this version is the inclusion of the help file in the installation package.

While installing SQL Server 2008 in a Virtual PC virtual machine I run out of disk space.

Looking around, I found this great tool: VHD Resizer. Registration is required to download the tool.

Posted by Paulo Morgado | with no comments
Filed under: , ,

Microsoft .NET Framework 3.5 Service Pack 1

Microsoft Visual Studio 2008 Service Pack 1 (iso)

Visual Studio 2008 Team Foundation Server Service Pack 1

In the past I presented another possible use for the using keyword: as hints on LINQ.

I’ve been giving some thought about this lately and refined my proposal.

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;

The above query would be converted to:

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

What do you think of this?

Posted by Paulo Morgado | 2 comment(s)
Filed under: , , , , ,

C# 3.0 introduced object and collection initializers. It is now easier to initialize objects or collections:

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" } }
};

Wouldn't be nice to be able to do the same on already created objects and collections?

But, what would the syntax used be? Something like this?

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" } }
};

What do you think of this?

Posted by Paulo Morgado | 3 comment(s)
Filed under: , , , ,

According to the MSDN Subscriptions home page, we should expect Visual Studio 2008 Service Pack 1 availability after August 11, 2008.

SQL Server 2008 is finally out and comes with the Entity Framework, which means that SP1 for Visual Studio 2008 and the .NET Framework is almost out.

 

ASP.NET provides out of the box three session state stores:

Provider Description
InProc

Session state is stored in the ASP.NET cache.

SQLServer

Session state is stored out-of-process in an SQL Server database.

StateServer

Session state is stored out-of-process in an ASP.NET state service.

Because with SQLServer and StateServer providers the state must cross the AppDomain boundary it needs to be serialized when stored and deserialized when loaded. Because the state needs to be loaded and stored on each request, it is only available from the PostAcquireRequestState to the ReleaseRequestState events. And, because of serialization and deserialization, all objects stored must be serializable any reference held to one of the session state items won’t be to the same item after being deserialized.

On the other hand, with the InProc provider, the state will never be serialized or deserialized, which means that objects don’t need to be serializable and any reference to an item in the state is always a reference to the item in the state even before the PostAcquireRequestState event and after the ReleaseRequestState event.

In practice, developers use the InProc provider and applications are deployed to production using the SQLServer provider. This usually leads to application errors, like storing non serializable objects in the state, that are only uncovered in production. That’s why I’ve written a serializable in-process session state store. You can find the sources here.

(This was pointed out to me by Frans Bouma and explained by Jon Skeet)

Imagine you have this set of 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"; }
    }
}

And this class:

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();
    }
}

The above class writes to the console the lambda expression, the declaring type of the property and the value of the property for the target and the target’s type.

Now, let’s look at what happens when used from this C# code:

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);

The output will be:

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

On the other hand, if used from the equivalent Visual Basic code:

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)

The output will be:

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

Why the differences? It’s because of each language’s specification and compiler:

  • The C# compiler will issue a virtual call to the virtual member in the class where it’s declared as virtual.
  • The Visual Basic compiler will issue a virtual call to the overriding member on the class that overrides it.
Posted by Paulo Morgado | with no comments

In one of the environments I work, cookies cannot be used because the pages run inside web browser controls running on a client application and cookies end up being shared by all browsers.

Fortunately, ASP.NET allows us to persist some cookies as part of the URL.

To persist the session state identifier cookie in the URL we just need to add the following configuration:

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

and you’ll get URLs like this:

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

The way IIS and ASP.NET do this is by IIS removing the section between parenthesis after the virtual directory path and adding the AspFilterSessionId HTTP header to the request. Than, ASP.NET picks it up and extracts the cookie.

I wrote this simple page to demonstrate this working:

<%@ 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>

For the above URL, we'll get a page like this:

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

IIS strips these cookies even for serving static content like cascading stylesheets.

You can test this by creating a default theme. You can do this by adding a Default folder under the App_Themes folder and adding a Styles.css file to it:

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

and setting the theme as default using the following configuration:

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

And you'll get a "pretier" page:

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

If you have special needs for your session state identifiers, you can implement your own session identifier manager.

But if you want to use cookieless cookies, you only have one way to do it: extend the SessionIDManager class:

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;
        }
    }
}

and configure the session state module to use it:

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

And we'll end up with this nice page:

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}

OOPS! What happened here?

Looks like IIS was unable to transfer the cookies to the appropriate HTTP header but ASP.NET was able to find the requested resource. On the other hand, IIS couldn’t find the http://localhost/Cookieless/(S(%7b0861e55a-e29b-4b6f-825b-1e1d4c57f095%7d))App_Themes/Default/Styles.css.

This happens in these environments:

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

Fortunately, in IIS 7 you can have HTTP modules in integrated pipeline mode that are called for every resource requested to IIS.

Your module doesn’t even need to do nothing. It just needs to exist:

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

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

and be added to the configuration:

<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>

And our “pretty” page is back:

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

Is it just me, or there’s something definitely wrong here?

That’s why I opened this bug on Microsoft Connect

Posted by Paulo Morgado | with no comments

On my last post I wrote about a solution for the problem that arises when we try the use path infos and ASP.NET Themes and Skins together.

Raj Kaimal suggested rewriting all LINK HTML elements URLs to the correct URL as seen from the client. Something like this:

void HttpApplicationPreRequestHandlerExecute(object sender, System.EventArgs e)
{
    var httpApplication = sender as System.Web.HttpApplication;

    var httpContext = httpApplication.Context;

    var page = httpContext.CurrentHandler as System.Web.UI.Page;

    if ((page != null) && !string.IsNullOrEmpty(httpContext.Request.PathInfo))
    {
        page.PreRenderComplete += delegate(object source, System.EventArgs args)
        {
            var p = source as System.Web.UI.Page;

            foreach (System.Web.UI.Control headerControl in p.Header.Controls)
            {
                var link = headerControl as System.Web.UI.HtmlControls.HtmlLink;
                if (link != null)
                {
                    link.Href = p.ResolveUrl(link.Href);
                }
            }
        };
    }
}

With this approach you still have a problem (which mine didn’t solve) with post backs because the rendering of the ACTION of the HTML FORM is also broken.

Israel Aéce suggested the use of the BASE HTML element to re-base relative URLs. Something like this:

void HttpApplicationPreRequestHandlerExecute(object sender, System.EventArgs e)
{
    var httpApplication = sender as System.Web.HttpApplication;

    var httpContext = httpApplication.Context;

    var page = httpContext.CurrentHandler as System.Web.UI.Page;

    if ((page != null) && !string.IsNullOrEmpty(httpContext.Request.PathInfo))
    {
        page.PreRenderComplete += delegate(object source, System.EventArgs args)
        {
            page.Init += delegate(object source, System.EventArgs args)
            {
                var p = source as System.Web.UI.Page;

                var htmlBase = new System.Web.UI.WebControls.WebControl(System.Web.UI.HtmlTextWriterTag.Base);
                htmlBase.Attributes.Add("href", p.Request.Url.GetLeftPart(System.UriPartial.Authority) + p.Request.CurrentExecutionFilePath);
                p.Header.Controls.Add(htmlBase);
            };
        };
    }
}

This seems like the better solution except if your site sits behind several security perimeters and it is not possible to be sure what the domain is as seem from the client side, which was my problem to begin with.

But if you are thinking of calling Server.Execute, Server.TransferRequest or Server.TransferRequest, neither of these two solutions will work.

Posted by Paulo Morgado | with no comments

Updated on 2008.07.28 – The code was done in a hurry and, talking to my friend Luís, I noticed that I had forgotten to make a case insensitive comparison and that the code was not so obvious. So, I updated the code and added an explanation.

On my last post I wrote about the problem that arises when we try the use path infos and ASP.NET Themes and Skins together.

But most of the times you don’t care about the why you can’t. You just want to know how you can.

The way I see it, the right solution would be to render the URLs for the stylesheets rooted.

But since I can’t do that, the next best thing is the serve the wrongly addressed request properly.

But how can we do that?

The only way I could come up with, was an HTTP Module:

public class AppThemesModule : global::System.Web.IHttpModule
{
    private const string LocalThemesFolderName = "/App_Themes/";
    private static readonly int searchStartIndex;
    private static readonly int minimumLenghtForSearch;

    static AppThemesModule()
    {
        int searchStartIndex = System.Web.HttpRuntime.AppDomainAppVirtualPath.Length;

        AppThemesModule.searchStartIndex = ((searchStartIndex == 1) ? 0 : searchStartIndex) + 2;

        AppThemesModule.minimumLenghtForSearch = AppThemesModule.searchStartIndex + AppThemesModule.LocalThemesFolderName.Length;
    }

    #region IHttpModule Members

    public void Dispose()
    {
    }

    public void Init(System.Web.HttpApplication context)
    {
        context.BeginRequest += HttpApplicationBeginRequest;
    }

    #endregion

    void HttpApplicationBeginRequest(object sender, System.EventArgs e)
    {
        System.Web.HttpApplication httpApplication = sender as System.Web.HttpApplication;

        string path = httpApplication.Request.Path;
        if (path.Length > searchStartIndex)
        {
            int appThemesStartIndex = path.IndexOf(AppThemesModule.LocalThemesFolderName, searchStartIndex, System.StringComparison.OrdinalIgnoreCase);
            if (appThemesStartIndex > 0)
            {
                httpApplication.Context.RewritePath("~" + path.Substring(appThemesStartIndex));
            }
        }
    }
}

The code starts by initializing the static read-only field searchStartIndex with the start index of the search for the /App_Themes/ pattern. If the length of the application’s virtual path is 1, that means that it’s the root of the site and search start index is 0 instead of 1; otherwise the search start index will be the length of the application’s virtual path. 2 is added because there is no need to start searching the path just after the application’s virtual path (if the pattern was found just after the application’s virtual path, no replacement would be needed).

Than, the static read-only field minimumLenghtForSearch is initialized with the minimum length of the path to search for the pattern. There is no need to search for the pattern on paths shorter than the search start index plus the length of the pattern because, if found, no replacement would be needed.

Besides registering the module, you’ll have to configure your virtual directory so that all the files to be served out of the themes are handled by a StaticFileHandler.

Posted by Paulo Morgado | 3 comment(s)
Filed under: , , , , ,