The Modern .NET Show

S07E19 - .NET Web App Modernization Made Easy with Tomáš Herceg's New Book and DotVVM

Sponsors

Support for this episode of The Modern .NET Show comes from the following sponsors. Please take a moment to learn more about their products and services:

Please also see the full sponsor message(s) in the episode transcription for more details of their products and services, and offers exclusive to listeners of The Modern .NET Show.

Thank you to the sponsors for supporting the show.

Embedded Player

S07E19 - .NET Web App Modernization Made Easy with Tomáš Herceg’s New Book and DotVVM
The Modern .NET Show

S07E19 - .NET Web App Modernization Made Easy with Tomáš Herceg's New Book and DotVVM

Supporting The Show

If this episode was interesting or useful to you, please consider supporting the show with one of the above options.

Episode Summary

Tomáš Herceg’s new book, Modernizing .NET Web Applications, focuses on the process of modernizing legacy .NET web applications to take advantage of newer technologies such as ASP.NET Core. Tomáš discussed his book in an interview, sharing insights and expertise gained from years of experience with .NET web development.

One key takeaway from the conversation was the importance of incremental modernization when migrating a legacy application to a new technology stack. Tomáš recommended starting with small, trivial tasks and gradually increasing complexity as confidence grows. This approach can help teams navigate the challenges of modernizing an existing application while minimizing disruptions to users.

Tomáš also discussed his DotVVM framework, which allows developers to build ASP.NET Core applications using HTML and C# without requiring extensive JavaScript knowledge. The framework leverages Model-View-ViewModel (MVVM) pattern and is designed to simplify development and improve maintainability. According to Tomáš, DotVVM can help bridge the gap between .NET Framework and newer technologies like Blazor.

Throughout the conversation, Tomáš emphasized the value of his book in providing practical guidance for developers working on modernizing .NET web applications. He highlighted key areas such as authentication, configuration, logging, and infrastructure changes that require attention during the migration process.

The interview concluded with a discussion on how to get in touch with Tomáš and access his book and DotVVM framework. Tomáš kindly recommended LinkedIn as a preferred platform for reaching out, while also providing URLs for his book and DotVVM website. The conversation was informative, engaging, and provided valuable insights into modernizing .NET web applications and leveraging the DotVVM framework.

Episode Transcription

I remember I had the entire life cycle of the web forms printed on a wall. It was like six sheets of paper and it was very complex, and it was very useful to have it on the wall because, like, you could always look at it and say, “okay, this is going on before this one.” So you have to like switch the order of things. But that’s exactly what I call interesting.

- Tomáš Herceg

Welcome friends to The Modern .NET Show; the premier .NET podcast, focusing entirely on the knowledge, tools, and frameworks that all .NET developers should have in their toolbox. We are the go-to podcast for .NET developers worldwide, and I am your host: Jamie “GaProgMan” Taylor.

In this episode, we talk with Tomáš Herceg about strategies for modernizing .NET Framework web applications such that they leverage the very latest in the .NET stack. Tomáš shares his insights from the journey of upgrading his own applications and those of his clients, both of which provided the background for his new book: “Modernizing .NET Web Applications”.

The biggest problem of the YARP migrations: that they will force you to do a lot of infrastructure things at the beginning before you even start migrating some real functionality.

- Tomáš Herceg

Along the way, we discuss how using his DotVVM project can help with the migration. Not only is the upgrade path for DotVVM projects a process of swapping a NuGet package, but is also keeps the upgrade as a single in-memory process—something that YARP-based migrations aren’t able to do.

Anyway, without further ado, let’s sit back, open up a terminal, type in dotnet new podcast and we’ll dive into the core of Modern .NET.

Jamie : [0:00] So Tomáš, welcome to the show. I really appreciate everyone who takes time to be here and talk to me and the listeners about all things .NET. So thank you for taking some time out. I usually tell people that are listening roughly what time it is, but I realize that people listen to podcasts ad hoc. So it really doesn’t matter what time of day is that we’re recording, except, you know, to our clients, we’re not recording during work time, folks.

Tomáš : [0:30] Yeah so thanks for having me.

Jamie : [0:32] Excellent.

Jamie : [0:34] No it really is great to have you on the show. Especially with the topic we’re going to talk about, because I feel like it’s something that a lot of folks either have already started doing or will start doing, perhaps when .NET 10 drops and we get the long-term support version of that.

Jamie : [0:53] There is a really interesting point about that but I’ll bring that up later in the episode quick spoiler alert folks: I am going to ask the audience what STS stands for in the context of the .NET life cycle . Without looking it up, I’d love you to, maybe not shout at your phone right now because people will think that’s a bit strange; shouting words at your phone. But have a think about what you think STS stands for and we’ll talk about it in this episode. So with with respect to the .NET life cycle, what does STS stand for? We all know what that LTS stands for long term, but what does STS stand for? So I’ll leave you all with that whilst we get on with the show. We’ll come back to that later.

Jamie : [1:34] So Tomáš, we’ve kind of briefly intro’d you and said you’re going to be on the show, we’re going to talk about the topic later on, I was just wondering would you mind giving the folks who are listening a little bit of like a brief bio about you? Like maybe the kind of the work you do? I know we’ve got the book that we’re going to talk about, maybe talk about the book that kind of thing?

