AWS Open Source Blog
Open sourcing the Porting Assistant for .NET
In July 2020, AWS launched the Porting Assistant for .NET, a tool for analyzing the compatibility of .NET Framework applications and estimating the effort required to port them to .NET Core. Porting applications to .NET Core enables you to take advantage of future investments in .NET, reduced license spend, and innovations to improve application scaling and performance on Linux.
The Porting Assistant for .NET analyzes NuGet package dependencies and API usage in .NET Framework applications at the solution level. With the compatibility and porting effort assessed, the assistant further helps in the porting process by removing the manual effort needed to convert project files to the new .NET Core format, including the upgrading of NuGet packages when compatible replacements exist. The Porting Assistant for .NET is free of charge and you can read more about the tool in the original launch announcement blog post. A video walking through the features of the assistant can also be viewed on YouTube.
We’ve been encouraged by positive feedback from our customers and the .NET community on the savings in time and effort when porting that are resulting from using the assistant. Kloia, an Amazon Partner Network partner, ported the EposNow Point-of-Sale (POS) application to .NET Core:
“The application was a multi-layered and comprehensive API with more than 20 projects bundled into one single solution. With Porting Assistant, the entire compatibility assessment and effort estimation, which would normally take several days was completed within a few hours. Also, during the porting stage, the tool made recommendations that reduced the manual effort significantly.”
You can read more about Kloia’s experience using the assistant in this blog post.
What are we open sourcing today?
With the original launch, we open sourced the data sets used to determine compatibility. Today, we’re excited to open source the source code and compatibility analysis components of the assistant. We recognize that porting .NET Framework applications to .NET Core is a broad problem space and we want to encourage community users to share and use the growing knowledge base around best practices in porting .NET applications via recommendations. And, although we continue expanding the data sets used for assessment, we also want to invite community members to actively collaborate further. Users are encouraged to participate through open issues in GitHub, review, comment, ask questions, offer suggestions, or open new issues if you’d like to start a new conversation. We also welcome your participation in contributing new recommendations to the data sets, and review and offer suggestions on existing data sets.
With today’s open source launch, we also encourage community members, including our solution partners, to add extensions to the Porting Assistant for .NET to best address their customer needs. Along with the source code projects noted below, we are publishing a proposed roadmap for the project, giving community participants the opportunity to comment on and influence the future of the assistant. The roadmap will continue to be updated by incorporating community-offered feature requests, issues raised, and more.
Adding to the original model data sets, two new repositories for the code analysis and back-end assessment APIs make up the core functionality of the assistant. These are the current repositories, all released under the Apache 2.0 license:
- Porting Assistant for .NET client: Contains the back-end assessment APIs and project porting code, making it easy to interface with the assistant from your own code.
- Codelyzer: Contains the source code analyzer used by the assessment APIs.
- Porting Assistant for .NET Datastore: The original repository containing the data sets used in compatibility assessment. As part of today’s release, we also added a Recommendations folder enabling contributions to the NuGet and API replacement data.
Extending the Porting Assistant for .NET
The README files in the repositories show examples of how to use the assistant’s various components. For example, perhaps you are interested in contributing to the recommendations. If so, take a look at the recommendation folder in the data store repository. This folder contains a series of JSON-formatted files, one for each package in nuget.org. At time of writing this post, the recommendation files represent compatibility data on 211K unique packages and 2.5 million package versions. For each package, the file captures compatibility information for all of the package’s versions.
The file format is described in the repository’s RECOMMENDATIONS.md file. Here’s an example of a recommendation that is used when the assistant encounters use of System.Data.SqlClient
in a source code file. The top of the recommendation states the package and namespace (the type is used to group recommendations together):
"Name": "System.Data.SqlClient",
"Version": "1.0.0",
"Packages": [
{
"Name": "System.Data",
"Type": "SDK"
}
],
The Recommendations
section that follows informs the assistant of what to look for in the source code; below, the sample shows we are looking for use of the System.Data.SqlClient
namespace:
"Type": "Namespace",
"Value": "System.Data.SqlClient",
The Description
field summarizes the steps required to migrate to .NET Core. For this recommendation, there are three steps. Add a package reference to Microsoft.Data.SqlClient
, then remove all using statements for System.Data.SqlClient
, and finally, add a using statement for Microsoft.Data.SqlClient
:
"Description": "Add reference to Microsoft.Data.SqlClient\r\nAdd Microsoft.Data.SqlClient namespace\r\n Remove System.Data.SqlClient namespace\r\n"
The complete recommendation is shown below:
{
"Name": "System.Data.SqlClient",
"Version": "1.0.0",
"Packages": [
{
"Name": "System.Data",
"Type": "SDK"
}
],
"Recommendations": [
{
"Type": "Namespace",
"Value": "System.Data.SqlClient",
"RecommendedActions": [
{
"Source": "OpenSource",
"TargetFrameworks": [
"netcoreapp3.1"
],
"Description": "Add reference to Microsoft.Data.SqlClient\r\nAdd Microsoft.Data.SqlClient namespace\r\n Remove System.Data.SqlClient namespace\r\n",
}
]
}
]
}
Maybe instead you are interested in extending the analysis of .NET Framework application compatibility for .NET Core. For this, take a look at the Roslyn-based code analyzer in the new Codelyzer repository. The processor in this project walks an abstract syntax tree (AST) to collect metadata on the source file components making up your application–its solution file, project files, namespaces, classes, methods, method invocations, and literal expressions, etc. The code analyzer is a framework designed to support analysis of application source code in different languages, although currently only support for .NET languages (C#, Visual Basic) is implemented. As shown in the repository’s README file, constructing and running an analyzer against an application’s solution file is easy:
// 1. Create logger object
var loggerFactory = LoggerFactory.Create(builder =>
builder.SetMinimumLevel(LogLevel.Debug).AddConsole());
var logger = loggerFactory.CreateLogger("Analyzer");
var outputPath = @"/home/users/steve/porting-analysis";
// 2. Create Configuration settings
var configuration = new AnalyzerConfiguration(LanguageOptions.CSharp);
configuration.ExportSettings.OutputPath = outputPath;
// 3. Get Analyzer instance based on language
var analyzer = CodeAnalyzerFactory.GetAnalyzer(configuration, logger);
// 4. Analyze the project or solution
var projectFilePath = @"/home/users/steve/projects/TestProject.csproj";
var analyzerResult = await analyzer.AnalyzeProject(projectFilePath);
Console.WriteLine("The results are exported to file : " + analyzerResult.OutputJsonFilePath);
The output from the analyzer can be either a results object or, as requested in the code sample above, a JSON-format file. In either case, the results detail the entities discovered in the source code tree, their name and type (namespace, method, property, etc.), and the character location and span of the discovered entity in the relevant source file, amongst other data. An example of the output can be found in the README along with the preceding code sample.
The analysis output is consumed by the projects contained in the client repository, starting with the PortingAssistant.Client.Analysis project. The client application uses the data sets in the datastore repository to determine the compatibility of the application with .NET Core. It does this by checking consumed NuGet packages (public and private) and API calls made by the application against the models to determine whether the package or API call has a .NET Core equivalent. In the video I linked to previously, you can see a walk through of the various compatibility reports that the assistant provides.
The Porting Assistant for .NET benefits from multiple open source projects and contributions, and we appreciate their support and contribution in helping us deliver this tool. A list of projects and contributors to the Porting Assistant for .NET can be found on GitHub.
Moving forward
We’re excited about the Porting Assistant for .NET, and the positive reaction to it from the .NET community. As noted, we will be maintaining a roadmap in the repositories. Ideas for the future direction of the assistant include IDE integrations, a command-line interface, and improved support for scanning source code repositories (public and private). We recognize that the scope of porting .NET applications is broad enough that a community-based approach to tackling it is needed, so we plan on continuing to work on extensibility—for example, adding the capability for users to add additional logic to extend the analysis. The team welcomes feedback and contributions in all those areas, and more, and looks forward to collaborating further with the community in the Porting Assistant for .NET client, Codelyzer, and Porting Assistant for .NET Datastore repositories.