Tag: ASPNETCore


Deploy an Existing ASP.NET Core Web API to AWS Lambda

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

In the previous post, we talked about the new ASP.NET Core Web API blueprint for AWS Lambda, and the Amazon.Lambda.AspNetCoreServer NuGet package that made it possible to run the ASP.NET Core Web API through Lambda. But what if you already have an existing ASP.NET Core Web API that you want to try as a serverless application? You can do this by following these steps:

  • Add the Amazon.Lambda.AspNetCoreServer NuGet package.
  • Add a Lambda function and bootstrap the ASP.NET Core framework.
  • Add the Amazon.Lambda.Tools NuGet package to enable the toolkit’s deployment features.
  • Add a serverless.template file to define Amazon API Gateway.
  • Deploy the project.

Let’s take a deeper look at each step.

Setting Up the Lambda Function

The first step is to add the Amazon.Lambda.AspNetCoreServer NuGet package that bridges the communication between Amazon API Gateway and the ASP.NET Core framework.

After you add the package, add a new class named LambdaFunction and have it extend from Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction. You have to implement the abstract method Init to bootstrap the ASP.NET Core framework.


public class LambdaFunction : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
{
    protected override void Init(IWebHostBuilder builder)
    {
        builder
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup()
            .UseApiGateway();
    }
}

Enable Tool Support in the AWS Toolkit for Visual Studio

In order for the AWS Toolkit for Visual Studio to recognize the project as a Lambda project, you have to add the Amazon.Lambda.Tools NuGet package. This package isn’t used as part of the runtime of the function and is added as a build tool.


{  
  "dependencies": {
    ...

    "Amazon.Lambda.AspNetCoreServer": "0.8.4-preview1",
    "Amazon.Lambda.Tools": {
      "type": "build",
      "version": "1.1.0-preview1"
    }
  },

  ...
}

To also enable the integration with the .NET Core CLI, list the Amazon.Lambda.Tools NuGet package in the tools section in the project.json file.


{
  ...

  "tools": {
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
    "Amazon.Lambda.Tools": "1.1.0-preview1"
  },

  ...
}

Configuring Amazon API Gateway

At this point, you could right-click the project and deploy it to Lambda, but it wouldn’t be fronted by API Gateway exposing the function as an HTTP REST API. The easiest way to do that is to add a serverless.template file to the project and deploy the project as an AWS Serverless project.

Add a serverless.template file to the project by right-clicking the project and choosing Add, AWS Serverless Template.

add-serverless

The default serverless.template file contains one function definition configured to be exposed by API Gateway using proxy integration, so all requests will go to that function. This is exactly what you need for an ASP.NET Core Web API project. The only thing that needs to be updated is the handler field. The format for the handler field is <assembly-name>::<namespace>.LambdaFunction::FunctionHandlerAsync. The FunctionHandlerAsync method is inherited from the base class of our LambdaFunction class.


{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Transform" : "AWS::Serverless-2016-10-31",
  "Description" : "Starting template for an AWS Serverless Application.",
  "Parameters" : {
  },
  "Resources" : {
    "DefaultFunction" : {
      "Type" : "AWS::Serverless::Function",
      "Properties": {
        "Handler": "ExistingWebAPI::ExistingWebAPI.LambdaFunction::FunctionHandlerAsync",
        "Runtime": "dotnetcore1.0",
        "CodeUri": "",
        "Description": "Default function",
        "MemorySize": 256,
        "Timeout": 30,
        "Role": null,
        "Policies": [ "AWSLambdaFullAccess" ],
        "Events": {
          "PutResource": {
            "Type": "Api",
            "Properties": {
              "Path": "/{proxy+}",
              "Method": "ANY"
            }
          }
        }
      }
    }
  },
  "Outputs" : {
  }
}

Deploy

Now you can deploy the ASP.NET Core Web API to either AWS Elastic Beanstalk or Lambda. The deployment process works in the same way that we’ve shown in previous blog posts about AWS Serverless projects.

deploy-selector

And that’s all you have to do to deploy an existing ASP.NET Core Web API project to Lambda.

Visit our .NET Core Lambda GitHub repository to let us know what you think of running ASP.NET Core applications as an AWS Serverless functions and issues you might have. This will help us take the Amazon.Lambda.AspNetCoreServer NuGet package out of preview status.

Running Serverless ASP.NET Core Web APIs with Amazon Lambda

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

