Native Application Development on AWS using .NET
Scott Baldwin
Principal Consultant
Scott Baldwin
Principal Consultant
A brief overview of the maturity and support for the .NET platform on AWS
When most people think about native application development on AWS, they often think of the usual suspects: NodeJS, Python, Java, or even Go. Still, not many people realise the amount of work and extensive support AWS has for Microsoft’s .NET platform. While, like other languages, .NET has a well-supported SDK that abstracts the AWS resource APIs, it also has dedicated teams building extensions and tooling to make developing native cloud applications on AWS in .NET a productive and enjoyable experience. In this post, I want to highlight a few of these projects and discuss how AWS is investing heavily in ensuring .NET on AWS is a good choice.
Lambda and Serverless
.NET Runtime Support
Little-known fact: AWS started offering .NET Core Lambda runtime support as early as December 2016, significantly before Azure Functions shipped with the same functionality. The support for running .NET on AWS Lambda has been improving ever since. AWS even created the .NET Lambda tool, which integrates into the .NET CLI. This tool offers a range of useful commands for working with serverless applications based on the AWS Serverless Application Model (SAM), as well as several blueprints for creating various types of serverless projects.
Templates like “serverless.AspNetCoreWebApp” create a .NET Web API/MVC Web App fronted by an API Gateway and hosted in Lambda, with the ability to run/debug locally or deploy to AWS using `dotnet lambda deploy-serverless` to deploy the SAM template. There are many more blueprints for different patterns, which you can view after installing them with
dotnet new -i "Amazon.Lambda.Templates:*"
by using thedotnet new list-author --aws
command
Power Tools
To add robustness to your lambda-based applications, AWS has a set of Power Tools for Lambda. This provides high-level abstractions for crucial aspects of developing serverless applications, such as logging, tracing, and metrics, as well as abstractions for handling challenging tasks like ensuring Idempotency or batch processing of SQS or streaming data. This talk at AWS re:Invent, Build production-ready serverless .NET apps with AWS Lambda (XNT301), dives deep into some of the benefits of using these Power Tools.
DynamoDB
DynamoDB is a NoSQL database used for low-latency (single-digit millisecond) access to data for OLTP applications. While the AWS .NET SDK provides low-level API access to DynamoDB (as do all supported SDKs), the .NET SDK adds two higher-level abstractions. The document model wraps some of the more repetitive and tedious work of interacting with DynamoDB API’s. The Object Persistence Model goes even further and allows you to use high-level C# constructs to define your data model and read and write it to DynamoDB. For example, you can specify a class and use attributes as shown in the code snippet below:
namespace orders.Models
{
[DynamoDBTable("orders")]
public class LineItem
{
[DynamoDBIgnore]
public string OrderId
{
get;
set;
} = string.Empty;
[DynamoDBHashKey("PK")]
public string PartitionKey
{
get => $ "O_{OrderId}";
set
{} // Setter needed for DynamoDB deserialization
}
[DynamoDBRangeKey("SK")]
public string SortKey
{
get;
set;
}
[DynamoDBProperty("product_name")]
public string ProductName
{
get;
set;
} = string.Empty;
[DynamoDBProperty("cost")]
public decimal Cost
{
get;
set;
}
[DynamoDBProperty("quantity")]
public int Quantity
{
get;
set;
}
[DynamoDBProperty("total")]
public decimal Total
{
get;
set;
}
private int _lineItemNumber;
[DynamoDBProperty("line_item_num")]
public int LineItemNumber
{
get => _lineItemNumber;
set
{
_lineItemNumber = value;
SortKey = $ "LI_{value}";
}
}
[DynamoDBProperty("order_id")]
public string LineItemOrderId
{
get => OrderId;
set => OrderId = value;
}
}
}
Reading all the LineItems then becomes as simple as creating a DynamoDBContext and querying it like so:
public async Task<List<LineItem>> GetOrderLineItemsAsync(string orderId)
{
var partitionKey = $ "O_{orderId}";
var queryConfig = new DynamoDBOperationConfig
{
QueryFilter = new List <ScanCondition>
{
new ScanCondition("SortKey", ScanOperator.BeginsWith, "LI_")
}
};
var search = _dynamoDBContext.QueryAsync<LineItem>(partitionKey, queryConfig);
return await search.GetRemainingAsync();
}
Similarly, the DynamoDBContext can be used to store your data like so:
public async Task SaveLineItemAsync(LineItem lineItem)
{
await _dynamoDBContext.SaveAsync(lineItem);
}
This eliminates much of the work involved in interacting with DynamoDB.
Modernisation
To truly leverage native application development on AWS, such as containers or Lambda, you need to be running the modern cross-platform version of .NET, rather than the legacy .NET Framework. Migrating from .NET Framework to .NET is not always a simple task, and the cost of doing so is often a blocker to organisations with legacy .NET Framework applications.
AWS recently released AWS Transform for .NET, which utilises an agent-based AI approach to facilitate modernisation efforts. This can speed up a modernisation project by up to four times. Once complete, you can then run your code on Linux and significantly reduce your hosting costs. While this isn’t the only thing required to modernize a legacy application for cloud-native development, it is a mandatory first step.
.NET Aspire
To simplify some of the more challenging aspects of developing distributed applications on .NET, Microsoft has introduced .NET Aspire. This enables developers to have a more fluid local development and debugging flow, thereby increasing productivity when building distributed applications. AWS is actively working on a set of integrations to support the .NET Aspire hosting model. Currently, this includes being able to generate cloud resources using CloudFormation or CDK, utilising DynamoDBLocal in place of a DynamoDB table, and they are working on adding a Lambda integration to support the local running and debugging of .NET Lambda functions.
Conclusion
When AWS released its CDK, C# was among the supported languages, meaning that your entire AWS project, including the infrastructure it runs on, can be written using C#.NET. Also, important to note that most of these projects are open-source and have a strong community around them. It’s safe to say that .NET is very well supported on the AWS platform, and AWS is investing heavily in making it a compelling choice for application development.
At Versent, we have digital engineers with deep experience in developing native cloud-based applications on .NET (as well as all the usual suspects). We have delivered many high-quality projects utilising the .NET tools that AWS provides.