Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Windows Azure, PHP, ...

About the author

Maarten Balliauw is currently employed as a Technical Evangelist at JetBrains. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Pro NuGet Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
Maarten Balliauw - MVP - Most Valuable Professional
Maarten Balliauw - ASPInsider

Search

Archive

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright Maarten Balliauw 2013


Books I recently read...

A while ago, I was contacted by the people of Packt Publishing asking me to review two of their latest books, ASP.NET Data Presentation Controls Essentials (by Joydip Kanjilal) and LINQ Quickly (by N. Satheesh Kumar). Since both books stated something about LINQ on the back-cover, and me wanting to read more on that matter, I engaged into reviewing them.

ASP.NET Data Presentation Controls Essentials

image Being an ASP.NET developer, I'm not new to ASP.NET's data bound controls. Upon receiving the book, I immediately knew this was not going to be new stuff to me, a thought which proved right. Nevertheless, the book has a value!

The author starts with a birds-eye overview of all data bound controls in ASP.NET, allowing the reader to immediately know what's possible with these controls. In the next chapters, each control is covered with some examples. Luckily, the book did not contain "full" examples yet short, to-the-point code snippets delivering a practical approach to solving a specific data binding scenario.

This leads me to agreeing with the author that "this book is not for beginners". Some snippets contain small typo's, and because a full frame around these snippets is missing, someone new to C# and ASP.NET will have some problems creating their own examples based on the book. It's also not for professionals to learn much new things, but I think anyone familiar with a C# background wanting to start data bound ASP.NET development can benefit from this no-nonsense quickstart book.

For me, this book will find a place on my book shelf along with other reference books, as it covers all data binding scenario's from ASP.NET 1.1 over ASP.NET 2.0 up to some snippets of data binding to LINQ data sources.

LINQ Quickly

image Since the release of the Microsoft .NET framework 3.5 a few months ago, I've been playing around with LINQ (Language Integrated Query) a couple of times. It is a uniform method of accessing any type of data (Collections, XML, database, ...) in a "natural" way.

The book covers all concepts of LINQ. It starts with an overview of all language elements that have been added to the .NET framework in order to enable the use of LINQ, such as anonymous types, object/collection initializers, expressions, partial methods, ... The next chapters all cover a LINQ implementation such as LINQ to Objects, LINQ to SQL, LINQ to Entities, LINQ to XML, LINQ to DataSets, ... The last chapter gives an overview of all LINQ methods and their use with a short code example that immediately clarifies the purpose of each method.