Tomáš : [1:54] Yeah sure. So hello everyone my name is Tomáš. I’m from the Czech Republic, from Prague. And I do quite a lot of things. I’m a Microsoft MVP for 16 years, so it’s quite a long time. I’m running a small consulting company with about 40 people. We built any kind of software, provided it’s on .NET for our clients. I’m also maintaining an open source framework called DotVVM. And recently, last year, I spent a lot of evenings and a lot of weekends by writing a book about modernizing .NET web applications. So that’s probably what we will be talking about today.

Jamie : [2:44] Excellent, excellent. So I wonder, before we talk about the book and the topic of modernizing .NET web apps, which, spoiler alert: that’s what we’re going to talk about, could you talk about DotVVM as well?

Tomáš : [2:55] So yeah, like DotVVM is a framework we started in 2014, at the time of .NET Framework because we weren’t very satisfied with how web apps are written in ASP .NET WebForms. It was quite dated at that time. So we wanted–me and my colleagues–we wanted something more simple to build rich interactive apps. And basically that’s how they started. And it’s actually one that does, that was the thing that led me to doing the modernization later because the framework was built on .NET Framework. And a year after that .NET Core came out. So like, we wanted to like port this project to support .NET Core. And it showed us as a migration path to .NET Core because it’s a library that supports basically both versions of ASP.NET.

Jamie : [4:00] Oh, interesting, interesting. I do like that you all were thinking about how do we build web apps in the time of ASP .NET WebForms because I feel like I felt a collective wave of nostalgia then from everyone who will be listening, which for us is in the future, for them is in the present and the past. For those of us who are long enough in the tooth to remember web forms that was an interesting experience.

Tomáš : [4:30] Yeah interesting is the correct word for that, because I still have very mixed feelings about this technology. Because on one hand a lot of things were really simple to create, like I could make a lot of pages in a single afternoon and like everything worked. But from the long-term perspective from the user experience and the customers, they get like more demanding after year after year. So then like it didn’t work quite well in the later years. And we were considering migrating to some like JavaScript framework like React or Angular JS at the time. Then there were new versions of that. But the experience of writing JavaScript in 2014, it also wasn’t very, it was also interesting, I would say. So that’s why we basically, our motivation was to build a framework that would be just C# and HTML. But it would somehow generate the JavaScript part that makes the web page interactive. So like when you click on a button you don’t have to reload the entire page, it would just update some things in the page dynamically with JavaScript.

Tomáš : [5:50] But the idea was that the developer would not have to write it. So that’s how this framework was created. If it reminds you Blazor, like yeah that’s the same thing we are not using web assembly but like the objective, like write interactive web apps without, writing javascript it’s basically the same.

Jamie : [6:12] You know the thing that I remember about web forms, and this is probably the bit that’s going to give people the heebie-jeebies I guess, is the post-back, the pre-post-back, the post-post-back and all those different events you could create right?

Tomáš : [6:27] Yeah, the life cycle. I remember I had the entire life cycle of the web forms printed on a wall. It was like six sheets of paper and it was very complex, and it was very useful to have it on the wall because, like, you could always look at it and say, “okay, this is going on before this one.” So you have to like switch the order of things. But that’s exactly what I call interesting.

Jamie : [6:58] Oh absolutely, absolutely. We are so spoiled now with what we have with ASP .NET Core. If folks are able to use that, especially with like Minimal API. I love minimal Minimal API, so good, Yeah a lot of people think minimal means minimal feature set, but it is actually just minimal code required from you to actually get it running. Which is just so good, none of this crazy amount of life cycle stuff. Like I never printed off the full life cycle. I just remembered post-back, pre-post-back, and post-post-back because those are the only two that i needed… the only three that I needed. That’s how bad it is: I can’t even count them.

Tomáš : [7:39] Yeah, yeah. Exactly. And the Minimal APIs are really great because it’s very straightforward like when you exactly see what it’s doing there is no hidden magic behind that, or there is maybe some kind of magic hidden behind, but like you don’t have to really think about that. In web forms you had to understand what’s going underneath.

Jamie : [8:01] Yep yep. I am more than happy with taking some of the code away, and maybe doing the source generators or whatever wizardry they are doing. I’m happy with that; you deal with the complexity, I’ll just build the app. Yeah. Okay, so you were saying there about you initially were looking into maybe porting it to one of the JavaScript frameworks and libraries before settling on, “no, actually, let’s move this over to modern .NET,” and how that sort of gave you the background information for the book, right?

Tomáš : [8:40] Yeah. Basically in my company we started building projects using this new framework, and in 2014-2015, and as you remember probably first few versions of .NET Core they were missing quite a lot of features. So like if you wanted to build a huge enterprise app, and then like try to use EF Core like it was missing a lot of things that came in the later versions. So like until .NET Core 3.1, we were still using .NET Framework, and then we made it to the point that we needed to migrate these applications. And because this UI framework we built supports .NET Framework and .NET Core, the migration was just about some tiny things in the code. In the C# code, and we didn’t have to redo the front-end parts. We barely had to touch them.

