Using LINQ with Microsoft.Web.Administration
With the upcoming release of .NET 3.5 and LINQ I thought it would be interesting to show some of the cool things you can do with IIS 7 and LINQ. Everything that I will do can be done with C# 2.0 code but it would take me several lines of code to write them but thanks to LINQ you can do them in about a line or two.
Let's start with a very basic example that does not use LINQ but just M.W.A (Microsoft.Web.Administration) and then start adding interesting things to it.
The following code just iterates the sites in IIS and displays their name.
using System;
using System.Linq;
using Microsoft.Web.Administration;
class Program {
static void Main(string[] args) {
using (ServerManager serverManager = new ServerManager()) {
var sites = serverManager.Sites;
foreach (Site site in sites) {
Console.WriteLine(site.Name);
}
}
}
}
Now, let's say I wanted to have them sorted by their name. This is where LINQ starts being useful using System.Linq;
using Microsoft.Web.Administration;
class Program {
static void Main(string[] args) {
using (ServerManager serverManager = new ServerManager()) {
var sites = serverManager.Sites;
foreach (Site site in sites) {
Console.WriteLine(site.Name);
}
}
}
}
using (ServerManager serverManager = new ServerManager()) {
var sites = (from site in serverManager.Sites
orderby site.Name
select site);
foreach (Site site in sites) {
Console.WriteLine(site.Name);
}
}
Say you want to start all the sites that are stopped: var sites = (from site in serverManager.Sites
orderby site.Name
select site);
foreach (Site site in sites) {
Console.WriteLine(site.Name);
}
}
using (ServerManager serverManager = new ServerManager()) {
var sites = (from site in serverManager.Sites
where site.State == ObjectState.Stopped
orderby site.Name
select site);
foreach (Site site in sites) {
site.Start();
}
}
OK, now let's imagine I want to find all the applications that are configured to run in the Default ApplicationPool and move them to run in my NewAppPool. This would take me a lot more lines of code but now I can just do: var sites = (from site in serverManager.Sites
where site.State == ObjectState.Stopped
orderby site.Name
select site);
foreach (Site site in sites) {
site.Start();
}
}
using (ServerManager serverManager = new ServerManager()) {
var apps = (from site in serverManager.Sites
from app in site.Applications
where app.ApplicationPoolName.Equals("DefaultAppPool", StringComparison.OrdinalIgnoreCase)
select app);
foreach (Application app in apps) {
app.ApplicationPoolName = "NewAppPool";
}
serverManager.CommitChanges();
}
Now let's say I want to find the top 20 distinct URL's of all the requests running in all my worker processes that has taken more than 1 second. var apps = (from site in serverManager.Sites
from app in site.Applications
where app.ApplicationPoolName.Equals("DefaultAppPool", StringComparison.OrdinalIgnoreCase)
select app);
foreach (Application app in apps) {
app.ApplicationPoolName = "NewAppPool";
}
serverManager.CommitChanges();
}
using (ServerManager serverManager = new ServerManager()) {
var requests = (
from wp in serverManager.WorkerProcesses
from request in wp.GetRequests(1000)
orderby request.TimeElapsed descending
select request).Distinct().Take(20);
foreach (Request request in requests) {
Console.WriteLine(request.Url);
}
}
OK, finally let's say I want to display a table of all the applications running under DefaultAppPool and display if Anonymous authentication is enabled or not. (Now this one is almost on the edge of "you should do it differently, but it is Ok if you are only reading a single value from the section): var requests = (
from wp in serverManager.WorkerProcesses
from request in wp.GetRequests(1000)
orderby request.TimeElapsed descending
select request).Distinct().Take(20);
foreach (Request request in requests) {
Console.WriteLine(request.Url);
}
}
using (ServerManager serverManager = new ServerManager()) {
var items = from site in serverManager.Sites
from app in site.Applications
where app.ApplicationPoolName.Equals("DefaultAppPool", StringComparison.OrdinalIgnoreCase)
orderby site.Name, app.Path
select new {
Site = site,
Application = app,
AnoymousEnabled = ((bool)app.GetWebConfiguration().GetSection("system.webServer/security/authentication/anonymousAuthentication")["enabled"])
};
foreach (var item in items) {
Console.WriteLine("Site:{0,-18} App:{1, -10} Anonymous Enabled:{2}",
item.Site.Name, item.Application.Path, item.AnoymousEnabled);
}
}
As you can see LINQ is an incredibly useful feature in C# 3.0 and in conjunction with Microsoft.Web.Administration allows you to do incredibly complex operations in IIS with just few lines of code. var items = from site in serverManager.Sites
from app in site.Applications
where app.ApplicationPoolName.Equals("DefaultAppPool", StringComparison.OrdinalIgnoreCase)
orderby site.Name, app.Path
select new {
Site = site,
Application = app,
AnoymousEnabled = ((bool)app.GetWebConfiguration().GetSection("system.webServer/security/authentication/anonymousAuthentication")["enabled"])
};
foreach (var item in items) {
Console.WriteLine("Site:{0,-18} App:{1, -10} Anonymous Enabled:{2}",
item.Site.Name, item.Application.Path, item.AnoymousEnabled);
}
}