One of the coolest things we demoed at our recent AWS re:Invent talk about .NET Core support for AWS Lambda was how to run an ASP.NET Core Web API with Lambda. We did this with the NuGet package Amazon.Lambda.AspNetCoreServer (which is currently in preview) and Amazon API Gateway. Today we’ve released a new AWS Serverless blueprint that you’ll see in Visual Studio or with our Yeoman generator that makes it easy to set up an ASP.NET Core Web API project as a Lambda project.

Blueprint Picker

How Does It Work?

Depending on your platform, a typically deployed ASP.NET Core application is fronted by either IIS or NGINX, which forwards requests to the ASP.NET Core web server named Kestrel. Kestrel marshals the request into the ASP.NET Core hosting framework.

Normal Flow

When running an ASP.NET Core application as an AWS Serverless application, IIS is replaced with API Gateway and Kestrel is replaced with a Lambda function contained in the Amazon.Lambda.AspNetCoreServer package which marshals the request into the ASP.NET Core hosting framework.

Serverless Flow

The Blueprint

The blueprint creates a project that’s very similar to the one you would get if you selected the .NET Core ASP.NET Core Web Application and chose the Web API template. The key difference is instead of having a Program.cs file that contains a Main function bootstrapping the ASP.NET Core framework, the blueprint has LambdaEntryPoint.cs that bootstraps the ASP.NET Core framework.


public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
{
    protected override void Init(IWebHostBuilder builder)
    {
        builder
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseStartup()
            .UseApiGateway();
    }
}

The actual Lambda function comes from the base class. The function handler for the Lambda function is set in the AWS CloudFormation template named serverless.template, which will be in the format <assembly-name>::<namespace>.LambdaEntryPoint::FunctionHandlerAsync.

The blueprint also has LocalEntryPoint.cs that works in the same way as the original Program.cs file, enabling you to run and develop your application locally and then deploy it to Lambda.

The remainder of the project’s files are the usual ones you would find in an ASP.NET Core application. The blueprint contains two Web API controllers. The first is the example ValuesController, which is found in the starter ASP.NET Core Web API project. The other controller is S3ProxyController, which demonstrates how to use HTTP GET, PUT, and DELETE requests to a controller and uses the AWS SDK for .NET to make the calls to an Amazon S3 bucket. The name of the S3 bucket to use is obtained from the Configuration object, which means you can set the bucket in the appsettings.json file for local development.


{
  ...

  "AppS3Bucket": "ExampleBucketName"
}

The Configuration object is built by using environment variables.


public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

    builder.AddEnvironmentVariables();
    Configuration = builder.Build();
}

When the application is deployed, serverless.template is used to create the bucket and then pass the bucket’s name to the Lambda function as an environment variable.


...

"Get" : {
  "Type" : "AWS::Serverless::Function",
  "Properties": {
    "Handler": "AspNetCoreWithLambda::AspNetCoreWithLambda.LambdaEntryPoint::FunctionHandlerAsync",
    "Runtime": "dotnetcore1.0",
    "CodeUri": "",
    "MemorySize": 256,
    "Timeout": 30,
    "Role": null,
    "Policies": [ "AWSLambdaFullAccess" ],
    "Environment" : {
      "Variables" : {
        "AppS3Bucket" : { "Fn::If" : ["CreateS3Bucket", {"Ref":"Bucket"}, { "Ref" : "BucketName" } ] }
      }
    },
    "Events": {
      "PutResource": {
        "Type": "Api",
        "Properties": {
          "Path": "/{proxy+}",
          "Method": "ANY"
        }
      }
    }
  }
},

...

Logging

ASP.NET Core introduced a new logging framework. To help integrate with the logging framework, we’ve also released the NuGet package Amazon.Lambda.Logging.AspNetCore. This logging provider allows any code that uses the ILogger interface to record log messages to the associated Amazon CloudWatch log group for the Lambda function. When used outside of a Lambda function, the log messages are written to the console.

The blueprint enables the provider in Startup.cs, where other services are configured.


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddLambdaLogger(Configuration.GetLambdaLoggerOptions());
    app.UseMvc();
}

This following snippet shows the call GetLambdaLoggerOptions from the Configuration object, which grabs the configuration of what messages to write to CloudWatch Logs. The appsettings.json file in the blueprint configures logging so that messages coming from classes under the Microsoft namespace are written if they’re informational level and above. For all other log messages, write debug level messages and above.


{
  "Lambda.Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft": "Information"
    }
  },

  ...
}

For more information about this package, see the GitHub repository.

Deployment

Deploying the ASP.NET Core Web API works exactly as we showed you in the previous post about the AWS Serverless projects.

