0

Migration Strategy for .net framework applications to the cloud

This blog post summarizes various options available for migrating .net framework applications to Azure or AWS.

  • Approach 1:  Deploy existing .NET apps as Linux containers only
  • Approach 2: Deploy existing .NET apps as  Linux containers or EC2 or Azure VMs
  • Approach 3:  Deploy existing .NET apps as Windows containers only
  • Approach 4: Deploy existing .NET apps as  Native Cloud Services

Comparison of all approaches

Linux containers onlyLinux Containers and  EC2 or Azure VMsWindows Containers onlyNative Cloud services
Porting to .net coreRequiredRequired for Linux containers
Optional for EC2 or Azure VM-hosted apps.
Not requiredNot required
End-to-End Migration timeVery highHighLowMedium
Ease of migrationVery Complex(Application need to be  targeted to .net core and lot of code refactoring)Complex(Apps that cannot be containerized will be hosted on EC2)Easy(Supports Lift and Shift with some code refactoring)Moderate(Might require some code refactoring based on the adopted service)


High-level steps of migration: Applies to all the above approaches.

  • Step 1: Run portability analysis using the following tools, a better approach would be to use both options a and b for analysis to get the best of both tools.
  1. .NET Upgrade Assistant
    1. The .NET Portability Analyzer – .NET
  2. AWS Porting assistant for .net
    1. Porting Assistant for .NET – Amazon Web Services
  • Step 3: Identify functionalities that need to be refactored to work seamlessly on Cloud, following are some of the items to consider.
    • Session State: Applications should be stateless to scale/switch at will. Session state should be persisted outside the app using services like Redis Cache etc. Especially with containers that get dropped and recreated more often than less maintaining Session state is critical.
    • Logging: If the apps are logging to file systems locally, these apps need to be updated to log to the native logging service within AWS or Azure.
    • LDAP-Queries: If the apps are querying LDAP stores such as AD, these applications should use AWS Cognito or Azure AD.
    • Authentication: If the app relies on Windows Authentication or on-Premise AD this might require additional changes to the application.
    • File-Persistence: If the apps have uploading files that need to be persisted these files have to be persisted outside the app.
    • Miscellaneous:
      • On-Premise dependencies.
      • Email functionality.
      • Custom Domains
      • Apps using GAC (Global Assembly Cache)
  • Step 4: Fix the issues from Step 1, 2 and 3
  • Step 5: Containerize the app- Add supporting YAML configuration, make project changes, etc.
  • Step 6: Build, test locally and deploy.

Approach 1: Deploy existing .NET apps as Linux containers only

.NET Framework applications must run on Windows, porting these .NET Framework apps to Linux containers requires these apps to be re-targeted to the .NET core. This makes this approach the most time-consuming and complex among all of the approaches. 

Note: As of this writing, .Net 5 is the latest stable version that supports Linux containers. .NET 5.0 is the next major release of .NET Core following .NET core 3.1. 

Microsoft released .NET 5.0 instead of .NET Core 4.0 for two reasons:

  1. Skipped version numbers 4. x to avoid confusion with .NET Framework 4. x.
  2. Dropped “Core” from the name to emphasize that this is the main implementation of .NET going forward. .NET 5.0 supports more types of apps and more platforms than .NET Core or .NET Framework. [1]
  3. NET Framework 4.8, released in April 2019, is the last major version, “all future investment will be in .NET Core.”[2]

.Net 6 is still in Release candidate (RC) releases that provide early access to features and are feature complete. These releases are supported for production use since they have a go-live license.

Please find this white paper on what it takes to convert a simple .NET Framework to .NET Core to run on Linux containers.

Modernize .NET Applications with Linux Containers

Pros:

  • Upgrading to .Net 5 makes it easier for future upgrades.

Cons:

  • Requires a lot of changes to the project structure to retarget to the .NET 5 framework.
  • Porting Windows apps, .net libraries to .NET 5 can be relatively easy compared to ASP.NET Web applications.
  • ASP.NET web applications require quite a lot of code refactoring, changes to project structure, and how the configuration is read and written, as well as source code changes may be required for unresolved incompatibilities.
  • If there are no compatible NuGet packages for .NET 5, the application has to wait until a compatible NuGet package is released or find alternatives which can sometimes be tedious and time-consuming.
  • Any changes to the application require a deep understanding of the app and how it’s intended to function, this could be challenging for a team that is just responsible for migrations.
  • Applications well covered by unit tests are safer to port as there is a better chance of finding differences in behavior that may cause unexpected results.
  • Some of the features may not be supported in .net core, if the application uses any of these features, the application may have to be rewritten. Please see the complete list of .NET Framework technologies unavailable on .NET Core and .NET 5+