Tomáš : [9:42] So that was quite eye-opening moment for me because I realized that having a library that supports the old world and the new world, it’s a huge benefit for the modernization. And if you look at MVC, the MVC is present on ASP .NET Core, but there are quite a lot of tiny differences and the same is like with ASP.NET web pages. Now we have Razor pages. Again, like the principle behind these technologies is the same, but like there are a lot of syntax differences, a lot of things you need to edit in your code. So having a front-end library that is exactly the same, it can save quite a lot of effort.

Jamie : [10:32] Right. And so if folks were using DotVVM previously on, say, a .NET Framework application. If they manage to, let’s just, let’s talk 10,000-foot view, right? We’re not talking about low-level implementation details. Just imagine a world where I can wave a magic wand and I swap my .NET Framework ASP.NET WebPages app over to something with a modern .NET underneath it, but I’m still using DotVVM. Is that transition super easy, the DotVVM part? Like because you said it works with both right, so is that a case of it just continues working as long as I handle my low level logic

Tomáš : [11:14] Basically, you need just to switch a NuGet package from DotVVM.Owin to DotVVM.AspNetCore. And then there are some ASP.NET related things that are different like authentication and configuration. You no longer have the web.config file. So you need to migrate these things, but you would have to migrate them with any other technology as well. But for the DotVVM part, it’s just a switching of NuGet package.

Jamie : [11:44] Right. That… you see I love when things like that are so simple. I… the DotVVM part is simple, right. The underlying bit, the bit that we waved our hands at and waved a magic wand, that’s not simple. But I like that the migration for the dependency that take on my app is super simple. It’s change a NuGet library and hit build, and presumably make sure that everything that’s calling the NuGet library is calling it in the same way, and it isn’t calling like APIs that maybe don’t exist anymore or things like that. I like that, that makes me feel happy: when I can when an upgrade is the NuGet dependency you just change a version or you change the name and it just carries on working, I like that.

Jamie : [12:28] But of course that that means that there’s lots of complexity behind the scenes, right? So I can imagine, yeah, that for DotVVM.Owin versus DotVVM.AspNetCore is like the complexity of managing that, keeping that API the same, because you said, you know earlier, you said ASP .NET Framework with MVC and ASP .NET Core with MVC are subtly different. That, I guess the subtle differences are big enough differences for folks like you writing that kind of framework that sits on top of that, right?

Tomáš : [13:06] Yeah, basically we had to create abstraction on a lot of concepts in ASP.NET and that allowed us to bring the same API to ASP .NET Core. And we didn’t try to reinvent the wheel. So we didn’t implement our own authentication and things like that. We just reused that from the underlying platform, but we were lucky enough to have an abstraction over that.

Tomáš : [13:31] So that’s what enabled us to do that, and like of course not many people at that time used DotVVM so they probably use different framework in their projects. But what DotVVM also allowed us to really implement an incremental way of modernization, because we also had at that time, we had a lot of web forms apps with like thousands of pages, and when once you decide to move that to the new .NET basically you need to redo all of these pages ; rewrite them to some other technology. And there are ways how to do that.

Tomáš : [14:14] One of them is like the side-by-side migration: basically you start a new ASP .NET Core application aside of the old one and install some proxy, for example YARP, to route the traffic; so the parts that were already migrated would be handled by the new app and the parts you didn’t touch yet so that these were handled by the old application. But now you have two applications. So basically you have created a distributed system, you need to synchronize the state, you need to make single-sign-on experience. And there is quite a lot of things you need to deal with. And with DotVVM, we use a different approach.

Tomáš : [15:02] Basically we take, we took this, uh, large web forms app with these thousands of pages and DotVVM is just a NuGet package. So you could install it in a .NET Framework project. And we started like rewriting the web forms pages into DotVVM, but we were still running on .NET Framework, still running on the same, uh, in the same project, a single process and once all these web forms, thousands of pages, were replaced and we built a converter that helped us to convert between these syntaxes; because otherwise it would be a lot of a lot of manual work, then you end with something that can be quite easily switched to the new with .NET.

Tomáš : [15:52] So recently we worked on one project. It had like 600 pages and we were quite surprised that the time required for the migration wasn’t like 20 or 30 percent of that effort we had to spend there. It was just like small, small percent of the total effort that was required to build the entire app.

Jamie : [16:18] Wow. That, I can’t even imagine an ASP .NET WebForm… web… yeah it’s causing me to lose my words. Like 600 pages. Yeah, that’s a lot of work. Yeah, even with the reduction through DotVVM that is still a lot of work, right

Tomáš : [16:42] Yeah, and a lot of testing. Of course on the other hand, if you look at these pages you split them into buckets like small, medium, large and a lot of them were quite trivial. But still it’s a thing you need to deal with; you need to like review , test whether it didn’t stop working, if it looks the same, if it behaves the same. So it’s a lot of effort. But like yeah 600 pages, if you have a team working on a project for 10 years then you will end up with application with 600 pages.

Jamie : [17:17] Wow. Just… yeah, wow.

Jamie : [17:21] And then the fact that you said that it was considerably less effort than you thought it was going to be because of DotVVM and YARP as well. I just want to really quickly point out that that is a wonderful use of the strangler fig pattern.

