This is part of the .NET Core and VS Code series, which contains:
Since the release of .NET Core 1.1, a lot has changed, so I am trying to keep this up to date as much as possible, but there still might be some leftover obsolete info from earlier versions.

Continuing the post about building a console application in .Net Core with the free Visual Studio Code tool on Windows, I will be looking at ASP.Net, also using Visual Studio Code. Some of the things required to understand this are in the previous post, so do read that one, at least for the part with installing Visual Studio Code and .NET Core.

Reading into it


Start with reading the introduction to ASP.Net Core, take a look at the ASP.Net Core Github repository and then continue with the information on the Microsoft sites, like the Getting Started section. Much more effort went into the documentation for ASP.Net Core, which shows - to my chagrin - that the web is a primary focus for the .Net team, unlike the language itself, native console apps, WPF and so on. Or maybe they're just working on it.

Hello World - web style


Let's get right into it. Following the Getting Started section, I will display the steps required to create a working web Hello World application, then we continue with details of implementation for common scenarios. Surprisingly, creating a web app in .Net Core is very similar to doing a console app; in fact we could just continue with the console program we wrote in the first post and it would work just fine, even without a 'web' section in launch.json.
  1. Go to the Explorer icon and click on Open Folder (or FileOpen Folder)
  2. Create a Code Hello World folder
  3. Right click under the folder in Explorer and choose Open in Command Prompt - if you have it. Some Windows versions removed this option from their context menu. If not, select Open in New Window, go to the File menu and select Open Command Prompt (as Administrator, if you can) from there
  4. Write 'dotnet new console' in the console window, then close the command prompt and the Windows Explorer window, if you needed it
  5. Select the newly created Code Hello World folder
  6. From the open folder, open Program.cs
  7. To the warning "Required assets to build and debug are missing from your project. Add them?" click Yes
  8. To the info "There are unresolved dependencies from '<your project>.csproj'. Please execute the restore command to continue." click Restore
  9. Click the Debug icon and press the green play arrow

Wait! Aren't these the steps for a console app? Yes they are. To turn this into a web application, we have to go through these few more steps:
  1. Open project.json and add
    ,"Microsoft.AspNetCore.Server.Kestrel": "1.0.0"
    to dependencies (right after Microsoft.NETCore.App)
  2. Open the .csproj file and add
    <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    </ItemGroup>
  3. Open Program.cs and change it by adding
    using Microsoft.AspNetCore.Hosting;
    and replacing the Console.WriteLine thing with
    var host = new WebHostBuilder()
    .UseKestrel()
    .UseStartup<Startup>()
    .Build();
    host.Run();
  4. Create a new file called Startup.cs that looks like this:
    using System;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;

    namespace <your namespace here>
    {
    public class Startup
    {
    public void Configure(IApplicationBuilder app)
    {
    app.Run(context =>
    {
    return context.Response.WriteAsync("Hello from ASP.NET Core!");
    });
    }
    }
    }

There are a lot of warnings and errors displayed, but the program compiles and when run it keeps running until stopped. To see the result open a browser window on http://localhost:5000. Closing and reopening the folder will make the warnings go away.

#WhatHaveWeDone