Following is just a sneak peek of  .NET Portability Analyzer in action, Micorosft has heavy documentation regarding the tool. Please see more at The .NET Portability Analyzer – .NET

Run the .NET Portability Analyzer.

The sample out of the Analyzer can be found at

The tool is available as a Visual Studio extension, following screen capture shows how to target .NET 5.0

After the extension has been installed, the Portability analysis can be performed as shown below.

Approach 2: Deploy existing .NET apps as  Linux containers or EC2 or Azure VMs:

This is similar to Approach 1 but accommodates all use cases. If there are any issues with porting to .NET Core or if an app cannot be containerized, in such cases these apps can be hosted within AWS EC2 or Azure VM instances. 

Approach 3: Deploy existing .NET apps as Windows containers only

A .NET Framework application must run on Windows, period. If existing .NET Framework applications have to be containerized, you can’t or don’t want to invest in migration to .NET Core or later (“If it works properly, don’t migrate it”), the only choice you have for containers is to use Windows Containers. [3]

Pros:

  • Aligns well with Rehost migration strategy, applications can be ported as Windows containers easily with very less turnaround time.
  • If there is no need for full-fledged Container orchestration Azure has low-cost managed services that support both Windows and Linux-based containers.
  • Applications can benefit from windows containers, as the main dependency for the .NET Framework in Windows. 
  • Also, applications having secondary dependencies, like IIS, and System.Web in traditional ASP.NET benefits from using Windows containers.

Cons:

  • Each application warrants changes to the project structure to support containerization.
  • Architecture and maintenance can get complex depending on the choice of container orchestration between managed vs. self-managed.
  • Code may need to be refactored if the functionality is compromised due to hosting it within a container.

Approach 4:  Deploy existing .NET apps as  Native Cloud Services

Microsoft introduced Cloud Adoption Framework that recommends how to migrate various applications to Azure. A good strategy should include multiple migration/design choices catering to the application needs with the least amount of migration time and modifications to the applications. 

Please see the flowcharts below to get a high-level understanding of Microsoft’s recommendation of migrating applications and their supporting data sources within Azure.

Flow chart to select a candidate to compute service.

Read more at Choosing an Azure compute service – Azure Architecture Center

Flow chart to select a candidate data service.

Read more at Review your data options – Cloud Adoption Framework

Note: This section covers Azure services only, a similar flowchart can be devised for AWS as well. It’s important to establish a clear plan and scope upfront for all the applications, the team should not come to the drawing board for each application.

Pros:

  • More flexible due to more services/design choices and eventually reduces the overall migration cost and time.
  • Accommodates all the acceptable migration strategies
    • Rehost – Lift and shift as-is with no changes to applications.
    • Refactor/Repackage – With a few code changes and refactoring
    • Rearchitect
    • Rebuild

References:

  1. What’s new in .NET 5
  2. Microsoft .NET Framework – Microsoft Lifecycle
  3. Deploy existing .NET apps as Windows containers
  4. NuGetPackageExplorer/NuGetPackageExplorer: Create, update and deploy Nuget Packages with a GUI

0

Error: An error occurred while receiving the HTTP response

We have an Azure AppService that communicates with web services that are hosted on-premise via a Site-to-Site VPN. We are using a HUB and SPOKE model for the Site-to-Site VPN set up and this web app integrates with one of the subnets that is part of SPOKE VNet. We have gotten the following exception while performing end-to-end testing. Hope this blog helps you save some research time. Good luck!

Exception:

An error occurred while receiving the HTTP response to https://yourwebserviceURL. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive.

Inner exception:

System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)at System.Net.TlsStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)

Solution:

You might find a lot of solutions online suggesting to update the web.config, edit the binding etc. none of them worked for me. By default, Azure app routes only RFC1918 traffic into your VNet. If you want to route all of your outbound traffic into your VNet, use the following steps to add the WEBSITE_VNET_ROUTE_ALL setting in your app:

WEBSITE_VNET_ROUTE_ALL = 1

References:

https://docs.microsoft.com/en-us/azure/app-service/web-sites-integrate-with-vnet

3

Cloud Applications development – It’s NOT all about VMs

Cloud platforms have plethora of options and they come in many flavors. Be it Microsoft Azure, Rackspace, AWS, Oracle or any cloud platform of your choice, all of these are unique and are irreplaceable. But they all share one common offering i.e. Infrastructure as Service (IaaS) and Platform as a Service (PaaS). IaaS is the most basic and widely adapted cloud offering. PaaS is gaining popularity and would be the default choice in near future, but not at the time of writing this blog.

