Solution and Project structure
If you are familiar with previous versions of ASP.NET, the change in solution and project structure in ASP.NET 5 is quite considerable.
The role of the solution is the same as in previous versions of Visual Studio: it is a container for organising the items required by your application. It includes projects, build configurations and so on. JSON is the preferred format for configuration files in other modern web development frameworks, so it has been chosen instead of XML as the default format for configuration files in ASP.NET 5. So the solution is defined by the contents of a global.json file (although VS 2015 still produces .sln files):
{ "projects": [ "src", "test" ], "sdk": { "version": "1.0.0-beta6" } }
VS2015 specifies two locations for projects in the solution: src
and test
. The src
project contains the actual application while the test
project contains any tests and will be generated automatically if you selected the option to include tests when creating the original application. The image above shows an application generated without this option selected. The file also specifies that this application will make use of the beta 6 version of ASP.NET 5. You can have multiple applications running on the same machine, each one targeting a different version of ASP.NET 5. Now that it is open source and free from the shackles of the rest of the .NET framework, it is anticipated that the release cycle for new major and minor versions of ASP.NET will be a lot more frequent than with previous versions.
The NuGet.config file is an XML file that contains details of the location of the NuGet feed from where packages used in the application will be retrieved.
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <!--To inherit the global NuGet package sources remove the <clear/> line below --> <clear /> <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" /> </packageSources> </configuration>
References
When expanded, the References node provides a visual tree-style representation of the frameworks that the project targets, and the server-side references ( .NET assemblies, NuGet packages, other projects) for each one.
The project above targets .NET 4.5.1. It also targets the new .NET Core framework (DNX Core 5.0), a lightweight cross platform and cloud optimised framework introduced as part of ASP.NET 5. As you add further references to server-side packages or libraries that your application depends on, they will appear here.
The wwwroot folder
The wwwroot folder is new in ASP.NET 5. It is the location for browsable static files, such as images, style sheets and JavaScript files. Source code must be located outside of the wwwroot folder. Also, if you have static files that require some form of processing before you make them available - for example, PDF files that should only be available to authenticated users - you would not place them in the wwwroot folder.
Dependencies
This node is like the References node, except that it features client-side dependencies. In previous versions of Visual Studio, you were expected to use the NuGet package manager to obtain client-side libraries such as jQuery, BootStrap. Angular and so on. Visual Studio 2015 features first class support for framework agnostic package managers and tools such as Bower and NPM. While you can still use NuGet for your client-side dependencies, you also have the option to get to know and use the tools that the rest of the development world are using. The next article in this series will focus on installing and using these tools.
The project.json file
This file is used to manage project settings and server side dependencies. It largely replaces the web.config file from previous versions of ASP.NET. The default file contains the following:
{ "webroot": "wwwroot", "version": "1.0.0-*", "dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-beta6", "Microsoft.AspNet.Server.WebListener": "1.0.0-beta6" }, "commands": { "web": "Microsoft.AspNet.Hosting --config hosting.ini" }, "frameworks": { "dnx451": { }, "dnxcore50": { } }, "publishExclude": [ "node_modules", "bower_components", "**.xproj", "**.user", "**.vspscc" ], "exclude": [ "wwwroot", "node_modules", "bower_components" ] }
The first section specifies which folder should act as the webroot. By default, it is the wwwroot folder covered earlier. If you change the name of this folder to another one in the solution, Visual Studio will reflect that change by applying the same globe icon in Solution Explorer for your new folder choice that it currently uses for the wwwroot folder.
The content of the dependencies section is reflected in Dependencies node in Solution Explorer. This is where you can add and remove NuGet packages. This section enjoys full IntelliSense support - the responsiveness of which depends on your Internet connection as the source for the IntelliSense matches is the NuGet feed specified in the NuGet.config file.
The commands section contains any commands you want to execute against dnx.exe, which is the .NET Execution Environment (DNX). Each entry represents the name of the command which acts as a kind of alias for the assembly that dnx.exe should attempt to load, together with any parameters that should be passed to the assembly. The "web" command included by default starts up a rudimentary web server (Microsoft.AspNet.Server.WebListener
found in the Microsoft.Asp.Net.Hosting
assembly) enabling hosting outside of IIS. As well as using a command prompt to execute commands, they are available in the Run menu in Visual Studio:
The arguments passed to the command spcify that the configuration for the simple web server can be found in a file called hosting.ini, which is also included as part of the project. This is a simple text-based config file with the following content:
server=Microsoft.AspNet.Server.WebListener
server.urls=http://localhost:5000
The frameworks section shows the frameworks that the application is designed to target. This is depicted visually in the References node in Solution Explorer as mentioned earlier. If you comment out the dnxcore50
entry in project.json, you will see (Restoring...) appear next to the References node as the entry for DNX Core 50 disappears:
Any framework-specific dependencies are listed in the braces that follow the framework entry.
The publishExclude section is for resources that should be excluded from the publishing process. Globbing syntax is supported for specifying wildcard matches when indicating the resource types that should be excluded. Items in the exclude section are excluded from compilation. The wwwroot folder is excluded from compilation as it should only contain static files. Two other folders, node_modules
and bower_components
have been excluded from publishing and compilation, but do not exist - yet. These will get created in the next tutorial when I look at managing client-side dependencies.
Startup.cs
The final file of interest is the Startup.cs file. This is the entry point for the bootstrapping your web application (performing initial configuration tasks). It will be familiar to those who have worked with OWIN-based applications in earlier versions of ASP.NET. ASP.NET 5 applications are designed to be composable, based on an opt-in policy, where you choose only the components and services required for your application. This is in contrast to previous versions of ASP.NET, where everything you could conceivably need was crammed in to System.Web, and you had to depend on that regardless. The Startup class is where you specify the modules that your application requires. The default code is minimal:
public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); } }
There are two methods: ConfigureServices
and Configure
. The ConfigureServices
method is called first by the ASP.NET runtime and acts to register services (components) with the built-in dependency injection system. Examples of services include MVC itself, ASP.NET Identity and Entity Framework. The Configure
method is where you register components with the Request pipeline in the order in which they should be called. The only thing that has been added to the request pipeline in the Empty template is a delegate that writes "Hello World!" to the Response.
Running the application
At this stage, you have not added anything to your ASP.NET 5 application. However, it will do something as determined by the delegate in the Configure
method. If you run the application without debugging by pressing Ctrl+F5, your default browser should appear with "Hello World!" in it:
Now navigate to the Startup.cs file and change the text in the delegate to say "Goodbye World!"
app.Run(async (context) => { await context.Response.WriteAsync("Goodbye World!"); });
Save the change and switch back to the browser. Hit F5 or click the Refresh button. The display should update to show the change you just made to the source code.
In previous versions of ASP.NET, you had to recompile your code to get changes to source code to take effect. Visual Studio 2015 makes use of a new compiler, Roslyn, which detects changes to source code files and recompiles the code in memory. This experience is very similar to the one enjoyed by users of dynamic languages such as PHP, Ruby, Python, VBScript etc and enables you to be more productive during development because you don't have to keep waiting around for your code to build before you can test changes to source code.
Summary
This article introduced the new project structure employed by ASP.NET 5 applications and explored the main files and their purpose. It also looked at how the latest in compiler technology treats strongly typed source code as if it was a dynamic language processed on the fly to improve the developer experience.The next article in the series will take a look at how the management of client-side dependencies is catered for, using popular open source tools that have been integrated with the latest version of Visual Studio.