Deploy from Solution Explorer

Once deployed, a single Lambda function and an API Gateway REST API are configured to send all requests to the Lambda function. Then the Lambda function uses the ASP.NET Core framework to route to the correct Web API controller. You can test the deployment by accessing the two controllers using the AWS Serverless URL found in the CloudFormation stack view.

  • <aws-serverless-url>/api/values – Example controller
  • <aws-serverless-url>/api/s3proxy – S3 Proxy controller.

Feedback

We’re very excited about running ASP.NET Core applications on AWS Lambda. As you can imagine, the option of running the ASP.NET Core framework on top of Lambda opens lots of possibilities. The Amazon.Lambda.AspNetCoreServer package is in preview while we explore those possibilities. I highly encourage .NET developers to check out this blueprint and the Amazon.Lambda.AspNetCoreServer package and let us know on our GitHub repository or our new Gitter channel what you think and how we can continue to improve the library.

Configuring AWS SDK with .NET Core

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

One of the biggest changes in .NET Core is the removal of ConfigurationManager and the standard app.config and web.config files that were used ubiquitously with .NET Framework and ASP.NET applications. The AWS SDK for .NET used this configuration system to set things like AWS credentials and region so that you wouldn’t have to do this in code.

A new configuration system in .NET Core allows any type of input source from any location. Also, the configuration object isn’t a global singleton like the old ConfigurationManager was, so the AWS SDK for .NET doesn’t have access to read settings from it.

To make it easy to use the AWS SDK for .NET with .NET Core, we have released a new NuGet package called AWSSDK.Extensions.NETCore.Setup. Like many .NET Core libraries, it adds extension methods to the IConfiguration interface to make getting the AWS configuration seamless.

Using AWSSDK.Extensions.NETCore.Setup

If we create an ASP.NET Core MVC application in Visual Studio, the constructor for Startup.cs handles configuration by reading in various input sources, using the ConfigurationBuilder and setting the Configuration property to the built IConfiguration object.

public Startup(IHostingEnvironment env)
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
        .AddEnvironmentVariables();
    Configuration = builder.Build();
}

To use the Configuration object to get the AWS options, we first add the AWSSDK.Extensions.NETCore.Setup NuGet package. Then, we add our options to the configuration file. Notice one of the files added to the ConfigurationBuilder is called $"appsettings.{env.EnvironmentName}.json". If you look at the Debug tab in the project’s properties, you can see this file is set to Development. This works great for local testing because we can put our configuration in the appsettings.Development.json file, which is loaded only during local testing in Visual Studio. When we deploy to an Amazon EC2 instance the EnvironmentName will default to Production and this file will be ignored causing the AWS SDK for .NET to fall back to the IAM credentials and region configured for the EC2 instance.

Let’s add an appsettings.Development.json file to our project and supply our AWS settings.

{
  "AWS": {
    "Profile": "local-test-profile",
    "Region": "us-west-2"
  }
}

To get the AWS options set in the file, we call the extension method that is added to IConfiguration, GetAWSOptions. To construct a service client from these options, we call CreateServiceClient. The following example code shows how to create an S3 service client.

var options = Configuration.GetAWSOptions();
IAmazonS3 client = options.CreateServiceClient();

ASP.NET Core Dependency Injection

The AWSSDK.Extensions.NETCore.Setup NuGet package also integrates with a new dependency injection system in ASP.NET Core. The ConfigureServices method in Startup is where the MVC services are added. If the application is using Entity Framework, this is also where that is initialized.

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();
}

The AWSSDK.Extensions.NETCore.Setup NuGet package adds new extension methods to IServiceCollection that you can use to add AWS services to the dependency injection. The following code shows how we add the AWS options read from IConfiguration and add S3 and Amazon DynamoDB to our list of services.

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();
    services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
    services.AddAWSService<IAmazonS3>();
    services.AddAWSService<IAmazonDynamoDB>();
}

Now, if our MVC controllers use either IAmazonS3 or IAmazonDynamoDB as parameters in their constructors, the dependency injection system passes those services in.

public class HomeController : Controller
{
    IAmazonS3 S3Client { get; set; }

    public HomeController(IAmazonS3 s3Client)
    {
        this.S3Client = s3Client;
    }

    ...

}

Summary

We hope this new AWSSDK.Extensions.NETCore.Setup NuGet package helps you get started with ASP.NET Core and AWS. Feel free to give us your feedback at our GitHub repository for the AWS SDK for .NET

Multiple Application Support for .NET and Elastic Beanstalk

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