So if you are Cloud Applications developer, it is key that you understand what IaaS/PaaS is and things to bear in mind while developing applications for cloud platforms.

If you assumed that Cloud or Cloud Computing is nothing but a mere collection of millions and millions of VMs/servers remotely hosted and maintained by someone else. Also deployment is all about copying and pasting your code on to those servers! I am afraid you are wrong!

Developing cloud applications is not just mere copy and paste, there is much more to that.

This post will cover few examples that would influence your thought process while developing applications for cloud. Again, there are many more, many more things to consider while developing apps for Cloud platforms.

The following is an honest attempt to influence you to adopt different prospective while you design Cloud apps.

  1. Automation of  Deployments and Hardware Provisioning
    1. There are high chance that you may not have been concerned about hardware provisioning with traditional development. But with cloud application development, it is key that you are aware of automation all your hardware provisioning and deployments.You could leverage Windows Azure Object Model that helps automate lot of  things that are typical with Cloud application development like creation of VMs, Websites, Storage Accounts etc.
    2.  You my leverage C#, PowerShell scripts or popular tools like Chef , Puppet for IT/Deployment automation.
    3. Automation is one of the key design principles of Cloud application development and highly recommended by Microsoft. This will not only minimize errors but also makes it easier to create and deploy items repeatedly.
    4. Example: Consider a scenario where you were requested to create a developer VMs for 20 developers with with Windows Server 2012 R2, SQL Sever R2, IIS 8.0, Sharepoint 2010, MS office and other supporting tools.
      1. What is the first thought you get? I am sure you are tempted to create 20 VMs on Azure portal, RDP onto these machines and install these software. I bet even if you spend like 2 to 3 hours for each VM it would take 60 hours i.e. close to two business weeks.
      2. You might have also thought that, I would create one instance, generalize it and create the rest out of it correct? Note that some software cannot be part of generalization of VM and therefore cannot part of template
      3. Solution: Use scripts or any kind of automation of your choice.
        Write a script to create and spin up these 20 VMs. This can be easily done using Power Shell scripts often with few lines of code.  This could hardly take an hour or two.
        The other issue with software that doesn’t support generalization or bundling with VM images/templates, you could read Bootstrapping a Virtual Machine with Windows Azure, by Michael Washam.
  2.  Budgeting and Cost Conscious
    1. As a traditional developer cost is not something you would consider while developing. But when you are designing for Cloud apps everything come with a price. For instance, your design choice storing your data in-memory vs. database can have huge impact on pricing.
    2. Based on your application design choice you my end up saving a ton or pay the price for not having cost as as important parameter
    3. Cost calculation is as important as application design, development and testing. This should be an integral part of design.
  3. Fluid/Adaptive design choices
    1. The beauty of cloud platforms is you can start with minimal configuration and grow as needed. So your design should be flexible to adapt to changing hardware, it could be reduced CPU utilization or memory allocations or additional servers added to the NLB, it could be anything.
    2. You design choices are critical for Cloud development. For instance, for Session management, you have to prefer Outproc session management to Inproc while using ‘Swap Deployment‘ feature with Azure.What it means is that virtual IPs swap between the staging and production environments for a service. If the service is currently running in the staging environment, it will be swapped to the production. If it is running in the production environment, it will be swapped to staging.So if  are leveraging Inproc session management, you would loose your state, it id ideal that you choose Outproc session management.Please see the below screen capture highlighting ‘Swap’ feature under instances.

      Swap Deployment with Microsoft Azure

      Swap Deployment with Microsoft Azure

       

  4. High availability, Performance and Fault Tolerance
    1. Most of the Cloud providers will have an SLA of 99.5 and above for availability. This is valid only if you provision at least two instance for every service. Developers should be aware of this.
      1. If you choose only one instance, your application may be temporarily unavailable while patching or reboots.
    2. Another important feature that every developer should understand is Affinity Groups.These allow to group your Azure services to optimize performance. All services and VMs within an affinity group will be located in the same region. For instance, it is ideal that you may associate your application and supporting database servers to the same Affinity group to avoid any network latency and increase performance.

Conclusion: It is key to understand that developing Cloud based application development is not same as traditional development. You should start with leaving aside our ego and stop acting that developing for Cloud Platforms, is no different to traditional development. And stop thinking developing for Cloud platforms is all about logging on to a VM, copy-paste, deploy and configure. As a matter of fact, I was under the same impression and attitude when started picking up Azure. Its time to digest the notion that Cloud application development has lot more different in terms of design, development and cost AND IS NOT ALL ABOUT VMs.