So first we added Microsoft.AspNetCore.Server.Kestrel to the project. We added the Microsoft.AspNetCore namespace to the project. With this we have now access to the Microsoft.AspNetCore.Hosting which allows us to use a fluent interface to build a web host. We UseKestrel (Kestrel is based on libuv, which is a multi-platform support library with a focus on asynchronous I/O. It was primarily developed for use by Node.js, but it's also used by Luvit, Julia, pyuv, and others.) and we UseStartup with a class creatively named Startup. In that Startup class we receive an IApplicationBuilder in the Configure method, to which we attach a simple handler on Run.

In order to understand the delegate sent to the application builder we need to go through the concept of Middleware, which are components in a pipeline. In our case Run was used, because as a convention Run is the last thing to be executed in the pipeline. We could have used just as well Use without invoking the next component. Another option is to use Map, which is also a convention exposed through an extension method like Run, and which is meant to branch the pipeline.

Anyway, all of this you can read in the documentation. A must read is the Fundamentals section.

Various useful things


Let's ponder on what we would like in a real life web site. Obviously we need a web server that responds differently for different URLs, but we also need logging, security, static files. Boilerplate such as errors in the pages and not found pages need to be handled. So let's see how we can do this. Some tutorials are available on how to do that with Visual Studio, but in this post we will be doing this with Code! Instead of fully creating a web site, though, I will be adding to the basic Hello World above one or two features at a time, postponing building a fully functioning source for another blog post.

Logging


We will always need a way of knowing what our application is doing and for this we will implement a more complete Configure method in our Startup class. Instead of only accepting an IApplicationBuilder, we will also be asking for an ILoggerFactory. The main package needed for logging is
"Microsoft.Extensions.Logging": "1.0.0"
, which needs to be added to dependencies in project.json.
From .NET Core 1.1, Logging is included in the Microsoft.AspNetCore package.

Here is some code:

Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Logging;

namespace ConsoleApplication
{
public class Startup
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
var logger=loggerFactory.CreateLogger("Sample app logger");
logger.LogInformation("Starting app");
}
}
}

project.json
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.Extensions.Logging": "1.0.0"
},
"imports": "dnxcore50"
}
}
}


So far so good, but where does the logger log? For that matter, why do I need a logger factory, can't I just instantiate my own logger and use it? The logging mechanism intended by the developers is this: you get the logger factory, you add logger providers to it, which in turn instantiate logger instances. So when the logger factory creates a logger, it actually gives you a chain of different loggers, each with their own settings.

For example, in order to log to the console, you run loggerFactory.AddConsole(); for which you need to add the package
"Microsoft.Extensions.Logging.Console": "1.0.0"
to project.json. What AddConsole does is actually factory.AddProvider(new ConsoleLoggerProvider(...));. The provider will then instantiate a ConsoleLogger for the logger chain, which will write to the console.

Additional logging options come with the Debug or EventLog or EventSource packages as you can see at the GitHub repository for Logging. Find a good tutorial on how to create your own Logger here.

Static files


It wouldn't be much of a web server if it wouldn't serve static files. ASP.Net Core has two concepts for web site roots: Web root and Content root. Web is for web-servable content files, while Content is for application content files, like views and stuff. In order to serve these we use the
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
package, we instruct the WebHostBuilder what the web root is, then we tell the ApplicationBuilder to use static files. Like this:

project.json
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.StaticFiles": "1.0.0"
},
"imports": "dnxcore50"
}
}
}


.csproj file
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
</ItemGroup>

</Project>

Program.cs
using System.IO;
using Microsoft.AspNetCore.Hosting;

namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var path=Path.Combine(Directory.GetCurrentDirectory(),"www");
var host = new WebHostBuilder()
.UseKestrel()
.UseWebRoot(path)
.UseStartup<Startup>()
.Build();

host.Run();
}
}
}

Startup.cs
using Microsoft.AspNetCore.Builder;

namespace ConsoleApplication
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseStaticFiles();
}
}
}

Now all we have to do is add a page and some files in the www folder of our app and we have a web server. But what does UseStaticFiles do? It runs app.UseMiddleware(), which adds StaticFilesMiddleware to the middleware chain which, after some validations and checks, runs StaticFileContext.SendRangeAsync(). It is worth looking up the code of these files, since it both demystifies the magic of web servers and awes through simplicity.

Routing


Surely we need to serve static content, but what about dynamic content? Here is where routing comes into place.

First add package
"Microsoft.AspNetCore.Routing": "1.0.0"
to project.json, then add some silly routing to Startup.cs:

project.json
{
"version": "1.0.0-*",
"buildOptions": {
"debugType": "portable",
"emitEntryPoint": true
},
"dependencies": {},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.Routing": "1.0.0"
},
"imports": "dnxcore50"
}
}
}


From .NET Core 1.1, Routing is found in the Microsoft.AspNetCore package.

Program.cs
using Microsoft.AspNetCore.Hosting;

namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Build();

host.Run();
}
}
}

Startup.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace ConsoleApplication
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}

public void Configure(IApplicationBuilder app)
{
app.UseRouter(new HelloRouter());
}

public class HelloRouter : IRouter
{
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}

public Task RouteAsync(RouteContext context)
{
var requestPath = context.HttpContext.Request.Path;
if (requestPath.StartsWithSegments("/hello", StringComparison.OrdinalIgnoreCase))
{
context.Handler = async c =>
{
await c.Response.WriteAsync($"Hello world!");
};
}
return Task.FromResult(0);
}
}
}
}

Some interesting things added here. First of all, we added a new method to the Startup class, called ConfigureServices, which receives an IServicesCollection. To this, we AddRouting, with a familiar by now extension method that shortcuts to adding a whole bunch of services to the collection: contraint resolvers, url encoders, route builders, routing marker services and so on. Then in Configure we UseRouter (shortcut for using a RouterMiddleware) with a custom built implementation of IRouter. What it does is look for a /hello URL request and returns the "Hello World!" string. Go on and test it by going to http://localhost:5000/hello.

Take a look at the documentation for routing for a proper example, specifically using a RouteBuilder to build an implementation of IRouter from a default handler and a list of mapped routes with their handlers and how to map routes, with parameters and constraints. Another post will handle a complete web site, but for now, let's just build a router with several routes, see how it goes:

Startup.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace ConsoleApplication
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}

public void Configure(IApplicationBuilder app)
{
var defaultHandler = new RouteHandler(
c => c.Response.WriteAsync($"Default handler! Route values: {string.Join(", ", c.GetRouteData().Values)}")
);

var routeBuilder = new RouteBuilder(app, defaultHandler);

routeBuilder.Routes.Add(new Route(new HelloRouter(), "hello/{name:alpha?}",
app.ApplicationServices.GetService<IInlineConstraintResolver>()));

routeBuilder.MapRoute("Track Package Route",
"package/{operation:regex(track|create|detonate)}/{id:int}");

var router = routeBuilder.Build();
app.UseRouter(router);
}

public class HelloRouter : IRouter
{
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}

public Task RouteAsync(RouteContext context)
{
var name = context.RouteData.Values["name"] as string;
if (String.IsNullOrEmpty(name)) name="World";

var requestPath = context.HttpContext.Request.Path;
if (requestPath.StartsWithSegments("/hello", StringComparison.OrdinalIgnoreCase))
{
context.Handler = async c =>
{
await c.Response.WriteAsync($"Hi, {name}!");
};
}
return Task.FromResult(0);
}
}
}
}

Run it and test the following URLs: http://localhost:5000/ - should return nothing but a 404 code (which you can check in the Network section of your browser's developer tools), http://localhost:5000/hello - should display "Hi, World!", http://localhost:5000/hello/Siderite - should display "Hi, Siderite!", http://localhost:5000/package/track/12 - should display "Default handler! Route values: [operation, track], [id, 12]", http://localhost:5000/track/abc - should again return a 404 code, since there is a constraint on id to be an integer.

How does that work? First of all we added a more complex HelloRouter implementation that handles a name. To the route builder we added a default handler that just displays the parameters receives, a Route instance that contains the URL template, the IRouter implementation and an inline constraint resolver for the parameter and finally we added just a mapped route that goes to the default router. That is why if no hello or package URL template are matched the site returns 404 and otherwise it chooses one handler or another and displays the result.

Error handling


Speaking of 404 code that can only be seen in the browser's developer tools, how do we display an error page? As usual, read the documentation to understand things fully, but for now we will be playing around with the routing example above and adding error handling to it.