In the previous post we talked about the new deployment manifest you can use to deploy applications to AWS Elastic Beanstalk. You can now use the deployment manifest to deploy multiple applications to the same Elastic Beanstalk environment.

The deployment manifest supports ASP.NET Core web applications and msdeploy archives for traditional ASP.NET applications. Imagine a scenario in which you’ve written a new amazing application using ASP.NET Core for the front end and a Web API project for an extensions API. You also have an admin app that you wrote using traditional ASP.NET.

The toolkit’s deployment wizard focuses on deploying a single project. To take advantage of the multiple application deployment, you have to construct the application bundle by hand. To start, you need to write the manifest. For this example, write the manifest at the root of your solution.

The deployment section in the manifest has two children: an array of ASP.NET Core web applications to deploy, and an array of msdeploy archives to deploy. For each application, you set the IIS path and the location of the application’s bits relative to the manifest.

{
  "manifestVersion": 1,
  "deployments": {
 
    "aspNetCoreWeb": [
      {
        "name": "frontend",
        "parameters": {
          "appBundle": "./frontend",
          "iisPath": "/frontend"
        }
      },
      {
        "name": "ext-api",
        "parameters": {
          "appBundle": "./ext-api",
          "iisPath": "/ext-api"
        }
      }
    ],
    "msDeploy": [
      {
        "name": "admin",
        "parameters": {
          "appBundle": "AmazingAdmin.zip",
          "iisPath": "/admin"
        }
      }
    ]
  }
}

With the manifest written, you’ll use Windows PowerShell to create the application bundle and update an existing Elastic Beanstalk environment to run it. To get the full version of the Windows PowerShell script used in this example, right-click here. The script is written with the assumption that it will be run from the folder that contains your Visual Studio solution.

The first thing you need to do in the script is set up a workspace folder to create the application bundle.

$publishFolder = "c:temppublish"

$publishWorkspace = [System.IO.Path]::Combine($publishFolder, "workspace")
$appBundle = [System.IO.Path]::Combine($publishFolder, "app-bundle.zip")

If (Test-Path $publishWorkspace){
	Remove-Item $publishWorkspace -Confirm:$false -Force
}
If (Test-Path $appBundle){
	Remove-Item $appBundle -Confirm:$false -Force
}

Once the workspace is set up, you can get the front end ready. To do that use the dotnet CLI to publish the application.

Write-Host 'Publish the ASP.NET Core frontend'  
$publishFrontendFolder = [System.IO.Path]::Combine($publishWorkspace, "frontend")
dotnet publish .srcAmazingFrontendproject.json -o $publishFrontendFolder -c Release -f netcoreapp1.0

Notice that the subfolder "frontend" was used for the output folder matching the folder set in the manifest. Now let’s do the same for the Web API project.

Write-Host 'Publish the ASP.NET Core extensiblity API' 
$publishExtAPIFolder = [System.IO.Path]::Combine($publishWorkspace, "ext-api") 

dotnet publish .srcAmazingExtensibleAPIproject.json -o $publishExtAPIFolder -c Release -f netcoreapp1.0 

The admin site is a traditional ASP.NET application, so you can’t use the dotnet CLI. For this project, use msbuild, passing in the build target package to create the msdeploy archive. By default, the package target creates the msdeploy archive under the objReleasePackage folder, so you need to copy the archive to the publish workspace.

Write-Host 'Create msdeploy archive for admin site'

msbuild .srcAmazingAdminAmazingAdmin.csproj /t:package /p:Configuration=Release

Copy-Item .srcAmazingAdminobjReleasePackageAmazingAdmin.zip $publishWorkspace

To tell the Elastic Beanstalk environment what to do with all these applications, you copy the manifest from your solution to the publish workspace and then zip up the folder.

Write-Host 'Copy deployment manifest'
Copy-Item .aws-windows-deployment-manifest.json $publishWorkspace

Write-Host 'Zipping up publish workspace to create app bundle'
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory( $publishWorkspace, $appBundle)

Now that you have the application bundle, you can go to the web console and upload your archive to an Elastic Beanstalk environment. Or you can keep using Windows PowerShell and use the AWS PowerShell cmdlets to update the Elastic Beanstalk environment to the application bundle. Be sure you’ve set the current profile and region to the profile and region that has your Elastic Beanstalk environment by using the Set-AWSCredentials and Set-DefaultAWSRegion cmdlets.

Write-Host 'Write application bundle to S3'
# Determine S3 bucket to store application bundle
$s3Bucket = New-EBStorageLocation
Write-S3Object -BucketName $s3Bucket -File $appBundle