Jamie : [17:37] If folks haven’t used that before go check out YARP. It is really good. Is YARP is one of those acronyms… it’s yet another…. it’s not a backronym. It’s just an acronym, “Yet Another Reverse Proxy.” it’s a wonderful reverse proxy, written and supplied by the folks believe the folks at Microsoft, that allows you to do exactly what Tomáš said there: you put YARP in front of your rewrite and say to YARP, “if it doesn’t exist on this app, send it through to the to the old app,” i guess. And then you have to figure out some stuff to do with authentication like Tomáš said. And then that way you can slowly, I guess, peel off chunks of functionality from your, I guess, classic app and put it into your new, more modern app. And then fewer of those requests will go through to the original system. And that way you’re just slowly replacing things over time. I absolutely love that pattern, I have to say.

Tomáš : [18:35] Yeah, yeah. This is for this method, you don’t need to use DotVVM. You can use any framework because everything that is supported in the new .NET can be in the new project. However, as I said, there is the problem with having two apps. It’s more difficult to deploy. It’s more difficult to maintain and synchronize everything. I saw people using logs and things like that. And like now suddenly it doesn’t work when you have the logic in two processes, you would have to replace it with some other mechanism to handle these concurrency issues. So with DotVVM, you basically do the same things, but without YARP, you can do it in a single process because you can replace pages in the same project.

Jamie : [19:29] Wow. Okay.

Tomáš : [19:30] With their new implementations.

Jamie : [19:32] I really like that being able to do it in one process. We’ll come back to that in a moment because, obviously with YARP you’re adding an extra process, right. So we’ll come back to that in a moment, but first I think let’s talk about the book, because we’ve talked about all of this and we haven’t told the folks who are listening in about the book that you’ve written based on, from what you were saying, based on partially the experience of upgrading DotVVM and a number of your clients. So let’s talk about the book then. So what is, I guess the first thing is, what are people searching to get the book? What’s the full title?

Tomáš : [20:10] The full title is “Modernizing .NET Web Applications. " And the easiest way to get it is to go to modernizationbook.com. So just modernizationbook.com. And there is also like what you can find inside.

Tomáš : [20:27] I tried to make it a definitive guide to like for people who have .NET Framework project. I mean web project. I haven’t touched the desktop applications in this book. So if you have a web project built with .NET Framework, what you will need to change, what you will have to upgrade to get running on the latest version of .NET, which was 8 at the time of publishing the book. But there are not that many differences if you want to go to later versions like 9 or 10, like the upgrade, since like .NET 6 the upgrade to newer versions, is very straightforward.

Jamie : [21:09] Yeah yeah. I love that once you’re in modern .NET, once you’re in the .NET 6, 7, 8, 9, 10, most of the time the upgrade path is open: all of your project files, change the target framework moniker–the TFM–to either be target framework of the new version or target frameworks the old version the current version semicolon the new version, and then just hit build and see what breaks. I love how simple that upgrade path is it is glorious.

Tomáš : [21:43] Yeah, yeah. Like it’s still a good idea to test all the features of the app because occasionally there are some breaking changes, but it’s very simple. And I think that removing this barrier to make it really easy, it helps people to like continuously not increase the technologic depth in their projects.

Jamie : [22:07] Absolutely, absolutely. And I think, so I said at the very beginning of the episode that we’ll come back to this question, right. I just want to pose the question again to the listeners: so in the context of the .NET life cycle, what does STS stand for? And a lot of people actually get this wrong.

Jamie : [22:25] So a lot of people think that STS stands for “Short Term Support,” but actually folks it’s, “Standard Term Support.” So there is no real difference in the level of quality or anything in .NET versions that are odd numbered versus the .NET versions that are even numbered. So that’s STS and LTS, respectively; you’re just getting a a slightly longer life cycle for the even numbered versions. I just thought I’d throw that out there for people who are listening in.

Jamie : [22:56] So okay, we’re talking about the book is have a .NET Framework web application and I want to move from .NET Framework up to modern .NET." So before we get to that, I guess the first step is to plan it out, right. Because I know that with some of the .NET Framework based web applications that I have supported in the past, for one reason or another they rely on certain Windows services, right. And so just to set that expectation folks you may not be able to access those Windows services if you are running modern .NET; but perhaps on a Linux box you may not be able to. If you’re hosting on a Linux machine, you won’t be able to… may not be able to access those Windows services directly on that machine.

Jamie : [23:45] However, there is an answer to this; we’ll get to that in a moment. But we’re talking about that journey of like, “how do I plan it out ahead of just doing it?” right. Nobody, no engineer in the world wants to just jump straight into the work, right? They’ve got to plan it out. Is that your first step or is there a step before then?

Tomáš : [24:07] It’s like, the first three chapters are basically about that. Like to give you an idea, how .NET changed, what is new there. The second chapter is very long it’s about all the things, all the benefits you will get if you do the migration; because for me it’s always you need to do things for a reason, so like this chapter is about, “what you will get if you do that.” Not just because it’s modern, but like, what are the actual benefits? And there is quite a lot of them. I was very impressed. I expected that the chapter would be like 20 pages and it’s like over 60. I was never good in estimating things actually. So this is like, this is how it came out.

Tomáš : [24:56] And the third chapter is about like, how to convince the customers or like stakeholders who are not technical. So if you tell them that .NET 8 has better performance, or there is better APIs for this and that, they would probably not understand. But if you tell them about some like more generic security risks or like, that it’s difficult to hire people who would be willing on working with .NET Framework projects and these non-technical arguments, then probably they would understand what is going on. And so this chapter is also explaining how to advocate for this modernization within your company and make sure that everybody involved understands the risks of not doing the modernization, as well as the risk and how the process would look like when you decide to go on this journey. Because it’s never easy and every project is really unique. So you kind of don’t know what you will meet on the way.

