ASP.NET Core might not use a complicated hierarchy of XML configuration files anymore, but if you host under IIS, then IIS and web.config are still the best of friends. There is some XML configuration required to run Core under IIS, specifically the part to reverse proxy all incoming requests over to the ASP.NET Core module and ultimately into the Kestrel server.
Other pieces of web.config still work in the new world of ASP.NET, too. For example, IIS will still honor rewrite rules in web.config.
Here is a sample web.config to enforce lower case URLs that also proxies to the ASP.NET Core Module.
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="Convert to lower case" stopProcessing="true"> <match url=".*[A-Z].*" ignoreCase="false" /> <action type="Redirect" url="{ToLower:{R:0}}" redirectType="Permanent" /> </rule> </rules> </rewrite> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/> </handlers> <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/> </system.webServer> </configuration>
Over the summer I gave a talk titled “The New Dragons of JavaScript”. The idea was to provide, like the cartographers of the Old World, a map of where the dragons and sea serpents live in the new JavaScript feature landscape. These mythological beasts have a tendency to introduce confusion or pain in software development.
Arrow functions have surprised me with the amount of turmoil they’ve created. At first glance, they seem so easy, like when multiplying the numbers in an array by 2.
const numbers = [1, 2, 3]; const result = numbers.map(n => n * 2); // produces [2,4,6]
But even a simple map operation can run into problems if the code tries to map each element to an object literal using the wrong syntax.
const numbers = [1, 2, 3]; const result = numbers.map(n => { value: n }); // produces [undefined], [undefined], [undefined]
The problem in the above code is that the opening curly brace of the arrow function makes JavaScript think there is a block of code to execute instead of a simple object literal expression to evaluate. The result is an array of undefined. In this scenario the code either needs an explicit return statement, or to parenthesize the object literal.
const result = numbers.map(n => ({ value: n })); // [{value: 1}, {value:2}, {value:3}]
Ironically, most problems developers encounter with arrow functions center around the problem arrow functions attempt to solve. The slippery JavaScript this pointer. A bit of casual reading about arrow functions will tell you how arrow functions capture the this reference from their lexical environment. With arrows, you can write code like the following without worrying about explicitly capturing this into a local variable.
const adder = { sum: 0, add(numbers) { numbers.forEach(n => { this.sum += n; }); } }; adder.add([1, 2, 3]); // adder.sum === 6
However, it’s easy to write code that assumes the wrong environment. In the following code we have an arrow function inside an arrow function, so the this reference will not be the adder object, but whatever scope the adder object lives in.
const adder = { sum: 0, add: (numbers) => { // scope here is important numbers.forEach(n => { this.sum += n; }); } }; adder.add([1, 2, 3]); // adder.sum === 0
The biggest sea dragon on the map in the arrow function waters is highlighted in the “NOTE” section of 14.2.16 of the spec. The takeaway here is that we cannot change the this reference inside of an arrow function. The reference is fixed, it’s baked, it’s static and permanent. There are implications for two types of code. First is the type of code that expects to manipulate this using bind, call, or apply.
const adder = { sum: 0 }; const add = (numbers) => numbers.forEach(n => this.sum += 1); adder.add = add.bind(adder); adder.add([1, 2, 3]); // adder.sum === 0
The second type of code is code that expects someone else to setup this for a call. I first experienced the brain teaser of unexpected this values writing arrow functions with Jasmine. Jasmine sets this to a context object for sharing state between test setups and asserts. Arrow functions, Jasmine contexts and regular functions mix into a broken cocktail. The same problem can arise with DOM event handlers.
it("this is not what you might expect", () => { // .. this? });
Arrow functions are not a replacement for regular functions in JavaScript. There are situations where arrow functions do not work as expected. I’m not giving up on arrow functions, I still use them when possible. However, I do lament the fact that I still need to fret over every use of this in JavaScript code.
In some applications the Configure and ConfigureServices methods of Startup.cs can become unwieldy. It’s not complicated logic, but with all the middleware and services and options to configure, the methods become long and messy.
I prefer to keep a series of simple, one-line method calls inside of both methods.
public void ConfigureServices(IServiceCollection services) { // ... services.AddCustomizedMvc(); services.AddCustomizedIdentity(); services.AddDataStores(); // ... }
All of the details for these method calls live inside extensions methods for IApplicationBuilder or IServiceCollection. Here’s an example.
public static class ServiceCollectionExtensions { public static IServiceCollection AddCustomizedMvc(this IServiceCollection services) { var locationFormat = @"Features\Shared\{0}.cshtml"; var expander = new ViewWithControllerViewLocationExpander(); services.AddMvc() .AddRazorOptions(options => { options.ViewLocationFormats.Clear(); options.ViewLocationFormats.Add(locationFormat); options.ViewLocationExpanders.Add(expander); }); return services; } // ... }
The first course I ever made for Pluralsight was a LINQ Fundamentals course in 2008. I’ve received many great bits of feedback about the course over the last 8 years, but I’ve also learned a few things about teaching, presenting, and making courses during that time, too. Whenever I’m forced to listen to a clip from this early course I cringe. I sound like my speech was addled by sleeping pills and vodka.
A few months ago I decided it was time to make a new LINQ Fundamentals course, and this course was released just a few weeks ago. It’s mostly the same material as the original course, but with a more logical story arc and a perky sounding instructor.
I hope you enjoy watching the videos!
A number of people who have seen me code this year have asked me how I can make changes in an ASP.NET web application and see the changes in the browser without restarting the web application. The person asking always runs the application by starting the Visual Studio debugger.
The problem with starting the debugger is that later you’ll have to stop the debugger, and stopping the debugger also stops the default host process (IIS Express). Refreshing the browser at this point is like waiting for an echo in the emptiness of space.
I always run web applications without the debugger. The default shortcut key for this behavior is Ctrl + F5. Now the server can stay up and running, and changes are automatically loaded and seen in the browser after a reload. I will only run with the debugger if I have to debug code.
Unfortunately, Visual Studio encourages us to run with the debugger. Not only is the shortcut key easier (just F5), running with the debugger is also featured prominently in the menus and toolbars that appear in a web project.
Do yourself a favor and use Ctrl+F5 instead!
Routes are usually defined in an Aurelia application using a model’s configureRouter method in a declarative manner.
configureRouter(config, router) { this.router = router; config.title = "The App"; config.map([ { route: "", name: 'home', moduleId: "app/home", title:"Home", nav:true }, { route: "about", moduleId: "app/about", title: "About", nav:true } ]); }
However, you can also add routes at anytime using the Router’s API.
constructor(router) { this.router = router; } addRoute() { this.router.addRoute( { route: "secret", name: 'secret', moduleId: "app/secret", title:"Secret", nav:true } ); this.router.refreshNavigation(); }
I’d stick with the declarative routing whenever possible, but dynamically adding routes is useful in a few scenarios.
The 1.5 release of Angular JS is a release you should take a close look at if you, like me, still have some Angular 1 work to do. The new component based programming model simplifies application development with Angular by providing a cleaner API and sensible defaults when compared to programming with ng-controller and custom directives.
I was so impressed by the new addition to Angular 1 that I made a Pluralsight course covering how to program with components, and how to use components with old routers as well as the new component based router. The last module of the course looks at a variety of compositional patterns you can follow for building sophisticated pages using simple components.
In short, with components you’ll never need to use the ng-controller directive again. Components also replace most custom directives leaving only a few special case scenarios where you need to drop down to the lower level API of a directive.