$applicationName = "ASPNETCoreOnAWS"
$environmentName = "ASPNETCoreOnAWS-dev"
$versionLabel = [System.DateTime]::Now.Ticks.ToString()

Write-Host 'Update Beanstalk environment for new application bundle'

New-EBApplicationVersion -ApplicationName $applicationName -VersionLabel $versionLabel -SourceBundle_S3Bucket $s3Bucket -SourceBundle_S3Key app-bundle.zip

Update-EBEnvironment -ApplicationName $applicationName -EnvironmentName $environmentName -VersionLabel $versionLabel

Now check the update status in either the Elastic Beanstalk environment status page or in the web console. Once complete, you can navigate to each of the applications you deployed at the IIS path set in the deployment manifest.

We hope you’re excited about the features we added to AWS Elastic Beanstalk for Windows and AWS Toolkit for Visual Studio. Visit our forums and let us know what you think of the new tooling and what else you would like to see us add.

Customizing ASP.NET Core Deployments

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

In our previous post we announced support for deploying ASP.NET Core applications with AWS Elastic Beanstalk and the AWS Toolkit for Visual Studio. Today, we’ll talk about how deployment works and how you can customize it.

After you go through the deployment wizard in the AWS Toolkit for Visual Studio, the toolkit bundles the application and sends it to Elastic Beanstalk. When the toolkit creates the bundle, the first step is to use the new dotnet CLI and the publish command to prepare the application for publishing. The settings in the wizard pass the framework and configuration to the publish command. So if you selected Release for configuration and netcoreapp1.0 for the framework, the toolkit will execute the following command.

dotnet publish --configuration Release --framework netcoreapp1.0

When the publish command finishes, the toolkit writes the new deployment manifest into the publishing folder. The deployment manifest is a JSON file named aws-windows-deployment-manifest.json, which is read by the new tooling added to the 1.2 version of the Elastic Beanstalk Windows container to figure out how to deploy the application. For example, for an ASP.NET Core application that you want to deploy at the root of IIS, the toolkit generates a manifest file that looks like this.

{
  "manifestVersion": 1,
  "deployments": {
 
    "aspNetCoreWeb": [
      {
        "name": "app",
        "parameters": {
          "appBundle": ".",
          "iisPath": "/",
          "iisWebSite": "Default Web Site"
        }
      }
    ]
  }
}

The appBundle property indicates where the application bits are in relation to the manifest file. This property can point to either a directory or a ZIP archive. The iisPath and iisWebSite properties indicate where in IIS to host the application.

Declaring the Manifest

The toolkit only writes the manifest file if it doesn’t already exist in the publishing folder. If the file does exist, the toolkit updates the appBundle, iisPath, and iisWebSite properties in the first application listed in the aspNetCoreWeb section of the manifest. This allows you to add the aws-windows-deployment-manifest.json to your project and customize the manifest. To do this for an ASP.NET Core Web application in Visual Studio, add a new JSON file to the root of the project and name it aws-windows-deployment-manifest.json.

The manifest must be named aws-windows-deployment-manifest.json and it must be at the root of the project. The Elastic Beanstalk container looks for the manifest at the root and, if it finds it, will invoke the new deployment tooling. If the file doesn’t exist, the Elastic Beanstalk container falls back to the older deployment tooling, which assumes the archive is a msdeploy archive.

To ensure the dotnet CLI publish command includes the manifest, you must update the project.json file to include the manifest file in the include section that’s under publishOptions.

Customizing the Manifest File for Application Deployment

Now that you’ve declared the manifest so that it’s included in the app bundle, you can go beyond what the wizard supports to customize your application’s deployment. AWS has defined a JSON schema for aws-windows-deployment-manifest.json. When you installed the AWS Toolkit for Visual Studio, the setup registers deployment manifest schema.

If you look at the Schema box, you’ll see the schema is set to aws-windows-deployment-manifest-schema.json. When the schema is selected, Visual Studio provides IntelliSense while you’re editing the manifest.

For non Visual Studio users the deployment manifest schema can be accessed online here.

One customization you can do is to configure the IIS application pool that runs the application. The following example shows how you can define an IIS application pool that recycles the process every hour and assigns it to the application.

Additionally, the manifest can declare Windows PowerShell scripts to run before and after the install, restart, and uninstall actions. For example, the following manifest runs the Windows PowerShell script PostInstallSetup.ps1 to do more setup work after the ASP.NET Core application is deployed to IIS. Remember, just like the aws-windows-deployment-manifest.json file, be sure to add your scripts to the include section under publishOptions in the project.json file. If you don’t, the scripts won’t be included in the dotnet CLI publish command.