The short answer is add some middleware to the mix. Extensions methods in
"Microsoft.AspNetCore.Diagnostics": "1.0.0"

like UseStatusCodePages, UseStatusCodePagesWithRedirects, UseStatusCodePagesWithReExecute, UseDeveloperExceptionPage, UseExceptionHandler.

Here is an example of the Startup class:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace ConsoleApplication
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRouting();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseStatusCodePages(/*context=>{
throw new Exception($"Page return status code: {context.HttpContext.Response.StatusCode}");
}*/);

var defaultHandler = new RouteHandler(
c => c.Response.WriteAsync($"Default handler! Route values: {string.Join(", ", c.GetRouteData().Values)}")
);

var routeBuilder = new RouteBuilder(app, defaultHandler);

routeBuilder.Routes.Add(new Route(new HelloRouter(), "hello/{name:alpha?}",
app.ApplicationServices.GetService<IInlineConstraintResolver>()));

routeBuilder.MapRoute("Track Package Route",
"package/{operation:regex(track|create|detonate)}/{id:int}");

var router = routeBuilder.Build();
app.UseRouter(router);
}

public class HelloRouter : IRouter
{
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
return null;
}

public Task RouteAsync(RouteContext context)
{
var name = context.RouteData.Values["name"] as string;
if (String.IsNullOrEmpty(name)) name = "World";
if (String.Equals(name, "error", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Hate errors! Won't say Hi!");
}

var requestPath = context.HttpContext.Request.Path;
if (requestPath.StartsWithSegments("/hello", StringComparison.OrdinalIgnoreCase))
{
context.Handler = async c =>
{
await c.Response.WriteAsync($"Hi, {name}!");
};
}
return Task.FromResult(0);
}
}
}
}

All you have to do now is try some non existent route like http://localhost:5000/help or cause an error with http://localhost:5000/hello/error

Final thoughts


The post is already too long so I won't be covering here a lot of what is needed such as security or setting the environment name so one can, for example, only show the development error page for the development environment. The VS Code ecosystem is at its beginning and work is being done to improve it as we speak. The basic concept of middleware allows us to build whatever we want, starting from scratch. In a future post I will discuss MVC and Web API and the more advanced concepts related to the web. Perhaps it will be done in VS Code as well, perhaps not, but my point is that with the knowledge so far one can control all of these things by knowing how to handle a few classes in a list of middleware. You might not need an off the shelf framework, you may write your own.

Find a melange of the code above in this GitHub repository.

I am relatively new to the entire NuGet ecosystem. What I expected is for things to just work. You know... Microsoft. However the web of interdepencies seems to be too much even for them. The problems that appear when updating MVC versions, .NET Framework versions, etc, are as annoying as they are unclear. One example: I was trying to publish a project that worked perfectly on my system. I moved it to the server machine, and weird things began to happen. The most annoying of them all is that the errors that occur do that at runtime instead of at compile time. Such an error was "Could not load file or assembly System.Web.WebPages, Version=3.0.0.0...". The project reference for WebPages was 2.0.0.0. If I removed it and tried to add a reference, only versions 1.0.0.0 and 2.0.0.0 were available. Meanwhile Razor was complaining that it didn't find the 3.0.0.0 version of WebPages.

Long story short: don't try to resolve only the library dependencies, but also the framework dependencies. In this case, System.Web.WebPages 3.0.0.0 is only available for the .NET framework 4.5.1. The project was configured as 4.5. Updating the MVC framework after the change to .NET 4.5.1 solved it.

Steps:
  • Change the project version to 4.5.1 (or whatever the newest usable .NET framework version)
  • go to the NuGet Package Manager Console in Visual Studio
  • Run command Update-Package -reinstall Microsoft.AspNet.Mvc

This, of course, is not a panacea for all problems, but just remember that the .NET framework is important in these scenarios.