Jamie : [26:05] So I really like that because obviously us as developers, coders, engineers–whatever word we want to use to describe ourselves–we are so deeply involved in the technology that like saying things to people about the differences between .NET Framework and the more modern .NET stack… it’s like people like, you will start… I’ve had an experience where I’ll start talking about the differences between them and I can see people just shutting down; like they’ve just gone to sleep, right. Maybe in their heads I sound like the old dial-up modem or something, right. Because I may as well be speaking a foreign language, right. Because they just don’t, they… none of that makes sense to them. You’ve got to talk in business terms, right.

Tomáš : [26:55] Exactly, Once you say .NET twice in a sentence, and when it’s once it’s framework and once it’s core, people who are not developers, they would get completely lost. And like, it’s normal, it’s natural. We have to learn how to speak in like more non-technical terms that are translated better in the business language. Because I think that developers also should have some insights in the business context in which their project lives. Otherwise, they would be making bad decisions.

Jamie : [27:32] I agree, because for the same reasons that you were saying, if I’m building something and I don’t understand the greater context in which it exists, then I am going to make assumptions, I’m going to make mistakes, I’m going to misunderstand. And it’s really important like maybe domain-driven design doesn’t fit with every single thing that we’re ever going to build, but the idea of ubiquitous language and ubiquitous understanding. Like understanding the why is the most important part of any of the stuff that we do, because if we can understand why someone wants us to build something we can understand how to build it better for them, right. You know, somebody says to me, “build me a payment processor.” Oh yeah, cool. I can bash that out in a couple of hours. But if I understand why they want a payment processor, I could probably say, “well, actually I could build you a custom one, or we can just integrate Stripe or integrate PayPal or something like that,” tight. So I don’t actually have to build it. I can buy it if I understand the why, right. And I know that’s not what you were saying, but it feels like it’s a similar situation, right?

Jamie : [28:38] Understanding how everything fits together and understanding how the business owner and the decision maker, how they think about it. Because from, like if I take off my developer hat: the code still works, it still gives me the functionality, it still makes me money. Why do I need to spend, you know, several hundred thousand dollars–or whatever the the cost will be–to upgrade it from it currently working, to I don’t know? Because this is like ephemeral, this updated version over here. So understanding how they see the application: 100% agree with you. absolutely

Tomáš : [29:17] Yeah, I wanted to say something like that, but I wasn’t able to express that in such nice terms as you did. But it’s exactly that, because as a developer, if I don’t know the context, I would probably spend a lot of effort polishing some feature that, from the business perspective is not important at all. And I would be doing these things and like the overall result will not be that great. And the modernization, it’s also a very complex technical thing, and it’s crucial to explain it so everybody, every stakeholder would be on board with what’s going on. It’s also preventing disasters that may come in the future, because I have seen modernization projects that took three years. And if you need to work on something continuously for three years, you have to present very good arguments and you have to inform all people involved, like what is the progress, what they should expect, like to manage their expectations. Otherwise if you tell them modernization it’s just an upgrade it will turn against you because like usually this process can be long it can take months it can take even small number of years.

Jamie : [30:39] Absolutely agree with you there. Yeah being able to set those expectations of, “this may take x number of years; it may take x number of months. And this is how we’re going to do it. And does this fit with the wider business direction?” right. Because as much as upgrading to a in-support thing is super important, upgrading to something that has the security benefits and the security positive stuff where all the CVEs are covered and stuff; like that is super important.

Jamie : [31:16] However, you know if the application is, let’s say it’s a web application that’s running on an internal server, that is air-gapped, that has a whole bunch of firewalls in place and authorization and authentication, you know; it may be that, in that context, upgrading it isn’t the most important thing in the world. And so knowing and understanding that, and being able to say to the business, “totally, let’s not bother modernizing this yet,” or “let’s put it on the back burner, maybe circle back to it in six months’ time or a year,” is as important as advocating for “let’s modernize!” right?

Tomáš : [31:55] Yeah, and sometimes the old applications can be replaced with some software-as-a-service offerings that didn’t exist 15 years ago. But today we have a lot of them. Recently, I saw some customer relations management system like CRM. And today we have a bunch of ready-made products that have much more features. So there is no point in upgrading, modernizing that old custom CRM somebody made at the time where we didn’t have these choices.

Jamie : [32:29] A hundred percent, right. Why spend, you know, $10,000 to $100,000 and two years upgrading something when I might be able to spend some money like importing and translating that data from the old system into, like you said, maybe it doesn’t even cost us anything to use it because it might just be open source right? I’m not advocating that massive companies that are making millions of dollars use open source and don’t contribute back; that’s not what I’m saying. But what I am saying is: it might be that, you know, hiring a consultant to transform that data to put it into the format that fits this new open source CRM, or low-cost CRM, is cheaper and therefore more business savvy than rewriting everything from the ground up, right.

Jamie : [33:19] Yeah, exactly. The team can focus on some other more fruitful things.