{
  "manifestVersion": 1,
  "deployments": {
    "aspNetCoreWeb": [
      {
        "name": "app",
        "scripts": {
          "postInstall": {
            "file": "SetupScripts/PostInstallSetup.ps1"
          }  
        }  
      }   
    ]
  }
}

What about ebextensions?

The Elastic Beanstalk ebextensions configuration files are still supported like all the other Elastic Beanstalk containers. To include them in an ASP.NET Core application, add the .ebextensions directory to the include section under publishOptions in the project.json file. For more information about ebextensions, check out the Elastic Beanstalk Developer Guide.

We hope this post gives you a better understanding of how deploying ASP.NET Core applications to Elastic Beanstalk works. In our next post, we’ll show you how to use the new deployment manifest file to deploy multiple applications to the same Elastic Beanstalk environment.

ASP.NET Core Support for Elastic Beanstalk

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

Today, we release support for deploying ASP.NET Core applications to AWS by using AWS Elastic Beanstalk (Elastic Beanstalk) and the AWS Toolkit for Visual Studio. This Elastic Beanstalk release expands the support the service already offers for deploying applications, including traditional ASP.NET applications, in a variety of languages to AWS.

Let’s walk through the deployment experience. The AWS Toolkit for Visual Studio is the easiest way to get started deploying ASP.NET Core applications to Elastic Beanstalk. If you have used the toolkit before to deploy traditional ASP.NET applications, you’ll find the experience for ASP.NET Core to be very similar.

If you’re new to the toolkit, after you install it, the first thing you need to do is register your AWS credentials with it.

In Visual Studio, from the Views menu, choose AWS Explorer.

Click the Add button to add your AWS credentials.

To deploy an ASP.NET Core web application, right-click the project in the Solution Explorer, and choose Publish to AWS.

On the Publish to AWS Elastic Beanstalk page, you’ll choose to create an Elastic Beanstalk application. This is a logical representation of your application that will contain a collection of application versions and environments. The environments contain the actual AWS resources that will run an application version. Every time you deploy an application that creates an application version and points the environment to that version.

Next, set names for the application and its first environment. Each environment will have a unique CNAME associated with it that you can use to access your application when the deployment is complete.

On the AWS Options page, you configure the type of AWS resources to use for your application. For this example, we can leave the default values except for the Key pair section. Key pairs allow you to retrieve the Windows Administrator password so you can log into the machine. If you haven’t already created a key pair, you can select Create new key pair.

On the Permissions page, you assign AWS credentials to the Amazon EC2 instances running your application. This is important if your application is using the AWS SDK for .NET to access other AWS services. If you’re not using any other services from your application, you can leave this page at its default.

The Application Options page is the one that differs from deploying traditional ASP.NET Core applications. Here, you can specify the build configuration and framework used to package the application and also what IIS resource path to configure for the application.

Once that’s finished, click Next to review the settings. Then, click Deploy to begin the deployment process. After the application is packaged and uploaded to AWS, you can check the status of the Elastic Beanstalk environment by opening the environment status view from AWS Explorer.

Events are displayed in Status as the environment comes online. When everything is complete, the environment status changes to Environment is healthy. You can click the URL to view the site. Also from this page, you can pull the logs from the environment or remote desktop into the EC2 instances that are part of your Elastic Beanstalk environment.

The first deployment will take a little more time as it creates new AWS resources. As you iterate over your application, you can quickly redeploy by going back through the wizard or selecting Republish when you right-click the project.

Republish will package your application using the settings from the last time through the deployment wizard, and then upload the application bundle to the existing Elastic Beanstalk environment.

We hope you’re excited to try out our expanded ASP.NET Core support in AWS. In our next post, we’ll dive deeper into how the deployment works and how you can customize it.

Exploring ASP.NET Core Part 2: Continuous Delivery

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

The first post in this series discussed how to use an Amazon EC2 instance and AWS CodeDeploy to deploy ASP.NET Core applications from GitHub. The setup assumed all git pushes to GitHub were deployed to the running environment without validation. In this post, let’s examine how we can create an AWS environment for our ASP.NET Core application that gives us quality control and takes advantage of AWS cloud scale.

You’ll find the code and setup scripts for this post in the part2 branch of the aws-blog-net-exploring-aspnet-core repository.

Validating the Deployment