I found the LINQ to Entities chapter quite interesting, as it clearly explains how to create your class diagram using the right decorators for generating a database schema. Another useful thing are the appendices near the end of the book, covering LINQ to "anything" (there's an example on LINQ to Outlook Contacts).

To be honest, I'm quite enthousiast about this book. If you are a .NET developer and looking for a "one-night read" to-the-point book about LINQ and all related matter, this book is your friend!


Categories: ASP.NET | Book review | Books | C# | General | LINQ

ASP.NET Session State Partitioning using State Server Load Balancing

It seems like amount of posts on ASP.NET's Session State keeps growing. Here's the list:

Yesterday's post on Session State Partitioning used a round-robin method for partitioning session state over different state server machines. The solution I presented actually works, but can still lead to performance bottlenecks.

Let's say you have a web farm running multiple applications, all using the same pool of state server machines. When having multiple sessions in each application, the situation where one state server handles much more sessions than another state server could occur. For that reason, ASP.NET supports real load balancing of all session state servers.

Download example

Want an instant example? Download it here: SessionPartitioning2.zip (4.16 kb)
Want to know what's behind all this? Please, continue reading.

What we want to achieve...

Here's a scenario: We have different applications running on a web farm. These applications all share the same pool of session state servers. Whenever a session is started, we want to store it on the least-busy state server.

1. Performance counters

To fetch information on the current amount of sessions a state server is storing, we'll use the performance counters ASP.NET state server provides. Here's a code snippet:

if (PerformanceCounterCategory.CounterExists("State Server Sessions Active", "ASP.NET", "STATESERVER1")) {
    PerformanceCounter pc = new PerformanceCounter("ASP.NET", "State Server Sessions Active", "", "STATESERVER1");
    float currentLoad = pc.NextValue();
}

2. Creating a custom session id

Somehow, ASP.NET will have to know on which server a specific session is stored. To do this, let's say we make the first character of the session id the state server id from the following IList:

IList<StateServer> stateServers = new List<StateServer>();

// Id 0, example session id would be 0ywbtzez3eqxut45ukyzq3qp
stateServers.Add(new StateServer("tcpip=10.0.0.1:42424", "sessionserver1"));

// Id 1, example session id would be 1ywbtzez3eqxut45ukyzq3qp
stateServers.Add(new StateServer("tcpip=10.0.0.2:42424", "sessionserver2"));

Next thing we'll have to do is storing these list id's in the session id. For that, we will implement a custom System.Web.SessionState.SessionIDManager class. This class simply creates a regular session id, locates the least-busy state server instance and assign the session to that machine:

using System;
using System.Diagnostics;


public class SessionIdManager : System.Web.SessionState.SessionIDManager
{
    public override string CreateSessionID(System.Web.HttpContext context)
    {
        // Generate a "regular" session id
        string sessionId = base.CreateSessionID(context);

        // Find the least busy state server
        StateServer leastBusyServer = null;
        float leastBusyValue = 0;
        foreach (StateServer stateServer in StateServers.List)
        {
            // Fetch first state server
            if (leastBusyServer == null) leastBusyServer = stateServer;

            // Fetch server's performance counter
            if (PerformanceCounterCategory.CounterExists("State Server Sessions Active", "ASP.NET", stateServer.ServerName))
            {
                PerformanceCounter pc = new PerformanceCounter("ASP.NET", "State Server Sessions Active", "", stateServer.ServerName);
                if (pc.NextValue() < leastBusyValue || leastBusyValue == 0)
                {
                    leastBusyServer = stateServer;
                    leastBusyValue = pc.NextValue();
                }
            }
        }

        // Modify session id to contain the server's id
        // We will change the first character in the string to be the server's id in the
        // state server list. Notice that this is only for demonstration purposes! (not secure!)
        sessionId = StateServers.List.IndexOf(leastBusyServer).ToString() + sessionId.Substring(1);

        // Return
        return sessionId;
    }
}

The class we created will have to be registered in web.config. Here's how:

<configuration>
  <system.web>
    <!-- ... -->
    <sessionState mode="StateServer"
                partitionResolverType="PartitionResolver"
                sessionIDManagerType="SessionIdManager" />
    <!-- ... -->
  </system.web>
</configuration>

You notice our custom SessionIdManager class is now registered to be the sessionIDManager. The PartitionResolver I blogged about is also present in a modified version.

3. Using the correct state server for a specific session id

In the previous code listing, we assigned a session to a specific server. Now for ASP.NET to read session state from the correct server, we still have to use the PartitionResolver class:

using System;


public class PartitionResolver : System.Web.IPartitionResolver
{

    #region IPartitionResolver Members

    public void Initialize()
    {
        // No need for this!
    }

    public string ResolvePartition(object key)
    {
        // Accept incoming session identifier
        // which looks similar like "2ywbtzez3eqxut45ukyzq3qp"
        string sessionId = key as string;

        // Since we defined the first character in sessionId to contain the
        // state server's list id, strip it off!
        int stateServerId = int.Parse(sessionId.Substring(0, 1));

        // Return the server's connection string
        return StateServers.List[stateServerId].ConnectionString;
    }

    #endregion

}

kick it on DotNetKicks.com 


Categories: ASP.NET | C# | General | Software | Webfarm

ASP.NET Session State Partitioning

After my previous blog post on ASP.NET Session State, someone asked me if I knew anything about ASP.NET Session State Partitioning. Since this is a little known feature of ASP.NET, here's a little background and a short how-to.

When scaling out an ASP.NET application's session state to a dedicated session server (SQL server or the ASP.NET state server), you might encounter a new problem: what if this dedicated session server can't cope with a large amount of sessions? One option might be to create a SQL server cluster for storing session state. A cheaper way is to implement a custom partitioning algorithm which redirects session X to state server A and session Y to state server B. In short, partitioning provides a means to divide session information on multiple session state servers, which all handle "their" part of the total amount of sessions.

Download example 

Want an instant example? Download it here: SessionPartitioning.zip (2.70 kb)
 Want to know what's behind all this? Please, continue reading.

1. Set up ASP.NET session mode

Follow all steps in my previous blog post to set up the ASP.NET state service / SQL state server database and the necessary web.config setup. We'll customise this afterwards.

2.   Create your own session state partitioning class

The "magic" of this el-cheapo solution to multiple session servers will be your own session state partitioning class. Here's an example:

using System;

public class PartitionResolver : System.Web.IPartitionResolver
{

    #region Private members

    private String[] partitions;

    #endregion

    #region IPartitionResolver Members

    public void Initialize()
    {
        // Create an array containing
        // all partition connection strings
        //
        // Note that this could also be an array
        // of SQL server connection strings!
        partitions = new String[] {      
            "tcpip=10.0.0.1:42424",   
            "tcpip=10.0.0.2:42424",       
            "tcpip=10.0.0.3:42424"
        };
    }

    public string ResolvePartition(object key)
    {
        // Accept incoming session identifier
        // which looks similar like "2ywbtzez3eqxut45ukyzq3qp"
        string sessionId = key as string;

        // Create your own manner to divide session id's
        // across available partitions or simply use this one!
        int partitionID = Math.Abs(sessionId.GetHashCode()) % partitions.Length;
        return partitions[partitionID];
    }

    #endregion
}

Basically, you just have to implement the interface System.Web.IPartitionResolver, which is the contract ASP.NET uses to determine the session state server's connection string. The ResolvePartition method is called with the current session id in it, and allows you to return the connection string that should be used for that specific session id.

3. Update your web.config

Most probably, you'll have a web.config which looks like this:


<configuration>
  <system.web>
    <!-- ... -->
    <sessionState
        mode="StateServer"
        stateConnectionString="tcpip=your_server_ip:42424" />
    <!-- ... -->
  </system.web>
</configuration>

In order for ASP.NET to use our custom class, modify web.config into:


<configuration>
  <system.web>
    <!-- ... -->
    <sessionState
        mode="StateServer"
        partitionResolverType="PartitionResolver" />
    <!-- ... -->
  </system.web>
</configuration>

You may have noticed that the stateConnectionString attribute was replaced by a partitionResolverType attribute. From now on, ASP.NET will use the class specified in the partitionResolverType attribute for distributing sessions across state servers.

UPDATE 2008-01-24: Also check out my blog post on Session State Partitioning using load balancing!

kick it on DotNetKicks.com


Categories: ASP.NET | C# | General | Software | Webfarm

Preview Word files (docx) in HTML using ASP.NET, OpenXML and LINQ to XML

Since an image (or even an example) tells more than any text will ever do, here's what I've created in the past few evening hours:

image

Live examples:

Want the source code? Download it here: WordVisualizer.zip (357.01 kb)

Want to know how?

If you want to know how I did this, let me first tell you why I created this. After searching Google for something similar, I found a Sharepoint blogger who did the same using a Sharepoint XSL transformation document called DocX2Html.xsl. Great, but this document can not be distributed without a Sharepoint license. The only option for me was to do something similar myself.

ASP.NET handlers

The main idea of this project was to be able to type in a URL ending in ".docx", which would then render a preview of the underlying Word document. Luckily, ASP.NET provides a system of creating HttpHandlers. A HttpHandler is the class instance which is called by the .NET runtime to process an incoming request for a specific extension. So let's trick ASP.NET into believing ".docx" is an extension which should be handled by a custom class...

Creating a custom handler

A custom handler can be created quite easily. Just create a new class, and make it implement the IHttpHandler interface:

/// <summary>
/// Word document HTTP handler
/// </summary>

public class WordDocumentHandler : IHttpHandler
{
    #region IHttpHandler Members

    /// <summary>
    /// Is the handler reusable?
    /// </summary>

    public bool IsReusable
    {
        get { return true; }
    }

    /// <summary>
    /// Process request
    /// </summary>
    /// <param name="context">Current http context</param>

     public void ProcessRequest(HttpContext context)
    {
        // Todo...

        context.Response.Write("Hello world!");
    }

    #endregion
}

Registering a custom handler

For ASP.NET to recognise our newly created handler, we must register it in Web.config:

image

Now if you are using IIS6, you should also register this extension to be handled by the .NET runtime:

image

In the application configuration, add the extension ".docx" and make it point to the following executable: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll

This should be it. Fire up your browser, browse to your web site and type anything.docx. You should see "Hello world!" appearing in a nice, white page.

OpenXML

As you may already know, Word 2007 files are OpenXML packages containg WordprocessingML markup. A .docx file can be opened using the System.IO.Packaging.Package class (which is available after adding a project reference to WindowsBase.dll).

The Package class is created for accessing any OpenXML package. This includes all Office 2007 file formats, but also custom OpenXML formats which you can implement for yourself. Unfortunately, if you want to use Package to access an Office 2007 file, you'll have to implement a lot of utility functions to get the right parts from the OpenXML container.

Luckily, Microsoft released an OpenXML SDK (CTP), which I also used in order to create this Word preview handler.

LINQ to XML

As you know, the latest .NET 3.5 release brought us something new & extremely handy: LINQ (Language Integrated Query). On Doug's blog, I read about Eric White's attempts to use LINQ to XML on OpenXML.

LINQ to OpenXML

For implementing my handler, I basically used similar code to Eric's to run query's on a Word document's contents. Here's an example which fetches all paragraphs in a Word document:

using (WordprocessingDocument document = WordprocessingDocument.Open("test.docx", false))
{
    // Register namespace

    XNamespace w = "//schemas.openxmlformats.org/wordprocessingml/2006/main";">http://schemas.openxmlformats.org/wordprocessingml/2006/main";

    // Element shortcuts

    XName w_r = w + "r";
    XName w_ins = w + "ins";
    XName w_hyperlink = w + "hyperlink";

    // Load document's MainDocumentPart (document.xml) in XDocument

    XDocument xDoc = XDocument.Load(
        XmlReader.Create(
            new StreamReader(document.MainDocumentPart.GetStream())
        )
    );

    // Fetch paragraphs

    var paragraphs = from l_paragraph in xDoc
                    .Root
                    .Element(w + "body")
                    .Descendants(w + "p")
         select new
         {
             TextRuns = l_paragraph.Elements().Where(z => z.Name == w_r || z.Name == w_ins || z.Name == w_hyperlink)
         };

    // Write paragraphs

    foreach (var paragraph in paragraphs)
    {
        // Fetch runs

        var runs = from l_run in paragraph.Runs
                   select new
                   {
                       Text = l_run.Descendants(w + "t").StringConcatenate(element => (string)element)
                   };

        // Write runs

        foreach (var run in runs)
        {
            // Use run.Text to fetch a text string

            Console.Write(run.Text);
        }
    }
}

Now if you run this code, you will notice a compilation error... This is due to the fact that I used an extension method StringConcatenate.

Extension methods

In the above example, I used an extension method named StringConcatenate. An extension method is, as the name implies, an "extension" to a known class. In the following example, find the extension for all IEnumerable<T> instances:

public static class IEnumerableExtensions
{
    /// <summary>
    /// Concatenate strings
    /// </summary>
    /// <typeparam name="T">Type</typeparam>
    /// <param name="source">Source</param>
    /// <param name="func">Function delegate</param>
    /// <returns>Concatenated string</returns>

    public static string StringConcatenate<T>(this IEnumerable<T> source, Func<T, string> func)
    {
        StringBuilder sb = new StringBuilder();
        foreach (T item in source)
            sb.Append(func(item));
        return sb.ToString();
    }
}

Lambda expressions

Another thing you may have noticed in my example code, is a lambda expression:

z => z.Name == w_r || z.Name == w_ins || z.Name == w_hyperlink.

A lambda expression is actually an anonymous method, which is called by the StringConcatenate extension method. Lambda expressions always accept a parameter, and return true/false. In this case, z is instantiated as an XNode, returning true/false depending on its Name property.

Wrapping things up...

If you read this whole blog post, you may have noticed that I extensively used C# 3.5's new language features. I combined these with OpenXML and ASP.NET to create a useful Word document preview handler. If you want the full source code, download it here: WordVisualizer.zip (357.01 kb).

kick it on DotNetKicks.com


Categories: ASP.NET | C# | General | LINQ | OpenXML | Software

ASP.NET MVC framework - Security

Some posts ago, I started playing with the ASP.NET MVC framework. In an example I'm creating, I'm trying to add Forms-based security.

"Classic" ASP.NET offers a nice and easy way to set security on different pages in a web application, trough Web.config. In the example I'm building, I wanted to allow access to "/Entry/Delete/" only to users with the role "Administrator". So I gave the following snip a try:

<location path="/Entry/Delete">
   <system.web>
     <authorization>
       <allow roles="Administrators"/>
       <deny users="*"/>
     </authorization>
   </system.web>
</location>

This seems to work in some occasions, but not always. Second, I think it is very confusing to define security in a different place than my route table... Since the ASP.NET MVC framework is built around "dynamically" changing URL schemes, I'm not planning to maintain my Web.config security for each change...

In an ideal world, you would specify permissions for a route at the same location as you specify the route. Since the ASP.NET MVC framework is still an early CTP, perhaps this might be added in future versions. For now, the follwing strategies can be used.

Code Access Security

Luckily, the .NET framework offers a nice feature under the name "CAS" (Code Access Security). Sounds scary? Perhaps, but it's useful in the MVC security context!

The idea behind CAS is that you specify security requirements using attributes. For example, if authentication is required in my EntryController (serving /Entry/...), I could use the following code snippet:

[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
public class EntryController : Controller {
    // ...
}

Now let's try my example from the beginning of this post. The URL "/Entry/Delete" is routed to my EntryController's Delete method. So why not decorate that method with a CAS attribute?

[ControllerAction]
[PrincipalPermission(SecurityAction.Demand, Role="Administrator"]
public void Delete(int? id) {
   ...
}

This snippet makes sure the Delete method can only be called by users in the role "Administrator"

Exception handling

Problem using the CAS approach is that you are presented an ugly error when a security requirement is not met. There are two possible alternatives for catching these Exceptions.

Alternative 1: Using Global.asax

In Global.asax, you can specify an Application_Error event handler. Within this event handler, you can catch specific types of Exceptions and route them to the right error page. The following example redirects each SecurityException to the /Login, my LoginController:

protected void Application_Error(object sender, EventArgs e) {
    Exception ex = Server.GetLastError().GetBaseException();
    if (ex is SecurityException) {
        Response.Redirect("/Login");
    }
}

Alternative 2: Use more attributes!

Fredrik Normén has posted an ExceptionHandler attribute on his blog, which allows you to specify which type of Exception should be handled by which type of view. Hope this makes it into a future ASP.NET MVC framework version too!

Alternative 3: Use in-line CAS

Another option is to use in-line CAS. For example, you can do the folluwing in your ControllerAction:

try {
    PrincipalPermission permission = new PrincipalPermission(User.Identity.Name, "Administrators", true);
    permission.Demand();
} catch (SecurityException secEx) {
    // Handle the Exception here...
    // Redirect to Login page, for example.
}


Categories: ASP.NET | C# | General | MVC

ASP.NET DataPager not paging after first PostBack?

A few posts ago, I mentioned that I am currently giving a classroom training on ASP.NET. People attending are currently working on a project I gave them, and today one of them came up to me with a strange problem...

Here's the situation: in VS 2008, a web page was created containing 2 controls: a DataList and a DataPager. This DataPager serves as the paging control for the DataList. Databinding is done in the codebehind:

protected void Page_Load(object sender, EventArgs e) {
    ListView1.DataSource = NorthwindDataSource;
    ListView1.DataBind();
}

This works perfectly! When the page is rendered in a brwoser window, data is shown in the DataList control. Now, when testing the DataPager, something strange happens: when a page number is clicked, ASP.NET will process a PostBack, rendering... the same page as before! Clicking the DataPager again is the only way to really go to a different page in the result set.

Let's have a look at the ASP.NET page lifecycle... The page Load event is actually not the best place to call the DataBind() method. PreRender is a better place to call DataBind():

protected void Page_Load(object sender, EventArgs e) {
    ListView1.DataSource = NorthwindDataSource;
}

protected void Page_Render(object sender, EventArgs e) {
    ListView1.DataBind();
}

kick it on DotNetKicks.com


Categories: ASP.NET | C# | General | Software

ASP.NET MVC Framework - Basic sample application

ASP.NET MVC FrameworkYou might have noticed that I'm quite enhousiast about the new ASP.NET MVC framework.

What are you talking about?

Basically, this new ASP.NET MVC framework is an alternative to standard ASP.NET webforms, with some advantages:

  • No more postbacks or viewstate, no more page lifecycle trouble: all communication is done using a REST pattern
  • Separation of concerns: no more pages containing cluttered business logic inside view logic (MVC)
  • Testable model and controller: you can now create uinit tests which communicate with your model as if a user is browsing your website

Is there a tutorial available?

For more information and a step-by-step tutorial, check Scott Guthrie's blog:

My own sample project

For an article I'm working on, I am writing a sample application using this framework. This sample application is a very basic photo album website, listing some albums and photo's. Anyone who's interested in a sample MVC application (no data entry yet!) can download it.

Current shortcomings...

There are some shortcomings in the current CTP... Current databound controls can not be used easily. There are some ways around, but using a simple <% foreach ... %> is currently the easiest way to display data on your web page. Another way around is the MVCToolkit project, which adds support for some helper methods and classes.


ASP.NET 3.5 Extensions CTP preview released

Just over the weekend, Microsoft has released the ASP.NET 3.5 Extensions CTP. This download includes several additions to ASP.NET 3.5:

  • ASP.NET AJAX Improvements contains some new AJAX features like browser history support (back-forward), improvements to the JavaScript library, ...
  • The new ASP.NET MVC framework which I blogged about last week
  • ASP.NET Dynamic Data Support contains some new features for building a data-driven application much faster.
  • ASP.NET Silverlight support
  • ADO.NET data services, also known under the name "Astoria".

I'll be doing some testing during the week, and keep you all informed.


Categories: ASP.NET | C# | General | Software

LINQ to filesystem

The past few hours, I've been experimenting with LINQ. As a sample application, I'm trying to create a small photo album website, which shows me all images in a specific folder on my webserver.

What does LINQ have to do with that? Everyone has used a loop over all files in a folder, and I decided to try LINQ for that matter. Here's how:

var rootFolder = "C:\\";
var selectedImages = from file in Directory.GetFiles(rootFolder, "*.jpg")
                             select new { Path = file,
                                          Name = new FileInfo(file).Name,
                                          CreationDate = new FileInfo(file).CreationTime,
                                          DirectoryName = new FileInfo(file).DirectoryName
                                    };

There you go! A collection named "selectedImages", filled with anonymous class instances containg a file Path, Name, CreationDate and DirectoryName. This collection can now be bound to, for example, a GridView:

this.gridView1.DataSource = selectedImages;
this.gridView1.DataBind();

EDIT: (mental note to myself: add LINQ keywords to syntax highlighter...) - done!


Categories: C# | General | LINQ | Software

ASP.NET MVC framework preview to be released next week

Half the world has been focussing on the release of the new Visual Studio 2008 and .NET 3.5 last week. That is good, as .NET 3.5 offers lots of nice new features and improvements. In the blogosphere, I haven't read much about an extension I've been waiting for anxiously: the new ASP.NET MVC framework.

Luckily, Scott Guthrie posted some examples on it, and I can't wait for a preview to be released next week. I'll keep you informed!


Categories: ASP.NET | C# | General | Software