A Strategic Roadmap for a Distributed Workforce
About This Document
Curious about using ChatGPT to migrate your code? The Programmer’s Guide to Using ChatGPT to Migrate Code takes you through the process of transforming a VB.NET WinForms application into a modern C#/Blazor web app. This guide highlights the successes and challenges faced, the benefits of using ChatGPT, and crucial tips for a successful migration. Understand how AI tools can aid in modernizing your applications while collaborating with developers to achieve the best results.
Full Content Below
Read the Full Document
Explore the complete publication below
We’ve all asked ourselves the same question: can generative AI migrate an old legacy application? The answer is “yes,” but there are a lot of caveats.
In this post, we’ll share our experiences and learnings from using ChatGPT 4.0 to migrate a legacy VB.NET Winforms application to a modern C#/Blazor web application. The project aimed to use the power of generative AI’s natural language processing and code generation capabilities to streamline the migration process.

Tech Specs
The source application was a .NET 4.8/Entity Framework 6.4.4 VB.NET WinForms app developed in Visual Studio 2022. The target application was .NET 8/Entity Framework Core 8.0.2 C#/Blazor Server web app, also in VS2022.
What We Learned
Form Mapping and Understanding
Translating VB.NET WinForms to a Blazor web app required more than just code conversion. It involved understanding the structure, features and complexities of the source application, defining the scope of the migration and planning the architecture of the target Blazor application.
Migration Approach
We approached the migration in these phases:
- Analyzing and planning
- Setting up the Blazor project
- Migrating business logic
- Developing the UI with Blazor components
- Handling data access and state management
- Implementing authentication and authorization
- Testing and deployment
- Training and documentation
Factoring the Application
The VB.NET application lacked proper separation of concerns, with business logic and data access mixed in the UI layer. For an effective migration, it was crucial to refactor the application into distinct layers – UI, business logic and data access.
Iterative Migration and Learning Curve
The migration was an iterative process, requiring frequent adjustments and learning. As we gained more understanding of Blazor and .NET 8, the code generated by ChatGPT needed to be fine-tuned. The learning curve involved adapting to new concepts and best practices in C#, Blazor and Entity Framework Core.
Areas Where ChatGPT Exceeded Expectations
Code Translation:
ChatGPT (and generative AI in general) demonstrated impressive capabilities in translating VB.NET code to C#, handling complex constructs and providing syntactically correct code. Here are a few examples:
Business Logic Migration
Before (VB.NET):
Public Function Login(userid As String, password As String) As AccountCurrent
Dim theAccount As New AccountCurrent
theAccount.UserID = userid
Using accountcontext As New ACCOUNTDBEntities()
Dim parameter = New SqlParameter("@userId", userid)
Dim result = accountcontext.ACCOUNTPROFILEs.SqlQuery("SELECT * FROM
dbo.ACCOUNTPROFILE WHERE USERID = @userId", parameter)
For Each profile In result
theAccount.UserID = profile.USERID
theAccount.Password = profile.PASSWORD
theAccount.AccountID = profile.ACCOUNTID
theAccount.Salt = profile.SALT
theAccount.Name = profile.FULLNAME
Next
If theAccount.Password Is Nothing Then
GlobalSettings.LoggedIn = False
Else
Dim ver = New SaltedHash().Create(theAccount.Salt,
theAccount.Password)
GlobalSettings.LoggedIn = ver.Verify(password)
End If
End Using
Return theAccount
End Function
After (C#)
public async Task<AccountCurrent> LoginAsync(string userId, string password)
{
var theAccount = new AccountCurrent();
using (var accountContext = new ACCOUNTDBEntities())
{
var parameter = new SqlParameter("@userId", userId);
var accountProfiles = await accountContext.ACCOUNTPROFILEs
.FromSqlRaw("SELECT * FROM dbo.ACCOUNTPROFILE WHERE USERID = @userId", parameter)
.ToListAsync();
foreach (var profile in accountProfiles)
{
theAccount.UserID = profile.UserId;
theAccount.Password = profile.Password;
theAccount.AccountID = profile.AccountId;
theAccount.Salt = profile.Salt;
theAccount.Name = profile.FullName;
}
if (theAccount.Password == null)
{
GlobalSettings.LoggedIn = false;
}
else
{
var verifier = SaltedHash.Create(theAccount.Salt, theAccount.Password);
GlobalSettings.LoggedIn = verifier.Verify(password);
}
}
return theAccount;
}
UI Migration
Before (VB.NET)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GlobalSettings.LoggedIn = False
End Sub
Private Sub Label3_Click(sender As Object, e As EventArgs) Handles Label3.Click
Form1.Show()
End Sub
Private Sub Label2_Click(sender As Object, e As EventArgs) Handles Label2.Click
If GlobalSettings.LoggedIn Then
MsgBox("You are now Logged Out!")
GlobalSettings.LoggedIn = False
Login.PasswordTextBox.Text =""
Login.UserIDTextBox.Text =""
Else
Login.Show()
End If
End Sub
After (Blazor):
@page "/"
@inject NavigationManager NavigationManager
@inject IAuthenticationService AuthenticationService
<h3>Welcome</h3>
@if (!AuthenticationService.IsLoggedIn)
{
<p>Please log in to continue.</p>
}
else
{
<div>
<button @onclick="NavigateToForm1">Go to Form 1</button>
<button @onclick="ToggleLogin">Toggle Login</button>
<button @onclick="NavigateToHoldings">Holdings</button>
<button @onclick="NavigateToAccountForm">Account</button>
</div>
}
@code {
private void NavigateToForm1()
{
NavigationManager.NavigateTo("/form1");
}
private void ToggleLogin()
{
if (AuthenticationService.IsLoggedIn)
{
AuthenticationService.Logout();
}
else
{
NavigationManager.NavigateTo("/login");
}
}
private void NavigateToHoldings()
{
if (AuthenticationService.IsLoggedIn)
{
NavigationManager.NavigateTo("/holdings");
}
else
{
// Show a message or modal indicating the need to log in
}
}
private void NavigateToAccountForm()
{
if (AuthenticationService.IsLoggedIn)
{
NavigationManager.NavigateTo("/account");
}
else
{
// Show a message or modal indicating the need to log in
}
}
}
These examples show how ChatGPT translated the code from VB.NET to C#, handling differences in syntax, control flow and UI paradigms.
Best Practices:
- Identifying best practices: ChatGPT often suggested best practices and modern approaches, such as using async/await, dependency injection and separating concerns, even when the source code didn’t follow these patterns.
- Providing explanations: Along with generating code, ChatGPT offered clear explanations and reasoning behind its suggestions, helping us understand the rationale and learn new concepts.
- Handling different target platforms: ChatGPT was able to generate code targeting different platforms including Node.js/Angular, showcasing its versatility.
- Database class generation: Effective creation of database models from DDL.
- Debugging support: Played a significant role in resolving code issues.
Limitations of Generative AI
While ChatGPT was helpful in generating code snippets and providing guidance, it had limitations. The generated code often needed manual adjustments to align with the latest .NET versions and Blazor best practices.
Here are a few examples we encountered:
Entity Framework Core Usage:
ChatGPT generated the following code for querying the database using Entity Framework Core:
var result = _accountContext.ACCOUNTPROFILEs.SqlQuery("SELECT * FROM dbo.ACCOUNTPROFILE WHERE USERID = @userId", parameter);
However, this code uses the SqlQuery method, which is not available in Entity Framework Core. The code needed to be manually adjusted to use the FromSqlRaw method instead:
var accountProfiles = _accountContext.ACCOUNTPROFILEs
.FromSqlRaw("SELECT * FROM dbo.ACCOUNTPROFILE WHERE USERID = @userId", parameter)
.ToList();
Asynchronous Code:
ChatGPT sometimes generated synchronous code, even when as