In the first post, the appspec.yml file called the InstallApp.ps1 script during the ApplicationStart hook to extract the application and set up IIS. To verify the application is up and running, let’s update the appspec.yml file to call ValidateInstall.ps1 during the ValidateService hook.

version: 0.0
os: windows
files:
  - source: 
    destination: C:ExploringAspNetCore
hooks:
  ApplicationStop:
    - location: .RemoveApp.ps1
      timeout: 30
  ApplicationStart:
    - location: .InstallApp.ps1
      timeout: 300
  ValidateService:
    - location: .ValidateInstall.ps1
      timeout: 300

This script allows us to call tests to make sure our application is running correctly. In the GitHub repository, I added some xunit tests under .SampleAppsrcSmokeTests. My sample application is no more than a simple "Hello World" web application so I just need to test that I can make a web call to the application and get a valid response. In a real-world application you would have a much more exhaustive suite of tests to run during this validation step.

Let’s take a look at ValidateInstall.ps1 to see how the tests are run.

sl C:ExploringAspNetCoreSampleAppsrcSmokeTests

# Restore the nuget references
& "C:Program Filesdotnetdotnet.exe" restore

# Run the smoke tests
& "C:Program Filesdotnetdotnet.exe" test

exit $LastExitCode

To run the tests, switch to the directory where the tests are stored. Restore the dependencies, and then run the dotnet test command. The failure of any test will cause dnx to return a non 0 exit code, which we return from the PowerShell script. AWS CodeDeploy will see the failed exit code and mark the deployment as a failure. We can get logs from the test run from the AWS CodeDeploy console to see what failed.

Using AWS CodePipeline

Now that deployments are running smoke tests, we can detect bad deployments. In a similar way, we want to make sure users aren’t affected by bad deployments. The best practice is to use a pipeline with a beta stage during which we run smoke tests. We promote to production only if beta was successful. This gives us continuous delivery with safety checks. Again, as we discussed in part 1, we benefit from the ability of ASP.NET Core to run from source. It means we do not have to bother configuring a build step in our pipeline. Pipelines can pull source from Amazon S3 or GitHub. To provide a complete sample that can be set up with just a PowerShell script, we’ll use S3 as the source for our pipeline. AWS CodePipeline will monitor S3 for new versions of an object to push them through the pipeline. For information about configuring a GitHub repository, see the AWS CodePipeline User Guide.

Setup Script

The PowerShell script .EnvironmentSetupEnvironmentSetup.ps1 in the repository will create the AWS resources required to deploy the application through a pipeline.

Note: To avoid charges for unused resources, be sure to run .EnvironmentSetupEnvironmentTearDown.ps1 when you are done testing.

The setup script sets up the following resources:

  • An S3 bucket with a zip of the archive as the initial deployment source.
  • A t2.small EC2 instance for beta.
  • An Auto Scaling group with a load balancer using t2.medium instances.
  • An AWS CodeDeploy application for beta using the t2.small EC2 instance.
  • An AWS CodeDeploy application for production using the Auto Scaling group.
  • AWS CodePipeline with the S3 bucket as the source and the beta and production stages configured to use the AWS CodeDeploy applications.

When the script is complete, it will print out the public DNS for the beta EC2 instance and production load balancer. We can monitor pipeline progress in the AWS CodePipeline console to see if the deployment was successful for both stages.

The application was deployed to both environments because the smoke tests were successful during the AWS CodeDeploy deployments.

Failed Deployments

Let’s see what happens when a deployment fails. We’ll force a test failure by opening the .SampleAppsrcSmokeTestsWebsiteTests.cs test file and making a change that will cause the test to fail.

[Fact]
public async Task PassingTest()
{
    using (var client = new HttpClient())
    {
        var response = await client.GetStringAsync("http://localhost-not-a-real-host/");

        Assert.Equal("Exploring ASP.NET Core with AWS.", response);
    }
}

In the repository, we can run the .DeployToPipeline.ps1 script, which will zip the archive and upload it to the S3 location used by the pipeline. This will kick off a deployment to beta. (The deployment will fail because of the bad test.)

A deployment will not be attempted during the production stage because of the failure at beta. This keeps production in a healthy state. To see what went wrong, we can view the deployment logs in the AWS CodeDeploy console.

Conclusion

With AWS CodeDeploy and AWS CodePipeline, we can build out a full continuous delivery system for deploying ASP.NET Core applications. Be sure to check out the GitHub repository for the sample and setup scripts. In the next post in this series, we’ll explore ASP.NET Core cross-platform support.

Exploring ASP.NET Core Part 1: Deploying from GitHub

