Key Takeaways
- ASP.NET Core supports cross platform (windows / macOS / Linux) which pairs nicely with Azure's hosting of Windows & Linux virtual machines.
- ASP.NET Core includes a built-in container that supports constructor injection.
- Configure this container's services in the ConfigureServices in your ASP.NET Core app's Startup class.
- Azure Resource Manager templates allow for the scripted configuration of Azure VMs and the software they need.
- Azure App Service abstracts away the lower level details of server maintenance and lets developers deploy ASP.NET projects straight to Azure.
With the release of .NET Core 2.0, Microsoft has the next major version of the general purpose, modular, cross-platform and open source platform that was initially released in 2016. .NET Core has been created to have many of the APIs that are available in the current release of .NET Framework. It was initially created to allow for the next generation of ASP.NET solutions but now drives and is the basis for many other scenarios including IoT, cloud and next generation mobile solutions. In this series, we will explore some of the benefits .NET Core and how it can benefit not only traditional .NET developers but all technologists that need to bring robust, performant and economical solutions to market.
This InfoQ article is part of the series ".NET Core". You can subscribe to receive notifications via RSS.
One of the features of .NET Core that is the most interesting to me is the cross-platform support, both at development time and at runtime. No longer are you limited to Windows for .NET, you can now use both Linux and macOS for development and app runtime. Also, there are no constraints that require the same development and runtime platforms, so you can develop your .NET Core apps on a Mac, and then deploy to Windows and Linux servers.
Azure, the Microsoft Cloud Platform
Azure, Microsoft’s cloud platform, is a great match for .NET Core apps because of the wide range of infrastructure and platform services for hosting these applications, along with the broad cross-platform support. Azure has a set of foundational infrastructure services that provide compute, storage and networking capabilities that enable customers to deploy virtualized servers very much like managing infrastructure in a traditional data center. This approach provides customers with great control of the infrastructure and OS configuration that will host the applications. Azure Virtual Machines support multiple versions of Windows Server and multiple distributions of Linux, including Red Hat, CentOS, Suse and more.
Before you can deploy your .NET Core apps into Azure, you need to set up an application host or runtime in Azure. There are numerous ways you can deploy infrastructure and services in Azure. The easiest way to get started is using the Azure Portal. From the portal, you can find the services you need in the marketplace and go through a series of guided questions to configure and deploy these services. If you are configuring a virtual machine, once the VM is in a running state, you can remotely manage and configure it by using Remote Desktop if it is running Windows, or using SSH if it’s running Linux.
If you’re a fan of DevOps like me, you probably like to script and automate as much as you can so it’s repeatable and streamlined. Azure Resource Manager (ARM) templates allow you to automate the service deployment in Azure. ARM templates are simply JSON files that define the resources that you want to deploy and their relationships to each other. These ARM templates are very popular, and there is a GitHub repo that contains hundreds of pre-built templates for lots of services, platforms, and configurations. You can find these templates and the GitHub repo.
In addition to deploying and configuring Azure services, you can use ARM templates to configure the OS and install other dependencies using Virtual Machine extensions. For example, if you are setting up a web server on Ubuntu Linux, you will need to deploy the Ubuntu Linux Virtual Machine, and then deploy a web server like Apache. Using the custom script virtual machine extension, you can execute your custom script after the VM has finished deploying. Using these custom scripts, you can do things like installing other services and application servers like Apache and PHP. You can see an example of an ARM template that deploys an Ubuntu Linux server with Apache in the Azure Quickstart Templates GitHub repo. In the rendered README.md file on GitHub, you can click the “Deploy to Azure” as shown in Figure 1 button to start the process of deploying the selected template into your Azure subscription. Once you have a web server, you can deploy your ASP.NET Core apps and run them in Azure.
Figure 1 – Ubuntu with Apache GitHub README.md
Creating an ASP.NET Core App
Now it’s time to create a .NET Core app that we can deploy to Azure. Using Visual Studio 2017, I created a simple web API using ASP.NET Core. Since the new Hello World! web app seems to be a to-do list; I created a to-do list web API.
To get started, in Visual Studio I create a new project and selected the Web category and selected the ASP.NET Core Web Application template as shown in Figure 2.
Figure 2 – Visual Studio 2017 new ASP.NET Core Web Application
After creating the project, I added a model class that defines the properties for the to-do list item using the code shown in Figure 3. I kept it pretty lightweight and only created properties for the id and name of the to-do list item and a boolean to track if the item is completed.
public class TodoItem
{
public string Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
}
Figure 3 – TodoItem.cs model class
I like to use the repository pattern when creating data access classes, so I created an interface for the to-do list repository as shown in Figure 4. This defines all the methods I need for data access including a get method to read an individual to-do list item, a get method to return a list of all to-do list items, and methods to add, update and delete to-do list items.
public interface ITodoItemRepository
{
TodoItem Get(string id);
IList<TodoItem> Get();
void Add(TodoItem item);
void Update(TodoItem item);
void Delete(string id);
}
Figure 4 – ITodoItemRepository.cs to-do list repository pattern interface
I then created the implementation of the to-do list item repository interface using Entity Framework, as shown in Figure 5. This includes the EF context class and the repository class that uses the EF context.
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}
public DbSet<TodoItem> TodoItems { get; set; }
}
public class TodoItemRepository : ITodoItemRepository
{
private readonly TodoContext _context;
public TodoItemRepository(TodoContext context)
{
_context = context;
if (!_context.TodoItems.Any())
{
_context.TodoItems.Add(new TodoItem { Name = "Item1" });
_context.SaveChanges();
}
}
public TodoItem Get(string id)
{
return _context.TodoItems.FirstOrDefault(t => t.Id == id);
}
public IList<TodoItem> Get()
{
return _context.TodoItems.ToList();
}
public void Add(TodoItem item)
{
_context.TodoItems.Add(item);
_context.SaveChanges();
Figure 5 – TodoContext.cs and TodoListRepository.cs
Lastly, I created the controller for the to-do list web API using the code shown in Figure 6. The controller simply uses the ITodoItemRepository and executes the appropriate data access methods.
[Produces("application/json")]
[Route("api/Todo")]
public class TodoController : Controller
{
private ITodoItemRepository _repository;
public TodoController(ITodoItemRepository repository)
{
_repository = repository;
}
[HttpGet]
public IEnumerable<TodoItem> Get()
{
return _repository.Get();
}
[HttpGet("{id}", Name = "Get")]
public TodoItem Get(string id)
{
return _repository.Get(id);
}
[HttpPost]
public void Post([FromBody]TodoItem value)
{
_repository.Add(value);
}
[HttpPut("{id}")]
public void Put(int id, [FromBody]TodoItem value)
{
_repository.Update(value);
}
Figure 6 – TodoController.cs Web API controller
Now that we have completed the classes that implement the to-do list web API, we need to configure a couple of things for our web API to work. When we created the web API controller implementation, I mentioned that we are using the ITodoItemRepository, but after reviewing the code, you may be wondering how that ITodoItemRepository field gets an instance of the TodoItemRepository that implements Entity Framework. ASP.NET Core has built-in dependency injection container support to inject implementations at runtime, and with a call to an IServiceCollection.Add* method in the Startup.cs, as shown in Figure 7, we can associate the TodoItemRepository class with the ITodoItemRepository interface so that whenever a field of type ITodoItemRepository is needed, it can be initialized with an instance of the TodoItemRepository implementation. In this case, we are using the AddScoped() method, which creates a new instance per request and is recommended for Entity Framework. You can read more about the service lifetime options.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
services.AddScoped<ITodoItemRepository, TodoItemRepository>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
Figure 7 – Startup.cs
One other aspect that we need to configure is the data store for Entity Framework. For our simple Hello World! to-do list API, I chose to use the in-memory database. In the Startup.cs shown in Figure 7, the call to IServiceCollection.AddDbContext configures the in-memory database for the Entity Framework context.
With this, you can now press F5 and run this application locally and start debugging with Visual Studio. In addition to running it on Windows, you could also run this in macOS or Linux OS, and you can deploy it to a Windows or Linux VM in Azure too.
Deploy to Azure PaaS
As developers, we don’t want to worry about deploying, configuring and managing servers. Instead, we’d rather just focus on time and energy on developing our applications. While lower-level infrastructure services are available to us, Azure offers many higher-level platforms services that enable developers to focus on their applications and data, reducing the time spent setting up and configuring infrastructure. This also eliminates the ongoing OS and application server patching and maintenance for the customer.
Azure App Service is one of those higher-level platform services that abstract away and hide the servers and infrastructure and just provide us a target to deploy our web applications. In Visual Studio, you can right-click on an ASP.NET project, and select the Publish option as shown in Figure 8, to start deploying your web application to a Web App in Azure App Service.
Figure 8 – Visual Studio project context menu with Publish highlighted
After you select the Publish option, a screen in Visual Studio will display that will provide some deployment target options, and Azure App Service is the first option in that list as shown in Figure 9.
Figure 9 – Publish screen in Visual Studio
If you select Azure App Service, you can then select whether you want to create a brand new Web App by selecting the “Create New” option, or you can select an existing Web App in your Azure subscription by selecting the “Select Existing” option. After you do that, you can click the “Publish” button to start the walking through the guided deployment process. This will deploy to the default Azure App Service running on Windows, but now you can deploy to the Azure App Service running on Linux and even use Docker containers.
In Visual Studio, you can easily enable Docker container support for your ASP.NET Core application by right clicking on your ASP.NET Core project, selecting Add in the context menu, and select Docker Support as shown in Figure 10.
Figure 10 – Adding Docker Support to ASP.NET Core Apps
Visual Studio will then display a dialog that allows you to choose whether you want Windows or Linux Docker containers. After you select your platform, Visual Studio will add a Dockerfile to your project and a docker-compose node in the Solution Explorer that contains a couple of docker-compose.yml files.
Now when you right click on your Project and select Publish, you will see some different options including Microsoft Azure App Service Linux and Container Registry as shown in Figure 11.
Figure 11 – Publish screen in Visual Studio for an ASP.NET Core web application with Docker support
When you select Microsoft Azure App Service Linux, it will guide you through a deployment process that will set up an Azure App Service running on Linux, with docker support, and you will also have the option to create or use an existing docker container registry.
Azure is a large cloud platform with many services, and in this article, I’ve talked about infrastructure services like Virtual Machines, and platform services like App Service, but there are also other application runtimes that you could run .NET Core apps on in Azure including Azure Functions (serverless), Service Fabric (microservices) and Azure Container Service (docker containers) to name a few. If you are interested in these other services, I will encourage you to visit http://www.azure.com to learn more about those other services.
Conclusion
As I mentioned at the beginning of this article, one of my favorite features of .NET Core is the broad platform support including Windows, Linux, and macOS. Combined with Azure, you not only get development platform that is cross-platform, but you get a cloud platform to host and run your applications that support many OS’s including Windows Server and multiple distributions of Linux and additionally provides many higher-level platform services like Azure App Service, Docker containers, and serverless computing with Azure Functions. This capability is extremely exciting and opens many possibilities by providing broad ecosystem support and being open.
About the Author
Eric D. Boyd the Founder and CEO of responsiveX. responsiveX is a management and technology consultancy with deep industry and functional expertise. With a strong focus on user experience, innovation and emerging platforms, responsiveX clients get a strategic partner to help guide today’s development efforts while preparing for tomorrow’s innovation. Eric is passionate about technology, entrepreneurship and business growth. He loves developing innovative and disruptive startups, growing existing businesses and helping others increase the value and return of technology investments.
With the release of .NET Core 2.0, Microsoft has the next major version of the general purpose, modular, cross-platform and open source platform that was initially released in 2016. .NET Core has been created to have many of the APIs that are available in the current release of .NET Framework. It was initially created to allow for the next generation of ASP.NET solutions but now drives and is the basis for many other scenarios including IoT, cloud and next generation mobile solutions. In this series, we will explore some of the benefits .NET Core and how it can benefit not only traditional .NET developers but all technologists that need to bring robust, performant and economical solutions to market.
This InfoQ article is part of the series ".NET Core". You can subscribe to receive notifications via RSS.