Jamie : [33:26] Sure. Okay so let’s say we’ve gotten past that stage of: we’ve gotten buy-in from the decision makers; they’re like, “yep. Here’s three years, here’s a budget of this much money. Go upgrade this one app,” right. Is there a planning step? I know we talked about how chapters one to three are planning and all that kind of stuff, and getting buy-in; but like the technical aspect of planning this out: like is there an almost like a playbook? Is there a common set of steps that you’d recommend people do or is it just a case of, “every project is different so good luck to you”?

Tomáš : [34:01] Oh it’s kind of both. Like I try to make a complete like address book or yellow pages; like, “if you are using this you, will need to replace with that. If you are using this, you need to replace with that.” But of course there are so many combinations of things that the book can never like cover everything, so I took the most things I thought that were used most frequently and then provided some guidance how to do that. And there is a part about like estimating and planning this up front so you can decide in which order you will do these replacements; and I also try to show how to cover these things with tests so you will get more confidence that you didn’t break anything during the process.

Tomáš : [34:48] So there is a chapter about like web services with these old SOAP formats based on XML, there is what to do with Windows Communication Foundation, how to migrate from LINQ to SQL to entity framework, forms, authentication, and like these things that are commonly used in old project, and step-by-step guides how to move them to their equivalents in the newest .NET.

Jamie : [35:20] Right, okay. So with that plan in place, this list almost like a dictionary of, you know, this thing needs to be replaced with this thing or this thing is recommended to be replaced with this thing. That’s in place.

Jamie : [35:34] So I’ve got buy-in from the decision makers. I’ve got a plan for which components need to be replaced. I’m potentially going to throw YARP at my app so I can start building it from the ground up with a proxy in front, so I can start carving out bits of functionality and putting them in the new application. Is there… how do you go about that, right? Is it just, “pick a piece of functionality and work on that,” or is it a case of finding what the business requires first and working through that? Like you said earlier on you moved one customer from 600 pages of ASP .NET WebForms over to the new modern .NET stack; how did you do that? Was that start with the most used pages, the least used pages, maybe pages that have the most test coverage? What if there’s no test coverage right? I’m asking a million questions there, I’m sorry.

Tomáš : [36:33] No problem, no problem. Like the first step was I described what we did in this project, but like in more general terms the same thing is written in the book: first thing is to get rid of everything that is not used, and like do some code cleanup and refactoring. Because the cleaner the code base is at the beginning, the less problems you may have later. So it’s really good to, after you have a high level plan that is agreed on with the business then like try to like really clean up the code base: investigate what parts are no longer used, because in these old projects you can probably find even quite big areas that haven’t been touched for years. So these can be either completely removed or just postponed to later stages. And then it’s great to set up the process and test it on something easier.

Tomáš : [37:37] Or things like: do not start with the most complicated part, because then you may run into many obstacles and it would be like a rabbit hole. You start working on some issue, it leads you to three and other issues, and then you have to recursively browse through the entire tree, and then some at some day you will–if you survive that–you will probably fix everything and you will migrate the most complicated page. But like it’s quite risky and frustrating so don’t do that.

Tomáš : [38:08] Basically I always start with classifying, no matter if these are the pages or like domain objects domain areas, but like to classify things if it’s small, medium, or large. And then I start with [a] couple of examples of small things, [a] couple of examples with medium things, and [a] couple of examples of the large things. And this helps me to provide or update my estimates.

Tomáš : [38:38] So if I would simplify this a little bit, I have 600 pages, I find that 300 of them are small, 200 of them are medium and 100 is large. So I would do five examples of every bucket and measure how much time I spent on migrating those. And this would help me to get a better guess of how much effort I will need in total.

Tomáš : [39:09] Yeah, of course, there are a lot of things that you can reuse later. So probably, you will be more pessimistic at the beginning. But also there can be a lot of things you didn’t expect. So like, it’s better to be able to measure these things and provide estimates and like update them during the process. But like, I would just a general advice would be not to start with the most complicated part. Because it may unveil a lot of problems at the beginning, and you could get lost in that. But on the other hand, if you just pick the trivial things and leave everything that is even a bit complicated to later, then you are just delaying the most problematic things. So, like, use common sense and you will get there, basically. It’s the most generic advice I can give.

Jamie : [40:08] I mean, sometimes the most generic advice is the best advice, right.


A Request To You All

If you're enjoying this show, would you mind sharing it with a colleague? Check your podcatcher for a link to show notes, which has an embedded player within it and a transcription and all that stuff, and share that link with them. I'd really appreciate it if you could indeed share the show.

But if you'd like other ways to support it, you could:

  • Leave a rating or review on your podcatcher of choice
  • Consider buying the show a coffee
    • The BuyMeACoffee link is available on each episode's show notes page
    • This is a one-off financial support option
  • Become a patron
    • This is a monthly subscription-based financial support option
    • And a link to that is included on each episode's show notes page as well

I would love it if you would share the show with a friend or colleague or leave a rating or review. The other options are completely up to you, and are not required at all to continue enjoying the show.

Anyway, let's get back to it.


Tomáš : [40:14] Yeah.