by Norm Johanson | on | in .NET | Permalink | Comments |  Share

ASP.NET Core, formally ASP.NET 5, is a platform that offers lots of possibilities for deploying .NET applications. This series of posts will explore options for deploying ASP.NET applications on AWS.

What Is ASP.NET Core?

ASP.NET Core is the new open-source, cross-platform, and modularized implementation of ASP.NET. It is currently under development, so expect future posts to cover updates and changes (for example, the new CLI).

Deploying from GitHub

The AWS CodeDeploy deployment service can be configured to trigger deployments from GitHub. Before ASP.NET Core, .NET applications had to be built before they were deployed. ASP.NET Core applications can be deployed and run from the source.

Sample Code and Setup Scripts

The code and setup scripts for this blog can be found in the aws-blog-net-exploring-aspnet-core repository in the part1 branch.

Setting Up AWS CodeDeploy

AWS CodeDeploy automates deployments to Amazon EC2 instances that you set up and configure as a deployment group. For more information, see the AWS CodeDeploy User Guide.

Although ASP.NET Core offers cross-platform support, in this post we are using instances running Microsoft Windows Server 2012 R2. The Windows EC2 instances must have IIS, .NET Core SDK and the Windows Server Hosting installed. The Windows Server Hosting, also called the ASP.NET Core Module, is required to enable IIS to communicate with the ASP.NET Core web server, Kestrel.

To set up the AWS CodeDeploy environment, you can run the .\EnvironmentSetup\EnvironmentSetup.ps1 PowerShell script in the GitHub repository. This script will create an AWS CloudFormation stack that will set up an EC2 instance and configure AWS CodeDeploy and IIS with the .NET Core SDK and Windows Server Hosting. It will then set up an AWS CodeDeploy application called ExploringAspNetCorePart1.

To avoid ongoing charges for AWS resources, after you are done with your testing, be sure to run the .\EnvironmentSetup\EnvironmentTearDown.ps1 PowerShell script.

GitHub and AWS CodeDeploy

You can use the AWS CodeDeploy console to connect your AWS CodeDeploy application to a GitHub repository. Then you can initiate deployments to the AWS CodeDeploy application by specifying the GitHub repository and commit ID. The AWS CodeDeploy team has written a blog post that describes how to configure the repository to automatically push a deployment to the AWS CodeDeploy application.

Deploying from Source

When you deploy from GitHub, the deployment bundle is a zip archive of the repository. In the root of the repository is an appspec.yml file that tells AWS CodeDeploy how to deploy our application. For our application, the appspec.yml is very simple:

version: 0.0
os: windows
files:
  - source: 
    destination: C:\ExploringAspNetCore
hooks:
  ApplicationStop:
    - location: .\RemoveApp.ps1
      timeout: 30
  ApplicationStart:
    - location: .\InstallApp.ps1
      timeout: 300

The file tells AWS CodeDeploy to extract the files from our repository to C:\ExploringAspNetCore and then run the PowerShell script, InstallApp.ps1, to start the application. The script has three parts. The first part restores all the dependencies for the application.

# Restore the nuget references
"C:Program Files\dotnet\dotnet.exe" restore

The second part packages the application for publishing.

# Publish application with all of its dependencies and runtime for IIS to use
"C:Program Files\dotnet\dotnet.exe" publish --configuration release -o c:\ExploringAspNetCore\publish --runtime active

The third part updates IIS to point to the publishing folder. The AWS CodeDeploy agent is a 32-bit application and runs PowerShell scripts with the 32-bit version of PowerShell. To access IIS with PowerShell, we need to use the 64-bit version. That’s why this section passes the script into the 64-bit version of powershell.exe.

C:\Windows\SysNative\WindowsPowerShell\v1.0\powershell.exe -Command {
             Import-Module WebAdministration
             Set-ItemProperty 'IIS:sitesDefault Web Site' 
                 -Name physicalPath -Value c:\ExploringAspNetCore\publish
}

Note: This line was formatted for readability. For the correct syntax, view the script in the repository.

If we have configured the GitHub repository to push deployments to AWS CodeDeploy, then after every push, the code change will be zipped up and sent to AWS CodeDeploy. Then AWS CodeDeploy will execute the appspec.yml and InstallApp.ps1 and the EC2 instance will be up-to-date with the latest code — no build step required.

Share Your Feedback

Check out the aws-blog-net-exploring-aspnet-core repository and let us know what you think. We’ll keep adding ideas to the repository. Feel free to open an issue to share your own ideas for deploying ASP.NET Core applications.