I had this memory problem that I could not understand. OK, the design of the application was not the best in the world, but why would it always give me a damn OutOfMemoryException when I have a super duper computer with a lot of memory and I have solved issues like heap memory allocation? And the reason is that IISExpress, the default Windows7 ASP.Net web server is running in 32bit mode, meaning it has a maximum of 4GB of memory no matter what you do. Well, you can make IISExpress run in 64bit mode by simply switching it on in the Windows registry. I don't want to copy the content of the article from someone else, so here is a link towards how to do it: Debugging VS2013 Websites Using 64-bit IIS Express.

Just in case you want the ultra fast version, copy this into a file with the .reg extension and execute it:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\WebProjects]
"Use64BitIISExpress"=dword:00000001

Cheers!

We had a legacy import page in our application that took a very long time to perform its operation. Thus, the user was faced with a long loading empty page and no feedback. We wanted to do something to show the user the progress of the import without fundamentally changing the page. Of course, the best solution would have been to make the import an asynchronous background operation and then periodically get the status from the server via Ajax calls, but limited by the requirement to not change the page we came up with another solution: we would send bits of javascript while the import went on.

An attempt was made but it didn't work. All the scripts were loaded and executed at once. The user would still see an empty page, then a progress bar that immediately gets to 100%. Strange, that, since we knew that in certain circumstances, the scripts are executed as they are loaded. The answer was that browsers are caching a minimum bit of the page before they are interpreting it, about 1024 characters. The solution, then, was to send 1024 empty spaces before we start sending in the progress. This value of 1024 is not really documented or standard; it is a browser implementation thing.

Our design had the page loaded in an iframe, which allowed for scripts and html to not be loaded in the import page (thus making us stumble upon this behavior), and allowed for them to be loaded in the parent page. The scripts that we sent through the ASP.Net pipeline (using Response.Write and Response.Flush) accessed the resources from the parent page and showed a nice progress bar.

In case the page would have been a simple ASP.Net page, then the html and the CSS would have had to be sent first, perhaps instead of the 1024 spaces. There would have been problems when the page would have finished the import and the output of the page would have followed the one sent via the pipeline, but for our specific scenario it seems mere spaces and script blocks did not change the way browsers interpreted the rest of the page output.

A secondary side effect of this change was that we prevented the closing of the connection by some types of routers that need HTTP connections to have some traffic sent through them in an interval of time, providing a sort of "keep-alive". Before we made this change, these routers would simply cut the connection, leaving the user hanging.

I had a pretty strange bug to fix. It involved a class used in a web page that provided localized strings, only it didn't seem to work for Japanese, while French or English or German worked OK. The resource class was used like this: AdminUIString.SomeStringKey, where AdminUIString was a resx file in the App_GlobalResources folder. Other similar global resource resx classes were used in the class and they worked! The only difference between them was the custom tool that was configured for them. My problem class was using PublicResXFileCodeGenerator from namespace Resources, while the other classes used the GlobalResourceProxyGenerator, without any namespace.

Now, changing the custom tool did solve the issue there, but it didn't solve it in some integration tests where it failed. The workaround for this was to use HttpContext.GetGlobalResourceObject("AdminUIString", "SomeStringKey").ToString(), which is pretty ugly. Since our project was pretty complex, using bits of ASP.Net MVC and (very) old school ASP.Net, no one actually understood where the difference stood. Here is an article that partially explains it: Resource Files and ASP.NET MVC Projects. I say partially, because it doesn't really solve my problem in a satisfactory way. All it says is that I should not use global resources in ASP.Net MVC, it doesn't explain why it fails so miserable for Japanese, nor does it find a magical fix for the problem without refactoring the convoluted resource mess we have in this legacy project. It will have to do, though, as no one is budgeting refactoring time right now.

Update:
I've pinpointed the issue after a few other investigations. The https:// site was returning a security certificate that was issued for another domain. Why it worked in FireFox anyway and why it didn't work in Chrome, but then it worked after an unauthorized call first, I still don't know, but it is already in the domain of browser internals.

I was trying to access an API on https:// from a page that was hosted on http://. Since the scheme of the call was different from the scheme of the hosted URL, it is interpreted as a cross domain call. You might want to research this concept, called CORS, in order to understand the rest of the post.

The thing is that it didn't work. The server was correctly configured to allow cross domain access, but my jQuery calls did not succeed. In order to access the API I needed to send an Authorization header, as well as request the information as JSON. Investigations on the actual browser calls showed the correct OPTIONS request method, as well as the expected headers, only they appeared as 'Aborted'. It took me a few hours of taking things apart, debugging jQuery, adding and removing options to suddenly see it work! The problem was that after resetting IIS, the problem appeared again! What was going on?

In the end I've identified a way to consistently reproduce the problem, even if at the moment I have no explanation for it. The calls succeed after making a call with no headers (including the Content-Type one). So make a bogus, unauthorized call and the next correct calls will work. Somehow that depends on IIS as well as the Chrome browser. In Firefox it works directly and in Chrome it seems to be consistently reproducible.

I had to investigate a situation where a message of "Object moved to here", where "here" was a link, appeared in our ASP.Net application. First of all, we don't have that message in the app, it appears it is an internal message in ASP.Net, more exactly in HttpResponse.Redirect. It is a hardcoded HTML that is displayed as the response status code is set to 302 and the redirect location is set to the given URL. The browser is expected to move to the redirect location anyway, and the displayed message should be only a temporary thing. However, if the URL is empty, the browser does not go anywhere.

In conclusion, if you get to a webpage that has the following content:
<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href="[url]">here</a>.</h2>
</body></html>
then you are probably trying to Response.Redirect to an empty URL.

A Microsoft patch for ASP.Net released on the 29th of December 2011 adds a new functionality that rejects POST http requests with more than 1000 keys and any JSON http request with more than 1000 members. That is pretty huge, and if you have encountered this exception:
Operation is not valid due to the current state of the object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Operation is not valid due to the current state of the object.

Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:
[InvalidOperationException: Operation is not valid due to the current state of the object.]
System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded() +2692302
System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding) +61
System.Web.HttpRequest.FillInFormCollection() +148

[HttpException (0x80004005): The URL-encoded form data is not valid.]
System.Web.HttpRequest.FillInFormCollection() +206
System.Web.HttpRequest.get_Form() +68
System.Web.HttpRequest.get_HasForm() +8735447
System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) +97
System.Web.UI.Page.DeterminePostBackMode() +63
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +133


then your site has been affected by this patch.

Well, you probably know that something is wrong with the design of a page that sends 1000 POST values, but still, let's assume you are in a situation where you cannot change the design of the application and you just want the site to work. Never fear, use this:

<configuration xmlns=”http://schemas.microsoft.com/.NetConfiguration/v2.0>
<appSettings>
<add key="aspnet:MaxHttpCollectionKeys" value="5000" />
<add key="aspnet:MaxJsonDeserializerMembers" value="5000" />
</appSettings>
</configuration>


More details:
Knowledge base article about it
The security advisor for the vulnerability fixed
The entire MS11-100 security update bulletin

I was trying to access http://localhost/Reports/Page.aspx, in other words an ASP.Net page in the Reports path of the local site. Instead, I was getting a Windows authentication prompt that had no business being there. At first I thought to debug the page, but it wouldn't even get there before I got the authentication prompt. I googled for it, but I didn't get far because I was looking for weird Windows authentication prompts, not for the specific location of my page: the Reports folder. It was stranger yet, as I stopped IIS and the authentication dialog was still appearing!

In the end, a colleague told me the solution: SQL Reporting Services is answering on the local Reports path! I stopped the service and voila! no more authentication prompt. Instead, a Service unavailable 503 error. This article explained things quite clearly. Even if you stop the service, you have to delete the access control list entry for /Reports with the command netsh http delete urlacl url=http://+:80/Reports or, I guess, restart the system after you set the Reporting Services service to Manual or Disabled.

Update: It is even easier to go to Sql Server Configuration Tools (in the Start Menu), run the Reporting Service Configuration Manager, then change the URL for the Report Manager URL to something other than Reports.

But what is this strange Access Control List? You can get a clue by reading about Http.sys API in Windows Vista and above and about Namespace Reservation. Apparently, one can do similar things on Windows Server 2003 and maybe even XP with the Httpcfg utility.

I've finally finished reading Pro ASP.Net MVC Framework by Steven Sanderson. The book is slightly dated, since it discusses the technology used in Visual Studio 2008 and without any mention of the new Razor engine, but these are details that are not important to the content of the book anyway. I can say that it is a very nice book and it was worth reading, especially the first part.

There are two parts to this, the first being a TDD ASP.Net MVC web shop application built step by step and explained line by line. It goes through some Domain Driven Design concepts as well, it does unit testing and mocking, even shows off a little dependency injection via Castle Windsor. What I liked most, though, is how painstakingly thorough Sanderson was explaining every single detail. He didn't assume anything as he documented every step of the way, down to what lambda expressions are and what .Net features he was using.

The second part of the book is a little less readable, as it goes through the classes and features of ASP.Net MVC, complete with methods, properties and small samples. I highly recommend reading this part while actually experimenting with the framework on the computer. Even if you do not, this part of the book remains a very valuable reference for when you do. In this section of the book you can learn about data entry, Ajax and partial updates, application security and deployment, even how to mix classic ASP.Net with MVC, though not really recommended.

The bottom line is that Pro ASP.Net MVC Framework is a must read for a developer learning ASP.Net MVC. There is an updated version of the book for VS2010 and .Net 4 that I think that I will also read (the book was so good). Here is the link for Pro ASP.NET MVC 2 Framework.

Well, I have been kind of absent from the blog lately and that is for several reasons. One is that I have been waiting for some news that would determine my direction as a professional developer. The other is that I have re-acquired a passion for chess. So, between work at the office, watching chess videos, playing chess with my PDA and watching all seven seasons of Star Trek Deep Space 9, I haven't had much time for blogging.

Also, when you think about it, the last period of my programming life has been in some sort of a limbo: switched from ASP.Net to WPF, then to ASP.Net again (while being promised it would be temporary), then back to WPF (but in a mere executive position). Meanwhile, Microsoft didn't do much to help me, and thus saw their profits plummet. Well, maybe it was a coincidence, but what if it wasn't?

I am complaining about Microsoft because I was so sold into the whole WPF/Silverlight concept, while I was totally getting fed up with web work. Yet WPF is slow, with no clear development pathway when using it, while Silverlight is essentially something else, supported by only a few platforms, and I haven't even gotten around to use it yet. And now the Internet Explorer 9/Windows 8 duo come in force placing Javascript and HTML5 in the forefront again. Check out this cool ArsTechnica blog post about Microsoft's (re)new(ed) direction.

All of this, plus the mysterious news I have been waiting for that I won't detail (don't want to jinx it :-S), but which could throw me back into the web world, plus the insanity with the mobile everything that has only one common point: web. Add to it the not too enthusiastic reaction of my blog readers when starting talking about WPF. So the world either wants web or I just have been spouting one stupid thing after another and blew my readers away.

All these shining signs pointing me towards web development also say that I should be relearning web dev with ASP.Net MVC, getting serious about Javascript, relearning HTML in its 5th incarnation and finally making some sense of CSS. Exciting and crazy at the same time. Am I getting too old for this shit or am I ready for the challenge? We'll just have to see, won't we?

I restarted my computer and afterwards I could not access any of the local sites via IIS. The error message in the Application logs of the EventViewer was
Event Type: Error
Event Source: ASP.NET 4.0.30319.0
Description:
aspnet_wp.exe could not be started. The error code for the failure is C0000142. This error can be caused when the worker process account has insufficient rights to read the .NET Framework files. Please ensure that the .NET Framework is correctly installed and that the ACLs on the installation directory allow access to the configured account.
I did the classic
iisreset /stop
%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i
iisreset /start
to no avail. I was about to curse and restart the computer again when I found this pretty little link: IIS doesn't start. Error code: C0000142. A solution is at the bottom, as the least voted answer: Go to Task Manager, kill explorer.exe, Run another explorer.exe. This starts IIS (aspnet_wp.exe under inetinfo.exe) correctly.

Update: It bugged me that I had to kill explorer.exe. First of all it is a manual solution, then it always messed with my system tray icons. So I searched a little more. Short story shorter, you need to edit machine.conf and replace <processModel autoConfig="true" /> with <processModel userName="system" password="AutoGenerate" />. That effectively makes ASP.Net work under the System account, not the default machine. It does indicate the issue is permission related, but I don't get exactly where and why it should work if I restart explorer.exe. As long as you don't mind running ASP.Net under the System account, this solution seems to solve it. Here is the long version.

Note: you can find the machine.config file in %windir%\Microsoft.NET\Framework\[framework version]\Config\machine.config.

Well, there are a lot of good reasons why that could happen because of your bad code, but this time it is a plain ugly Microsoft bug. You see, the code in the RaisePostBackEvent method in the TreeView control first checks if the control has an Adapter and if not, it just does its thing. If there is an Adapter, it tries to cast it to a IPostBackEventHandler and then fires the RaisePostBackEvent event there. However, if the TreeView control has an adapter and it is not a RaisePostBackEvent, nothing happends!

Here is the offending code:

protected virtual void RaisePostBackEvent(string eventArgument)
{
base.ValidateEvent(this.UniqueID, eventArgument);
if (base.IsEnabled)
{
if (base._adapter != null)
{
IPostBackEventHandler handler =
base._adapter as IPostBackEventHandler;
if (handler != null)
{
handler.RaisePostBackEvent(eventArgument);
}
}
else ...


Bottom line, you need to either not use an adapter for the TreeView, or use one that knows how to handle the postback. And given the complexity of the code in the method, it is better to just not use an adapter.

The solution I have adopted is to recreate the functionality in an override of the RaisePostBackEvent method and add some more (like TreeNodeClicked and SelectedNodeClicked). Hint: you need to also get in LoadPostData and remember which nodes are selected in order to check if the selected node has changed.

Here is a post from Phil Haack about extra extensibility options in ASP.NET 4.0. I would like to emphasize the third "gem", the one that lets you add an assembly programatically to the list of loaded assemblies (equivalent to adding it in the assemblies tag in web.config). I wanted this from .Net 1.0 ! Unfortunately it must be called during the Application_PreStartInit stage of the application, but maybe the first gem can help with that.

Of course, I haven't been using these things yet, so I may be saying stupid things. It is a distinct possibility... Quite distinctive... Oh, shut up!

I was minding my own business doing this ridiculous ASP.Net project and suddenly I am hit with: "Multiple controls with the same ID 'lbTitle' were found. FindControl requires that controls have unique IDs.". I was using this web control that contained two others, each of them having a lbTitle control.

If you think about it, it does make sense to throw this exception when the FindControl method is used in the parent control. Which control did I mean? But the error appears even if the FindControl is used inside one of the child controls, what is up with that?

As a secondary thought, I wasn't using any FindControl. It seems that what does is the AssociatedControlID property of the Label control. Therefore I will set the HtmlTextWriterAttribute.For attribute manually to resolve this. Pretty damn ugly, if you ask me!


Update: My fault! The controls needed to implement the INamingContainer interface. It's not that the ClientID was not different, but FindControl works by going to the NamingContainer control and finding then children by ID. Too bad that you can't just specify the ClientID and be done with it, but that's that.