Jamie : [40:14] And all of that makes total sense, right. Because you’re still, I guess, whilst you’re still migrating the first few pages or functionality or whatever you’re still sort of ensuring that it is possible to do it. And so, like you said, you want to start with something that’s relatively trivial that is not maybe the entire authentication stack or the, you know, the the most complex bit of database stuff, right. Maybe even just, “hey, here’s the link to the privacy policy that shows a document being pulled from the new app rather than the old app,” because then you’re proving that it can still, like, it will work, and that you can still send requests to the new functionality through whatever you’re doing to the new bit, and then send requests to the the contemporary… the classic… the original application is still running; is still able to serve those requests. So that makes total sense.

Tomáš : [41:18] Like as a first instance you can start with these trivial things, but if there are like hundreds of these trivial things I would not do all of them in the beginning because you will not discover anything. You need to get to a reasonable complexity quite early to be able to have better estimates, yeah. So don’t get to the most complex thing at the beginning but try to get fast to some like medium complexities areas because also there is the like Gauss curve, like majority of the things would be like medium -complex, not the trivial and not extremely complex; it will be somewhere around the middle point.

Tomáš : [42:06] So like you need to get there quickly to get rid of the initial obstacles you may run into. And then, from there, you can you can continue to other areas of the application. And also like this, there are a lot of technical constraints, because for example if you use YARP you need to start with the authentication quite early, if not even as a first thing, because you have two applications, they probably need to be aware of who is signed in, who is interacting with the application. So you cannot say, “I will do the authentication in the new app later,” because you need it at the beginning.

Tomáš : [42:50] On the other hand, if you use DotVVM and this in-place modernization within a single project, the authentication is there from the web forms times or from the old times, and you can still be using it until the very end of the process. So there are technical constraints which depend really on the details. So it’s hard to provide a generic advice without knowing which concrete method you will use.

Jamie : [43:19] Yep. And it all still then depends on, like, not just what you’re migrating but how it was originally written, and how much different that is to how we do things now. And and so, yeah I can imagine that talking on a podcast like this, where we haven’t got a piece of code where we can actually share a video and say, “so how we would modernize this is to do this, that and, the other.” Can’t easily do that on audio, but I appreciate the point that you’re making about, “start with something trivial to get that that initial step, to prove it. Then move on to something not so trivial, maybe of a medium complexity, and then definitely do authentication as soon as you, can once you’ve proved that.” You’re absolutely right , because otherwise you’re just going to have a headache.

Tomáš : [44:13] Correct.

Jamie : [44:13] You’re going to build all this new functionality that’s hanging on YARP that allows you to do things where you should be authenticated, and then you have to build the authentication. And then it has to be signed in both directions for the old app, for the new app, and then you’ll end up–like listeners will know that I have no hair–you will end up like me: you’ll end up tearing, I’d never tear my hair out, but you will end up tearing your hair out with frustration going, “no. I can’t understand why is this not working.” Get it done really quickly.

Tomáš : [44:43] That’s because the point, these modernization processes are quite long-term, so you need to deploy new versions during this modernization. You cannot tell, in most cases, you cannot tell the business people like, okay, “I will be modernizing my apps for two years, so there will be no new requirements implemented. " That’s usually not possible.

Tomáš : [45:06] So you need to find a method, and the book shows how to do that, a method of incremental modernization that you can slowly migrate things to the new versions but be able to add new features, and implement new requirements, and fix bugs at the same time, with the same team in the ideal case. So that’s why you need to solve these authentication things first: because you will need to deploy the new ASP .NET Core application somewhere and if it would not have authentication probably you would have a security issue somewhere.

Jamie : [45:44] Absolutely, absolutely. And then, like you’re saying, if you then have to add new functionality because you can’t do a code freeze, you can’t say to someone, “we’re not going to add new stuff.” If you’ve already added the authentication, you might even be able to add the new features in the new version rather than adding it to the old version; then, hopefully, at some point in the future porting it across but you can only do that once you have authentication in place, right.

Tomáš : [46:12] Yeah and the same is with configuration logging and a lot of other areas. That’s the biggest problem of the YARP migrations: that they will force you to do a lot of infrastructure things at the beginning before you even start migrating some real functionality. Yeah so there is quite a huge entry barrier you have to get over and then you can start modernizing. And then and then it’s not that difficult because you have everything in place, but the first step is usually quite quite big.

Jamie : [46:49] Yep, yep. And so, okay, based on that then, and I remember we talked about DotVVM earlier on: if I’m lucky enough to be modernizing an application that uses DotVVM and you said that you can do the reverse proxying in one process rather than two with DotVVM, does that mean in this magical world where I have a DotVVM project and I’m modernizing it to the new one, is that then I’m conscious of using the phrase, but i’m going to use it anyway–easier to do the migration if you’re migrating a DotVVM versus a YARP? Or is it just a case of, it’ll suck for a little bit because it’s difficult and you’ll get past that bit, and then it’ll get really easy.

Tomáš : [47:37] Depends on the scenario.

Tomáš : [47:39] If you need to, or depends on how the initial and the final state, how they differ. If the point is that I’m quite happy with the application, but it’s using .NET Framework and I want to use it on the newest .NET because I want to invest in this application for other years, but I’m quite happy with the structure with the code base, just I need to upgrade the libraries. Then DotVVM can be easier because basically 10,000 feet view, you will have to touch less code and you will decrease the risks.

Tomáš : [48:20] But if the new application should differ from the old version, you need to split it multiple applications or you need to redo the user interface completely that it would look as a completely new app, then DotVVM wouldn’t help that much in the process, because basically what it’s giving you is the ability to put everything with the YARP inside one process. So you don’t need to deal with single sign-on, you don’t need to do all the infrastructure changes at the beginning, you can leave it to the very end of this migration process. But that’s it. Otherwise it’s just a UI framework that has some similar attributes to Blazor, so it’s quite similar: the comfort of using it’s quite similar to Blazor, it’s comparable.

Tomáš : [49:16] But otherwise it’s like if the application should remain 90% the same just with the new technologies, DotVVM will help. In other cases, it’s not that not that huge benefit.

Jamie : [49:34] Sure. Okay. So we’re similar to Blazor as well, which keeps us in the .NET stack. I really liked that.

Jamie : [49:43] I know that there are some spicy comments online about Blazor, but you know, I kind of like it. It allows me to stay in the .NET stack when I want to stay in the .NET stack. And t’s not like you can’t go–this is completely going off topic–butI like that Blazor allows me to go and add javascript in where I want to, which is really quite useful.

Jamie : [50:07] Cool, okay. So what i’m thinking then, because we’re coming up to the end of our time together, and I apologize folks we’ve gone on a couple of tangents and we haven’t really answered a lot of the questions that I had planned; but that’s okay.

Jamie : [50:20] So I wonder, with with us coming up to the end of our time, would you mind reminding folks about the book DotVVM, and where to get both of those: the book and DotVVM. And then if there is–like some people are online, some people are not–if folks have some burning questions, they’re like, “Tomáš, I’ve got this idea and I want to just pick your brains for two or three minutes,” is that an X-formerly-known -as-Twitter thing? Is that a Bluesky thing? Is that a LinkedIn thing? Is it none of those? That is also an option. How do folks get in touch, and remind folks about how to get the book and DotVVM.

Tomáš : [51:01] Yeah, so I will start from the end. If anybody wants to reach me, please try to use LinkedIn. I try to get rid of all other social media to reduce the mental clutter that is around these days. It’s working for me for two months. I can say I’m clean from social media, except for LinkedIn, which I use for work. And the other resources, like everything about the book, can be found at modernizationbook.com. And if you want to try DotVVM, look at DotVVM.com, D-O-T-V-V-M.com.

Tomáš : [51:42] Basically, if you use Blazor, DotVVM would not be that unfamiliar to you because you will be using just HTML and C#. It’s quite easily you can easily combine it with JavaScript, same as Blazor. And we don’t use web assembly, and we don’t use like the SignalR connection between the client and the server. DotVVM is just exchanging few JSON documents between the clients and server, so we are using different different things underneath but the outcome is the same. You can use HTML and C#, and not write hundreds of lines of JavaScript. And if you have been using WPF or .NET MAUI, DotVVM is using Model–view–viewmodel, MVVM, pattern. So it would feel very familiar to what you are used from different applications.

Jamie : [52:43] Ah, see that. So I know that I misnamed it earlier on, right at the beginning, I said dot MVVM. So my thinking is that’s where the name comes from, right? And that’s why I made that mistake. Right.

Tomáš : [52:57] Yeah. Yeah. We combine .NET and MVVM. So we skipped the M, but if you want it there. It’s not incorrect because actually you will be using MVVM while writing apps in DotVVM.

Jamie : [53:12] Nice, okay. Excellent, Well Tomáš, it’s been fantastic chatting with you today. Genuinely, I say this all the time folks but I really do mean it, I’ve walked away from this conversation with a whole bunch of new things to go check out. Like my own modernization of .NET apps has been slightly different to Tomáš’, not the same, but I now have a better understanding of the things that I need to, maybe map out, in my planning sessions. I like the idea of picking a trivial task and then moving up the complexity really quickly, as soon as I’ve established that I can build something with either a reverse proxy or with DotVVM or whatever.

Jamie : [53:58] So what I want to say, Tomáš, is thank you so much for sharing this expertise with folks.

Jamie : [54:03] And folks, please do go check out Tomáš’s book because at some point in your career, you are going to be modernizing a retro–i’ve used lots of different words in this episode–you are going to be modernizing a .NET Framework web application into the modern .NET tech stack, and you kind of need to know how to do it. So go have a look at Tomáš’s book for sure

Tomáš : [54:28] Thank you. It was great pleasure to be here. And I will be happy to talk at LinkedIn or on other opportunity.

Jamie : [54:36] Amazing, amazing. Thank you so much.

Wrapping Up

Thank you for listening to this episode of The Modern .NET Show with me, Jamie Taylor. I’d like to thank this episode’s guest for graciously sharing their time, expertise, and knowledge.

Be sure to check out the show notes for a bunch of links to some of the stuff that we covered, and full transcription of the interview. The show notes, as always, can be found at the podcast's website, and there will be a link directly to them in your podcatcher.

And don’t forget to spread the word, leave a rating or review on your podcatcher of choice—head over to dotnetcore.show/review for ways to do that—reach out via our contact page, or join our discord server at dotnetcore.show/discord—all of which are linked in the show notes.

But above all, I hope you have a fantastic rest of your day, and I hope that I’ll see you again, next time for more .NET goodness.

I will see you again real soon. See you later folks.

Follow the show

You can find the show on any of these places