# Wednesday, November 12, 2008

image 

The user group met today at netzkern, a company in Wuppertal specialized in .net development and SiteCore - thanks the venue and drinks! Thanks to Matthias for the pic!

This time we had "Sliverlight 2 in the real world" as a topic presented by Florian Kruesch. He presented new visual features as well as use cases and projects he's working on. Because he didn't touch the non-visual stuff like Isolated Storage he invited me to show something that I've build with the bits:

The "Silverlight Cache" for javascript - most commonly used to cache json returned by web services.

image

A lovely way to reduce traffic :-)

Wednesday, November 12, 2008 10:23:58 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, October 27, 2008

image

The first day of PDC is almost gone. I met my former Boss Clemens Vasters had a nice conversation during lunch with John Lam and "a guy with a blue shirt" that I'm not allow to cite here :-).

image

Micheal Willers, Ron Jacobs and I talked about SOA, Dublin, OSLO and the sometimes hard job trying to explain people the problems they will have in the feature (commonly known as archtecture :-P).

image

I was a bit disappointed by the "ASP.NET 4.0 roadmap" because I expected more "visions" and ideas -  Phil Haack showed mostly stuff that is available today (actually really today on codeplex...).

Monday, October 27, 2008 11:22:20 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Monday, October 20, 2008

In reply to Scott Hanselmann's post on freeing up disc space I'd like to share a batch that I've written some time ago to clear different temp directories for instance before I run a backup. the referenced file "cleanup.txt" just contains the text "yes" (w/o quotes) to automate the cacls command.

 

@Echo off
for /f "tokens=3 delims=\" %%i in ("%USERPROFILE%") do (set user=%%i) 2>&1

@Echo on

del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\WebsiteCache\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Windows\Burn\Burn\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Microsoft SQL Server Data\SQLEXPRESS\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Media Player\Transcoded Files Cache\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Temp\*.*"
rmdir "C:\Users\%user%\AppData\Local\Temp" /S /Q
mkdir "C:\Users\%user%\AppData\Local\Temp"

del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Team Foundation\1.0\Cache\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Windows\Temporary Internet Files\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.Outlook\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Windows\Temporary Internet Files\WebTempDir\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Windows\WER\ReportArchive\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Windows\WER\ReportQueue\*.*"
del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Microsoft SQL Server Data\SQLEXPRESS\*.*"

del /F /S /Q "C:\Users\%user%\AppData\Local\Microsoft\Media Player\Transcoded Files Cache\*.*"
rmdir "C:\Users\%user%\AppData\Local\Microsoft\Media Player\Transcoded Files Cache" /S /Q

del /F /S /Q "C:\Users\%user%\AppData\Roaming\Microsoft\Web Server Extensions\Cache\*.*"

rmdir  "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files" /S /Q
mkdir "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files"
cacls "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files" /g "System":F < "D:\Tools\cleanup.txt"
cacls "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files" /e /g "Administrators":F < "D:\Tools\cleanup.txt"
cacls "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files" /e /g "Network Service":F < "D:\Tools\cleanup.txt"
cacls "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files" /e /g "IISWPG":F < "D:\Tools\cleanup.txt"

del /F /S /Q "C:\Windows\Temp\*.*"
rmdir  "C:\Windows\Temp" /S /Q
mkdir "C:\Windows\Temp"
cacls "C:\Windows\Temp" /g "System":F < "D:\Tools\cleanup.txt"
cacls "C:\Windows\Temp" /e /g "Users":F < "D:\Tools\cleanup.txt"
cacls "C:\Windows\Temp" /e /g "Administrators":F < "D:\Tools\cleanup.txt"
cacls "C:\Windows\Temp" /e /g "Network Service":F < "D:\Tools\cleanup.txt"

del /F /S /Q "C:\Windows\Downloaded Program Files\*.*"

rmdir  "C:\MSOCache" /S /Q
rmdir "C:\SWSetup" /S /Q

pause

Life | Misc
Monday, October 20, 2008 2:33:20 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, October 18, 2008

What is life without security. In the last posts I told you how to do URLRewriting with the ASP.NET 3.5 RoutingEngine and how to pass query strings to the destination Web Form. In this post I'll add some authorization code to let ASP.NET Authentication mechanisms play well.

The first step is to figure out which authentication mechanism has taken place in the local configuration file. For the case of forms based authentication it would be nice to redirect to the configured login Web Form, for all other authentication mechanisms we can only throw a security exception and set a HTTP status code.

I only wanted this operation to be executed once and therefore I implemented as static and thread safe property with a backing field and a lock object:

private static string s_authenticationType;
private static object s_authenticationTypeLock = new object();
private static string AuthenticationType
{
    get
    {
        if (string.IsNullOrEmpty(s_authenticationType))
        {
            lock (s_authenticationTypeLock)
            {
                if (string.IsNullOrEmpty(s_authenticationType))
                {
                    var authenticationSectionObject =
                        WebConfigurationManager.GetSection(
                        "system.web/authentication");

                    var authenticationSection =
                        authenticationSectionObject
                            as AuthenticationSection;

                    if (authenticationSection != null)
                    {
                        s_authenticationType =
                            authenticationSection.Mode.ToString();
                    }
                }
            }
        }
        return s_authenticationType;
    }
}

 

Now its time to check the authorization on the target Web Form:

if (httpContext != null &&
    !UrlAuthorizationModule.CheckUrlAccessForPrincipal(
        VirtualPath,
        httpContext.User,
        httpContext.Request.HttpMethod))
{
    if (AuthenticationType.
        Equals("forms", StringComparison.OrdinalIgnoreCase))
    {
        VirtualPath = FormsAuthentication.LoginUrl;
        queryString =
            new StringBuilder(
                string.Concat(
                    "?ReturnUrl=",
                    requestContext.HttpContext.Server.UrlEncode(
                        requestContext.HttpContext.Request.RawUrl
                        )));
    }
    else
    {
        throw (new SecurityException());
    }
}

Next I will add a login Web Form to the site and drop a LoginControl to the form:

image

And add some code behind:

using System;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class login : Page
{
    protected void OnLoggingIn(object sender, LoginCancelEventArgs e)
    {
        //TODO: add some auth logic or use membership...
        FormsAuthentication.RedirectFromLoginPage(
            "lennybacon", 
            false);
    }
}

Authorization requires an authorization and therefore I enable ASP.NET forms based authentication that also is compatible to ASP.NET Membership in the configuration file:

<configuration>
  <system.web>
    <authentication mode="Forms"/>
...

 

I can configure the authorization settings for the destination Web Forms are also in the web.config file by adding location sections:

<configuration>
  ...
  <location path="Default2.aspx">
    <system.web>
      <authorization>
        <deny users="?"/>
      </authorization>
    </system.web>
  </location>
...

 

Running the web site and clicking the link to the route (/other) that targets the Default2.aspx results in showing up the login.aspx.

image

Notice that the address bar has not changed - the usual roundtrip for redirecting to the loginURL is also "rewritten" inside of ASP.NET.

 

This way the security is easily plugged into the RoutingHandler class - Cool stuff! 

Article | ASP.NET | C#
Saturday, October 18, 2008 7:56:33 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [1]  | 
# Thursday, October 16, 2008

In the last post I showed how to use the ASP.NET 3.5 Routing Engine for URLRewriting purposes. I want to go further in this post by adding the ability to add variables into a route path and forward and append query string variables to the destination Web Form request.

A route can contain one or more variables expressed by its {name}.

 
RouteTable.Routes.Add( 
    new Route(
        "articles/{id}", 
        new devcoach.Web.RoutingPageHandler()));

 

Inside of the RoutingHandler we can iterate through the variables by accessing them by the RouteData property on the parameter passing the RequestContext:

 

var queryString = new StringBuilder("?");
foreach (var aux in requestContext.RouteData.Values)
{
    queryString.Append(
        requestContext.HttpContext.Server.UrlEncode(aux.Key));
    queryString.Append("=");
    queryString.Append(
        requestContext.HttpContext.Server.UrlEncode(
            aux.Value.ToString()));
    queryString.Append("&");
}
queryString.Remove(queryString.Length - 1, 1);

 

The problem now is that the method CreateInstanceFromVirtualPath of the BuildManager class does not allow us to pass for instance a query string as a parameter (I had this discussion recently with Holger at the speakers party of the Basta! confrence):

 

var handler = 
    (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(
        VirtualPath,
        typeof(Page));

 

Passing URL Parameters (a query string) to the instance of the page created from its virtual path we can use the good old RewitePath method (which should be familiar for everyone who has rewritten URLs with ASP.NET 2.0):

 

HttpContext.Current.RewritePath(
    string.Concat(
        VirtualPath,
        queryString));

var handler =
    (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(
        VirtualPath,
        typeof(Page));

 

It feels a bit strange to use the old fashioned way of rewriting URLs just to pass a query string, but the routing handler will stay in control of the request and only the context  variables gets modified.

 Listening to: Elbow - Grounds for Divorce

Article | ASP.NET | C#
Thursday, October 16, 2008 4:26:29 PM (W. Europe Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |