Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs
Contact   •   Articles   •   Products   •   Support   •   Search
Ad-free experience sponsored by:
ASPOSE - the market leader of .NET and Java APIs for file formats – natively work with DOCX, XLSX, PPT, PDF, images and more

First Steps: Exploring .NET Core and ASP.NET Core


.NET Core and ASP.NET Core 1.0 are finally here, and in this post I'll show how to get started with these new tools using the command line tooling. This is not meant to be your typical getting started tutorial that jumps right into Visual Studio and creates a Web project from there. Rather, the purpose of this post is to demonstrate some of the core underpinnings of how .NET Core and ASP.NET Core projects are bootstrapped and using the command line tooling is actually the best way to demonstrate this.

I'll start at the beginning with 'HelloWorld' then add additional pieces and ASP.NET and demonstrate how to deploy and then run the application both on Windows and a Mac.

You can find the code for this simple walkthrough at:

If you're brand new to .NET Core and what it all means you might also enjoy reading the Overview post first:

Command Line Tooling

One of the nice things about the new command line tooling is that all .NET pieces - the runtimes, compiler and command line tooling - are installed through a single unified install. As I mentioned in my ASP.NET and .NET Core Overview post.

I’ll use Windows here to create this first application, but note that you can also do the same thing on a Mac or a Linux machine if the .NET SDK is installed. The steps other than installation are the same so you can follow along on a Mac or Linux.

Start by downloading the .NET SDK from http://dot.net. Click on the .NET Core link and follow the install instructions for your platform. To create a new project, you can follow the directions from that page.

The steps are:

  • Create a new folder
  • Change to the new folder
  • dotnet new to create a new project
  • dotnet restore to bring down NuGet packages required
  • dotnet run to actually run the application

As you can see in Figure above the output of this console application is dumped to the console. You’ve just created and run a .NET application in 3 small steps.

Start with dotnet new which creates a new project with a program.cs file that contains a public Main() function, just like you expect for a classic Console application. All .NET Core applications, including ASP.NET applications now are Console applications.

The first thing you need to do is dotnet restore which restores all the NuGet packages linked in the project. In an empty project like this one it doesn't actually do anything other than reference the .NET Standard Library installed on your machine.

Once you've restored you can do dotnet run which runs the default hello world program:

You can now open the program.cs file in that was generated and change the code. For example, change the Console.WriteLine() to add a date and time:

using System;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World. Time is: " +
                              DateTime.Now.ToString("t"));
        }
    }
}

Back at the command line just use dotnet run and you should see the updated message including the time displayed.

Hello World. Time is: 5:36 PM

Note that the code automatically was recompiled and executed with the change you made when you did dotnet run. There's no explicit compilation step - there is however an explicit dotnet build command you can use if you explicitly want to just build your project.

To recap. You:

  • installed .NET
  • ran three commands
  • and had a running .NET piece of code

While developers of languages like NodeJs have taken this for granted you can now much more easily create new project or small utilities using this same approach using .NET.

Where's my Executable?

One thing you might have noticed in the code above is that you are not executing an EXE file. Instead you run dotnet run in a folder that contains a project.json file which contains the instructions to bootstrap the application. This does mean that current applications have to run out of a dedicated folder and have to contain the files to build the project.

Code is compiled into an assembly on the fly (stored in the bin folder as a DLL) which is then loaded by the dotnet runtime loader that hosts the DLL when you do dotnet run. The build process does produce binaries in the bin folder, but there's no mainline exe. dotnet run options determine whether the project is compiled or uses the existing assemblies from the bin folder.

Building an Exe

When you dotnet build or dotnet run using the project json shown earlier, it produces a platform agnostic, portable set of assemblies that can execute on any platform that are loaded from dotnet.exe when you run dotnet run.

It is possible to build your application to an EXE by creating a platform specific build. A number of directives in project.json can be used to specify the output targets. dotnet publish then creates a renamed dotnet.exe that automatically launches the platform specific project. For more info please see .NET Core Application Deployment (thanks to Bertrand for the link).

In the future there's also been talk about the creation of native binaries with dynamic compilation, but for now only this pass through execution through dotnet.exe and a required folder are supported.

Command Line Bigotry?

So the command line tooling is interesting in that it makes it much easier to create, build and run .NET applications.

But it's not just that you can perform the build process from the command line, but the fact that it’s very easy to get started. Download a relatively small SDK, install it, scaffold a base project, then use any text editor (or full boat Visual Studio) to make a change to your code and run. Compare that with the process of how you get started with the full version .NET, which pretty much involves downloading Visual Studio or installing a slew of SDKs and figuring CSC command line syntax. Using dotnet.exe with a few simple commands is a lot more approachable, and more importantly you can be up and running with this code from download to running code in about 5 minutes.

This is a very good thing!

The command line tools are there to make getting started easier and to appease those that like to work on a lower level than the big monster that is Visual Studio.

But that isn’t to say that you’re going to have to build your application from the command line now - you can still use Visual Studio which then uses the command line tooling for creating the projects on your behalf.

In fact, if you install the Visual Studio tooling for ASP.NET Core you get Visual Studio integration like you would expect, so you can use the rich Visual Studio editor and your favorite tools and extensions to build your applications.

But behind the scenes, Visual Studio calls into these same command line tools to compile your project. This opens up the build process to tooling or your own build process management, because you have easy access to the same tools that Visual Studio uses to build your project.

Personally I'm not a big command line guy - I prefer visual tooling for most things, but I have to admit that with this new tooling I find myself at the command line more often. Because the tooling is easy to use with terse commands it can often be quicker to restart an app from the command line than the Visual Studio run cycle. So beware - you might end up changing your habits (again - probably a good thing).

What about ASP.NET?

So far I’ve talked about general .NET with a console application, but what does all of that have to do with ASP.NET? Well, ASP.NET Core projects are Console applications that launch a Web server execution environment and use this very same infrastructure that I’ve talked about in the last example.

Let’s turn the lowly HelloWorld application into a much more desirable HelloWorld Web application. Change out the Main() method with the code shown here:

using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;

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

            host.Run();
        }
    }

    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {            
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync(
                    "Hello World. The Time is: " + 
                    DateTime.Now.ToString("hh:mm:ss tt"));
                                                               
            });
        }
    }
}

You’ll also need to make a small change in project.json to add a reference to pull in the Kestrel Web server and Http extensions:

 "dependencies": {
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0"
  },
  "frameworks": { ... }

Now go back to the command line and run the application again and then do:

dotnet restore

This updates the NuGet packages and pulls down the additional package. Then do:

dotnet run

and you should now get a prompt that states that the Web server has been started on port 5000. Navigate to http://localhost:5000 and… voila, HelloWorld from ASP.NET Core. You’ll get a plain text string:

Hello World. The Time is: 6/3/2016 2:32:20 PM

So this is super trivial, but it highlights the basic process of how an ASP.NET Core application bootstraps on top of the .NET Core runtime. You can see that the same Console application structure is used for ASP.NET. There’s no magic, you have full control all the way from the initial bootstrapping of the application, through startup configuration and into the full ASP.NET pipeline.

Middleware

ASP.NET Core applications are self contained Console applications that self host the Kestrel Web server. The code in Main() basically hoists up a new instance of Kestrel and configures it to handle Web requests. The configuration is delegated to the Startup class which usually lives in a separate file, but for simplicity I'm putting everything into a single file here.

The Startup class is where you can hook up custom middleware that is added to the ASP.NET pipeline. Middleware is essentially what we thought of as HttpHandlers and HttpModules in classic ASP.NET – it’s the stuff that makes things happen in an ASP.NET Core Web application.

App.Run() - Handler of Last Resort

The code in the Startup class above uses the App.Run() middleware handler, which is roughly the equivalent of an HttpHandler in classic ASP.NET. When App.Run() gets fired it’s expected to handle the inbound request completely and return a result. You can think of App.Run() as a last resort handler that is fired when nothing else has handled the request. In the example above there is nothing else handling requests, so the App.Run() handler is fired and hence we see the HelloWorld message.

App.Use - Middleware Modules

If App.Run() is like an Http handler, App.Use() is like an HttpModule. App.Use() handlers can be chained together and are fired in the order they are assigned. Unlike HttpModules middleware can handle both before and after request processing operations. Let’s modify the HelloWorld sample with an App.Use() handler that hooks in pre and post processing for each request on the server.

Add the following to the Configure method just before the App.Run() implementation:

app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Pre Processing");

    await next();

    await context.Response.WriteAsync("Post Processing");
});

If you stop the server with Ctrl-c and re-run it with dotnet run, you should now get:

Pre Processing...Hello World. The Time is: 6/3/2016 3:10:19 PMPost Processing...

As you can see the App.Use() middleware has wrapped itself around the App.Run() call. The middleware pipeline strings together all pieces of middleware one after the other and each piece of middleware calls the next in the chain. The middleware handlers are executed in order going in, and then in reverse order going out (stack behavior). Again if you think of the analogy with older ASP.NET versions you can think of it as pre and post request RequestHandler processing. All the pre-handlers fire until the pipeline has no more middleware or an operation doesn’t call next(), and then it reverses and walks the chain the other way. It’s a simple and elegant concept that's used by other server implementations like NodeJs and the previous ASP.NET OWIN architecture.

Hooking up ASP.NET MVC

App.Use() and App.Run() are very low level constructs akin to creating HttpHandlers and HttpModules and generally not the level at which you build applications. App.Use() is typically implemented by application frameworks like ASP.NET MVC or utility features like Authentication modules, state managers or loggers hook into.

When you build a Web application you tend use much higher abstractions such as ASP.NET MVC. Rather than implementing middleware yourself, ASP.NET MVC provides middleware integration with a configuration link that hooks up the MVC framework you then use to build your application. Once configured, building a typical ASP.NET Core MVC applications is fairly similar to the way you built older ASP.NET MVC applications.

To demonstrate let’s add ASP.NET MVC to our startup sample and create simple API endpoint that returns some JSON data to show that it works.

The first step to load the right packages loaded. Add the following to your dependencies in project.json:

  • "Microsoft.AspNetCore.Mvc": "1.0.0"

Make sure to do a dotnet restore (or build if you're in Visual Studio) to pull down the packages.

Next add the following configuration code to the Startup class:

using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;

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

            host.Run();
        }
    }

    public class Startup
    {
   
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseMvc();
        }
    }
}

This code sets up the required dependency injection in ConfigureServices() and then enables MVC for the application in Configure(). This is a common pattern: ConfigureServices() initializes dependency injection services typically with configuration settings that are set up so that dependency injection creates types with the right configuration settings when injected. Configure() then adjusts the behavior of the middleware which is typically a more specific wrapper around App.Use(). Methods like app.AddMvc() and app.UseMvc() are extension methods that are provided by the specific implementation – in this case provided by the Microsoft.AspNetCore.Mvc package.

In the case of MVC there’s no explicit configuration required, but other providers like EntityFramework or a logging provider require that you set up a connection string and data provider for example. Most .AddXXX() methods typically have overrides that pass in some sort of 'option' object with configurable properties or operations.

Once configuration is done, all that’s left is to create a controller. I’m going to start with an API request and I’ll create a good old HelloWorld API request. To do this create a class like this and add it to the bottom of program.cs:

public class HelloWorldController
{
    [HttpGet("api/helloworld")]
    public object HelloWorld()
    {
        return new
        {
            message = "Hello World",
            time = DateTime.Now
        };
    }
}

This is a controller with an API endpoint that returns an anonymous object instance. Because this is an API the result will be serialized - most likely into JSON (depending on the accept header of the client).

Now go back to the command line and again do dotnet run. Then navigate to http://localhost:5000/api/helloworld.

You should now get:

{
  message: "Hello World",
  time: "2016-06-03T15:39:18.339626-07:00"
}

And that's an API endpoint.

POCO Controller

Note that the controller implementation in this example doesn’t derive from Controller. It’s a POCO object and ASP.NET Core can figure out to call the controller’s method based on the name of the class by the Controller postfix convention. Unless you need specific features of the Controller base class you don’t have to inherit from it in ASP.NET Core. For simple APIs this can be useful as it reduces overhead of the relatively heavy Controller base class.

Adding MVC and Razor Views

Finally let’s add another method to the controller and render a Helloworld View page. To do this we need to make a couple of configuration changes. Start by adding this package in project.json:

  • "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0"

Do dotnet restore, then set .UseContentRoot() in the Main() startup to provide root path for the application:

public static void Main(string[] args)
{
  var host = new WebHostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseKestrel()
        .UseStartup<Startup>()                
        .Build();
    host.Run();
}

UseContentRoot is Required!

MVC uses the Content Root to figure out where the base folder for the application and without this things like MVC View resolution or general purpose virtual to physical path mapping doesn't work. It seems superfluous - after all we are running a Console app and it knows where it started - but without .UseContentRoot() anything that requires path mapping fails.

Now we can add a controller method to the existing Helloworld controller. Note that ASP.NET Core’s MVC version supports both API and MVC endpoints in the same controller, so I don’t need to create a separate controller class (although generally it’s a good idea to separate API and UI endpoints):

[HttpGet("helloworld")]
public ActionResult HelloworldMvc()
{
    ViewBag.Message = "Hello world!";
    ViewBag.Time = DateTime.Now;

    return View("helloworld");
    //return View("~/helloworld.cshtml");
}

There’s one more change required on this controller: When I showed the API request, the controller did not inherit from Controller and was a POCO object. But in this example I use the ViewBag and View() members of the base controller so this controller needs to inherit from Controller.

Change the Controller class definition to:

public class HelloworldController : Controller

Now all we need is a View. ASP.NET Core MVC uses standard View discovery logic by default, so it’s looking in the /Views/Helloworld folder for a HelloworldMvc.cshtml view. Instead I’ll create a helloworld.cshtml view which is reflected by explicitly specifying the requested view in the View("helloworld") call.

The view is ultra simple and just used to demonstrate that it works:

<label>Message:</label>
@ViewBag.Message

<hr/>

<label>Time:</label>
@ViewBag.Time

You also need to add one more setting to project.json in the builddOptions section:

  • "preserveCompilationContext": true

This option is required for dynamic compilation of views without it you will get a slew of errors that won't find dependencies. The switch passes forward all the host application assembly references.

The controller and view simply echo out the Viewbag values I passed from the controller as Razor expressions. Views work as you would expect supporting the full Razor/C# syntax. I’m only setting and accessing ViewBag values here, but of course you can also pass a full blown model object into the View just as you could in earlier versions of MVC.

Now go back to the command line and again do dotnet run. Then navigate to http://localhost:5000/helloworld.

You should now get:

Message: Hello world!
---
Time: 6/3/2016 9:29:12 PM

And that's an MVC Controller and View!

Where are we?

So at this point we started with a plain Console application, then added a low level ASP.NET Core handler implementation, followed by an MVC API implementation and finally an MVC View based implementation. All of the code required to do this is in a single small code file in about 60 lines of code as shown here:

using System;
using System.IO;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;

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

            host.Run();
        }
    }

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseDeveloperExceptionPage();

            app.UseMvc();

            //app.Use(async (context, next) =>
            //{
            //    await context.Response.WriteAsync("Pre Processing");
            //    await next();
            //    await context.Response.WriteAsync("Post Processing");
            //});

            // Handler of last Resort
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync(
                    "Hello World of the last resort. The Time is: " +
                    DateTime.Now.ToString("hh:mm:ss tt"));

            });
        }
    }

    public class HelloWorldController : Controller
    {
        [HttpGet("api/helloworld")]
        public object HelloWorld()
        {
            return new
            {
                message = "Hello World",
                time = DateTime.Now
            };
        }

        [HttpGet("helloworld")]
        public ActionResult HelloworldMvc()
        {
            ViewBag.Message = "Hello world!";
            ViewBag.Time = DateTime.Now;

            return View("helloworld");
            //return View("~/helloworld.cshtml");
        }
    }
}

Where’s IIS?

You may have noticed that I just ran a console application on Windows. There’s no IIS or other external Web server hosting the application. What’s happening is that ASP.NET Core uses a self-hosted Web Server (Kestrel which ASP.NET Core’s high performance Web Server) in a Console application.

The application is self-contained running with its own private copy of .NET and its own Web server which makes the application very portable. Portable in terms of deployment, but also portable in terms of platform – you can host this application on multiple operating systems and assuming you didn’t use any platform specific features the application will run on both using the same Kestrel Web server.

The application is self-hosted and doesn’t directly need a Web server to run. However, it’s not recommended to run Kestrel directly over the Internet. Instead you should use a front end reverse proxy like IIS on Windows or nginx or similar on Linux to front the IIS Web server. The reverse proxy provides multiple bindings to the open Http (80) and SSL (443) ports as well as potential load balancing and other request routing logic.

On Windows IIS additionally provides process management that can ensure that your application always stays running. If your application crashes it’s automatically restarted, much in the same way that the Windows Activation Service (WAS) does today with IIS Application Pools.

IIS Hosting

There’s a native AspNetCoreModule that is installed on Windows and IIS that handles ASP.NET Core routing and process management. This native module is lightweight and still requires an Application Pool, but no .NET Runtime. IIS doesn’t do any direct request processing, but rather acts as proxy to forward requests to your application.

Another benefit with this setup is that you can more easily set up load balancing and you can have a single server that requires an SSL certificate while the backplane runs over plain HTTP. You can also hide your application Web Server from the Internet as only the IIS server needs to be publicly exposed. When running ASP.NET Core on Windows, IIS is relegated to the job of reverse proxying and process management.

For more info on running ASP.NET Core on IIS check out:

Running on a Mac

So far I’ve run this little walk through exclusively on the Windows machine, but I can actually take this entire 'application' and move it over and run it on the Mac without any changes to the code!

To make this happen I'll push the project to source control on GitHub at:

The first thing that has to happen on the Mac side is to make sure that the .NET SDK is installed. Follow the simple and quick instructions there for installation and after a few minutes you should have a full install of .NET with the same feature functionality that I’ve discussed so far in this article. In fact, all of the steps I’ve run through so far (except for the section on IIS) apply just the same on the Mac or Linux for that matter.

Once the SDK is installed you can clone the repository from GitHub into any folder on your Mac or Linux machine. Once you have done that you can issue the following commands:

  • git clone https://github.com/RickStrahl/AspNetCoreFromScratchSample.git
  • dotnet restore
  • dotnet run

You can see the results in Figure 5 which shows the packages being downloaded and installed, the compiler building the application and then running the Web server on port 5000. You can then navigate to http://localhost:5000/api/helloworld, to see the API, MVC and the raw App.Run() endpoints.

While it’s not super practical or even realistic to have applications that run on multiple platforms, it’s pretty cool to see this 'just work' without any special effort or any code or configuration changes. We are no longer limited to just running on Windows which is exciting as it opens many new opportunities for .NET code.

Granted, the example are just about the most basic thing you can build so it’s not too surprising that the code works across platforms. But I’ve also taken a few more involved, data centric applications and moved them over to the Mac. I was surprised to find them just working as well. As long as you can stay away or isolate platform specific features in your application,.NET Core code just runs on multiple platforms now.

You can take a .NET Core application developed on Windows, restore it on a Mac or Linux and it just runs.

Core Analysis

It’s been a long journey for .NET Core and ASP.NET Core with a lot of false starts and a few tribulations along the way, but with the RTM release we're finally seeing all of that churn pay off in a flexible framework that finally seems to have a unified version on where its going in the future. The unified command line tooling features, the ability to run cross platform and relative ease with which you can now put applications together is good insight into what we can look forward to now and with the new features and functionality promised in the future.

In this article I’ve purposefully stuck to the low level aspects of creating a simple hello world application in a number of different ways, using just the command line tooling. This isn’t because I love command line tools, or because I plan on building everything using just this low level tooling. I’m quite happy using Visual Studio and the rich tooling and developer support it provides in the IDE, thank you very much. But I wanted to use this lower level approach because it demonstrates so much better how an application is put together than just hitting New Project in Visual Studio. Even if you do that from here on out, going through the manual process at least once really helps understanding the basic underpinnings of the platform so I hope you'll take the time to go through this exercise.

I hope you'll find this useful - it certainly has been helpful to me...

Related Links

Posted in ASP.NET Core  ASP.NET  

The Voices of Reason


 

Lee
June 29, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Everything worked until I tried to convert it to a web app. I updated my project.json file as mentioned above. However this gave the error:

"The dependency "Microsoft.AspNetCore.Server.Kestrel >= 1.0.0 could not be resolved."

Do you know what I may have done wrong?

Bertrand
June 30, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Great post as usual, thanks Rick! In "where's my exe", you missed that you can actually get an exe if you target a specific runtime. See https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/index

Nicholas Petersen
June 30, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

That was excellent Rick, thank you.

Rick Strahl
June 30, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@Lee - not sure why you would get that. Make sure you are online (the references are coming from NuGet after all) and that you have to the right target selected. Can you clone the project from Git to see if that works for you, and if it does compare what you find? Post back here if you find out what went wrong.

@Bertrand - thanks. Yup didn't know you could generate an Exe. I'll check it out and ammend the post later today.

Mike Gale
June 30, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Thanks for sharing your explorations. I was initially dubious about this approach, but this article has changed my mind.

Have you explored changing a Kestrel site to a pure IIS site (without the proxying)?

Rick Strahl
June 30, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@Mike - you can't run ASP.NET Core without Kestrel - Kestrel is THE web server that everything runs in. IIS is just a proxy front end as is something like ngnx on Linux. AFAIK there are no other hosts at the moment and I don't think you'd want another host really since Kestrel is highly optimized. You can embed Kestrel into other .NET Core apps so there should be very little need for something else.

Brad Falk
June 30, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@Lee After converting it to a web app you have to do a dotnet restore, before the dotnet run. This will pull down the AspNetCore related dependencies.

This is a great article Rick, thanks for this.

Rick Strahl
June 30, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@Brad - thanks for catching the missing `dotnet restore` calls whenever a library is added. I've added those into the post.

Kris
July 02, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Finally I have managed to run ASP.NET MVC using .NET Core on linux. Great, easy to follow article.

rahul
July 04, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

hi Rick,

I always loved your article and found you opening the nuts n bolts of internal systems.

One thing which is still kind of magic to me is : how coreclr is designed to target multiple OS ? Does Jitter uses conditional compilation to produce native code at run time ( meaning if target platform is MAC OS then run some MSIL else run some other MSIL for windows platoform ) ? As I know full CLR makes use of Win32 APIs for resource allocations ( like threads ) - how does CoreCLR address all this cross platform.

Could you please help me understand this !!

Thanks!

Rick Strahl
July 04, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@rahul - that's the way it's always worked with the JIT. In theory that was always possible and has been with Mono - you could run Windows compiled assemblies on Mac and Linux with Mono before - as long as you didn't stick Windows specific dependencies from the FCL into your code.

The runtime determines the execution environment that is platform specific, and the assembly code calls into the platform specific APIs that the runtime exposes for things like file access, network access and system resources like the environment etc.

With .NET Core you will eventually also be able to compile to native code by explicitly specifying your platform target which gets you a native binary. I think that works today with UWP executables (which is Windows only but you can get native, fully compiled binaries).

rahul agarwal
July 05, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Thanks Rick !!! One more quick thing, CLR itself is COM component and is specific to Windows. In this sense, is CoreCLR different ?

Also for MONO, is different runtimes required for different platforms.

Thanks!!

Serj
July 11, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Saw this article mentioned on the ASP.NET community stand-up. Good stuff. I know understand how the .Use .Run work.

Ammar
July 15, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Hi Rick,
I am trying to run an asp.net core app on Linux and Windows but it throws up saying appsettings.json not found. I figured out that if i run the command like (in windows):
C:\Users\Dev> dotnet C:\MyProgramFolder\MyProgram.dll
it sets the ContentRootPath to C:\Users\Dev which is obviously not what I want.
The program.cs contains the usual .UseContentRoot(Directory.GetCurrentDirectory()). How do we handle this?

Rick Strahl
July 16, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@Ammar - .NET Core Apps run out of the current folder that they are launched from, which is the same way .NET applications (and any Windows application for that matter) have always worked. If you want a different path and you want to control the path then you have to change path to that location. Path.SetPath() should work, along with looking at the executing assembly. .UseContentRoot() simply sets the path you provide it which in your code is the startup folder where you launched from.

Ammar
July 16, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@Rick - Thanks for the quick reply Rick. Indeed .net apps always run out of the current folder. Got a bit confused due to the problem that appsettings.json was not found. This project originally was created with RC1, migrated to to RC2 and then to RTM. I ran another project that was created fresh with RTM and it is worked fine. I compared all the configuration files and found everything same but still the first app did not work. I then opened the xproj file and replaced all "dnx" lines with "dotnet" ones copied for the new project and it all started working. Will dig more into it later.
Just mentioned it here so that someone else could save his/her time :)

Chris Harrington
July 19, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Hi Rich,
I see this code in controller
return View("helloworld");
//return View("~/helloworld.cshtml");
but nothing in your article explaining that second commented-out call.
I wasn't able to get either one to generate output.

Could you also elaborate on : "ASP.NET Core MVC uses standard View discovery logic by default, so it’s looking in the /Views/Helloworld folder for a HelloworldMvc.cshtml view. " I'm assuming that you didn't demonstrate this in your code. But again, I couldn't get any of the views to render.

Rick Strahl
July 19, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

@Chris - the second commented call was meant to demonstrate that you can serve Razor pages from any location in your wwwroot application. So ~/helloworld.cshtml can sit in the /wwwroot folder of your project and get served. Note that this only works if the Content Root is set in program.cs (which is why I was originally experimenting with this code as it wasn't working withtout the content root set).

QuantumHive
July 27, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Really great article! This helped me understand the basics. I've also read the previous "ASP.NET and .NET Core Overview" post.
Like you I'm not a Command-Line fanatic, I'd rather stick to VS, but I like to know what's happening behind the scenes.
With classic .NET, I've always had a pretty good idea and feeling what was happening when I developed an application.

This article now helps me understand more what happens when I create a new (ASP).NET Core project in VS.

Uwe
August 14, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

This is an awesome article.

While I rather dislike the design/layout/color of the website, I love your articles a lot.

They provide me in-depth information with a very good context, even if I have few background information of a topic. After reading your articles, I do _have_ good knowledge :-)

Mike
August 17, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Great articles, that's the approach I was looking for...very very good stuff :)

Thanks Rick

Steven
September 01, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Hi,
I followed your examples and built several 'projects' using the following simple folder structure : example 01, example 02, etc... Note the space in the folder names.
Everything built fine until I got to the mvc views example.
Turns out the space in the folder name was the culprit. Everything builds fine when the folder contains no spaces, otherwise you get an error like 'error CS2001 source file [path]views.deps.json could not be found'
Anyone else having the same issue or is it just my computer?
Steven

Caleb Jenkins
September 02, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Great write up Rick. Also, no need to "restore" to a mac, all of these steps can be followed along from a mac directly from scratch. So awesome.

Thendral
September 05, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Great article for beginners.
Thanks Rick!!

Erhan Kaluç
September 07, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Hi,

Would you have any ideas about clustering an asp.net web application on linux systems for multi core machines ?
I wonder if we need to do anything special for clustering or not. I previously using clustering on my nodejs web applications.

Regards

Fong
September 23, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Fantastic...after so many Hello World...this is the best, it explains how things work...!!!

Gives me confidence now..to move ...

Greg
September 27, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

Great Tutorial! Learned a lot from this.

Just a heads up, if you're trying to deploy or build on Linux the casing of the object matters for the view folder.

This snippet here -
[HttpGet("api/helloworld")]
                                public object HelloWorld()
                                {
                                                return new
                                                {
                                                                message = "Hello World",
                                                                time = DateTime.Now
                                                };
                                }


I had to rename the view folder to 'HelloWorld' mirroring the casing of the object in the git pull and in my application to get the view to render.

Cheers!

Chris
November 07, 2016

# re: First Steps: Exploring .NET Core and ASP.NET Core

I am coming from a pure javascript background using Node and found this tutorial helpful for learning about asp.net in general and how I can use Core on my Mac. Great article. I wish someone would write an article like this but "ported" to the Node user as I see this as MS's way of trying to lure those of use more used to Node than asp.net

Jose
January 05, 2017

# re: First Steps: Exploring .NET Core and ASP.NET Core

Fantastic, Rick!
As always, your post allows a developer to leap across the chasm of a new technology and hit the ground running. Thanks!

 

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2017