Tag Archives: IIS

Viewing Server Variables in Asp.Net Core

In Asp.Net Core, you can view a list of data known as Server Variables. These are available when hosting inside IIS, and they give information about the request call and security.

You can view any one of these by adding some middleware to your Asp.Net Core project:

    app.Use(async (context, next) =>
    {
        var url = context.Features.Get<IServerVariablesFeature>()["URL"];

        await next.Invoke();
    }

You’ll need to be hosting inside IIS, and the code should go in the routing zone.

There is also a helper method for this, meaning you can do this instead:

    app.Use(async (context, next) =>
    {
        string a = context.GetServerVariable("URL");

        await next.Invoke();
    }

I then thought, why not just enumerate all the variables. You can see the list here.

I created a list of these:

    public static class ServerVariables
    {
        public static string[] Variables = new[]
        {
            "UNENCODED_URL",
            "URL",
            "QUERY_STRING",
            "REMOTE_ADDR",
            "ALL_HTTP",
            "AUTH_USER",
            "AUTH_TYPE",
            "REMOTE_USER",
            "SERVER_ADDR",
            "LOCAL_ADDR",
            "SERVER_PROTOCOL",
            "ALL_RAW",
            "REMOTE_HOST",
            "SERVER_SOFTWARE",
            "HTTP_RAW",
            "HTTP_COOKIE"
        };
    }

And then, in the middleware, just looped through them:

            app.Use(async (context, next) =>
            {                
                await context.Response.WriteAsync("<div>");
                foreach (var variable in ServerVariables.Variables)
                {
                    string result = context.GetServerVariable(variable);
                    await context.Response.WriteAsync($"<p>{variable}:    <b>{result}</b></p><br />");
                }

                await context.Response.WriteAsync("</div>");
                await next.Invoke();
            });

Remember that if you run this hosted in Kestrel, you’ll get nothing back.

References

https://docs.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms524602(v=vs.90)

Adding and Removing an IIS Application in .NET

Following on from an earlier post about my discovery of an API to control IIS, I had cause to investigate creating a new web application in IIS. The code, again, is remarkably simple:

            ServerManager iisManager = new ServerManager();

            Console.WriteLine("Set-up new site...");

            var sites = iisManager.Sites;

            foreach (var s in sites)
            {
                Console.WriteLine($"Site {s.Name}");

                foreach (var a in s.Applications)
                {
                    Console.WriteLine($"Application {a.Path}");
                }
            }
            Console.WriteLine(" - - - ");

            var defaultSite = sites["Default Web Site"];
            defaultSite.Applications.Add("/Test", @"c:\inetpub\betapps\test");        
            iisManager.CommitChanges();

            Console.ReadLine();

This works fine and, as you can see, is really simple. If you remove the information lines at the top, it’s three lines of code.

Remove it again

To remove the application again, try this:

            var iisManager = new ServerManager();
            var sites = iisManager.Sites;
            var defaultSite = sites["Default Web Site"];
            var testapp = defaultSite.Applications["/Test"];

            if (testapp != null)
            {
                Console.WriteLine("Remove site");
                defaultSite.Applications.Remove(testapp);
                iisManager.CommitChanges();
            }

There is an important note here; simply adding, committing changes and then removing using the same instance of ServerManager will not work. It complains that once CommitChanges is called then the object is read only:

InvalidOperation

The configuration object is read only, because it has been committed by a call to ServerManager.CommitChanges(). If write access is required, use ServerManager to get a new reference.

Also, you can’t just get around this by calling something like:

iisManager = new ServerManager();

Although this does

How to Programmatically Retrieve The Physical Path from an IIS Site

While looking for a way to automate some IIS tasks, I discovered this, Microsoft Produced, NuGet package. It appears to give almost full control over IIS to your code. I’ll try and post more about its features and limitations in further posts.

The Microsoft NuGet package Microsoft.Web.Administration:

NugetWebAdmin

The following code will trawl all the sites hosted on the local machine, and print some key information about each application within, including the physical path.

            ServerManager sm = new ServerManager();
            foreach (var s in sm.Sites)
            {
                Console.WriteLine($"Name: {s.Name}, state: {s.State}");
                
                foreach(var app in s.Applications)
                {
                    Console.WriteLine($"\t{app.ToString()}, path: {app.Path}");

                    foreach(var vd in app.VirtualDirectories)
                    {
                        Console.WriteLine($"\t\tPhysical path: {vd.PhysicalPath}");
                    }
                }
            }

Output:

WebAdminOutput

Chaos Monkey – Part 2 – Programmatically Resetting IIS at Scheduled Intervals

In this previous post I gave an example of a DOS batch script that simulated an unstable network. This is an alternative to that in .NET, which uses the `System.ServiceProcess` namespace

Let’s start with the main function:

        private static async Task MainLoop()
        {
            while (true)
            {
                Console.WriteLine("Stopping IIS");
                StopService("World Wide Web Publishing Service", 10000);

                await Task.Delay(3000);

                Console.WriteLine("Starting IIS");
                StartService("World Wide Web Publishing Service", 10000);

                await Task.Delay(5000);
            }
        }

This defines the flow of the code: essentially, it’s just stop the IIS service, wait, start it again… and wait. The service name for IIS is “World Wide Web Publishing Service” – at least for Windows 7 & 8 it is. The start and stop functions look like this:

        public static void StartService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);

            TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

            service.Start();
            service.WaitForStatus(ServiceControllerStatus.Running, timeout);
        }

        public static void StopService(string serviceName, int timeoutMilliseconds)
        {
            ServiceController service = new ServiceController(serviceName);

            // Only stop if it's started
            if (service.Status != ServiceControllerStatus.Running) return;

            TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

            service.Stop();
            service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
        }

Obviously these could be used to stop and start any service; although you must be running as admin to affect admin services (such as IIS).

To test this, check you have a “default.htm” in your wwwroot and then navigate to localhost in a web browser. Run this app in the background and press F5 on your browser until you get an error.