The Modern .NET Show

S08E23 - From Pentest to 1.7 Million Downloads, Part 2: The Lessons Nobody Ever Taught Me

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

S08E23 - From Pentest to 1.7 Million Downloads, Part 2: The Lessons Nobody Ever Taught Me
The Modern .NET Show

S08E23 - From Pentest to 1.7 Million Downloads, Part 2: The Lessons Nobody Ever Taught Me

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

In the second half of this two-part story, Jamie picks up where the previous episode left off: with working middleware code on his laptop, and no idea what it takes to turn that into a NuGet package other developers will actually trust.

What follows is eight years’ worth of lessons, told in roughly chronological order. From a four-part blog series in 2017, through the first NuGet publish, through a JSON-configuration footgun shipped to production users, through a CI/CD migration from AppVeyor to GitHub Actions, through a single pull request from Scott Harden that lifted the entire project’s packaging standards, and into the supply chain hardening practices that any serious package author should be adopting in 2026.

Topics covered in this episode include:

Featuring quotes from previous guests Safia Abdalla, Scott Harden, and Tanya Janca, the episode closes with a direct call to action for both aspiring package authors and existing maintainers.

Episode Transcription

Hey everyone, and welcome back 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. I’m your host Jamie Taylor, bringing you conversations with the brightest minds in the .NET ecosystem.

Today’s episode is a little different from the norm. I waned to, temporarily, take you away from the “AI is the best thing ever/worst thing ever” news cycle, and talk to you about an open source project that I work on called “OwaspHeaders.Core”

This is the second in a two-part series about OwaspHeaders.Core and focusses on providing a timeline of the evolution of the package; but this isn’t going to a be all about how great I am. I’m going to cover the lessons I learned, the choices I made, and the help that I had from the community.

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

Last time, I told you how a failed pentest in 2016 led me to OWASP, to HTTP security headers, and to building an ASP.NET Core middleware to fix the problem.

What I didn’t tell you is what happened next.

Because having working code on your laptop and having a NuGet package that’s been downloaded 1.7 million times are two very different things.

This is the story of the journey between them. And it’s a story about everything I had to learn that nobody had ever taught me.

2017: The Blog Series Origin

So. Around the same time as the pentest story I told you in the last episode, Microsoft were doing something that had felt unimaginable a couple of years earlier. They were rebuilding .NET. Open source. Cross-platform. A version of the framework I’d grown up on that would run on a MacBook Air.

I was completely fascinated by it.

And I made what felt at the time like a very small decision: I started a blog. I called it “A Journey in .NET Core.” The title was deliberate. I wasn’t an expert. I wasn’t going to pretend to be one. The point was that I was going to figure this thing out in public, and write about what I learned along the way, so that anyone else walking the same path could trip on the same things and maybe get past them a bit quicker.

The blog isn’t live any more, by the way. I took it down in 2023. The full content is on the Wayback Machine, and I’ve got plans to revive it as an archived site at some point. I’ll link the Wayback Machine version in the show notes.

But back to 2017.

One of the new things in ASP.NET Core was the middleware pipeline. And I wanted to write about it. I wanted to take readers through how it worked, what you could do with it, how you’d build your own. And I needed a concrete example to hang the explanation on.

The pentest story was still fresh. The OWASP headers were the thing I’d most recently learned how to do well. So that became the vehicle. A four-part blog series, walking readers through building a custom ASP.NET Core middleware that would add the OWASP recommended security headers to any response that went through it.

The first post went up in July 2017. By the time I finished part four, in September, the middleware genuinely worked. It even had tests, the whole shebang. I’d shipped a real thing, in public, showing all of my working-out.

And then I had a thought.

A thought that, looking back, was the actual turning point.

The thought was: hang on. If this middleware is useful, then anybody who wants to use it has to read four blog posts, copy code out of them, paste it into their project, and hope they don’t miss anything. That’s a fair bit friction (and even more so, now that the blog is harder to access). That’s the kind of friction that means almost nobody will actually do it.

So why don’t I just make this a NuGet package? Wrap it up. Make it one line of configuration in someone else’s project. That way the only thing they have to do is type dotnet add package, and the whole thing is there, ready to go.

I had no idea what I was about to walk into.

2017 Into 2018: Becoming a Package Author

Here’s the honest truth. Before I tried to ship my first NuGet package, I had never thought about what a NuGet package actually was.

I’d consumed hundreds of them. So have most .NET developers. You type dotnet add package, something happens behind the scenes, and now you can call into a library you didn’t write. That’s the whole interaction, most of the time.

But what is the thing being added?

The short version is: a NuGet package, a .nupkg file, is essentially a zip file. Open one with seven-zip (or your favourite archive utility) and you can see the structure. There are some compiled DLLs in there. There’s an XML file with metadata. There’s the licence. There’s an icon. There are bits and pieces that the package management tooling reads in order to make decisions about how to wire your dependency into your project.

Scott Harden and I actually spent the best part of an episode on this in season seven, episode nine (“Modern .NET NuGet Packaging with Scott Harden”). We pulled apart the structure of a real package, layer by layer. If you want the deep dive, that’s where to go. The link is in the show notes.

Back to 2017, six years before that episode was recorded. I went from knowing none of that to having to know it well enough to publish my own NuGet package. And the things I had to learn to get from one end of that journey to the other came in roughly this order.

First, the csproj metadata. The properties that show up on nuget.org — the description, the author, the licence expression, the package icon, the project URL, the repository URL, the release notes — all of those live in the csproj file as MSBuild properties. Get them wrong, the package still builds but it just looks unprofessional on the listing page. And first impressions, when somebody’s deciding whether to trust your package, matter more than you’d think.

Second, semantic versioning. I’d been using version numbers as fairly arbitrary labels up to that point. The first time I had to decide whether a change was a patch, or a minor, or a major version bump, I sat staring at the screen for an embarrassingly long time. I’m being honest. Because once you publish that version, the contract you’ve made with everyone who depends on you is real. A major bump says “I have broken something on purpose.” A patch says “nothing about the surface area has changed.” Choosing wrong is the kind of mistake that costs other people their afternoons.

Third, the account setup. Generating an API key on nuget.org. Working out which scope it needed. Storing it somewhere that wasn’t in a screenshot on Twitter. All of that.

And fourth, the actual mechanics. Building the package, pushing it to nuget.org for the first time, watching the validation process, waiting for it to appear on the listing. The first time you see your own thing live on nuget.org is a properly memorable moment. I wish I’d taken a screenshot.

None of this was taught to me. I learned it by doing, by reading the documentation, and by getting things wrong in public. And the documentation on nuget, and on learn.microsoft.com, is genuinely good. It’s better now than it was when I started. The tooling has only improved.

So here’s the first thing I want you to take from this episode. If you’ve solved a problem in your own codebase that other developers are likely solving too, the barrier to publishing that as a NuGet package is much, much lower than you probably think it is.

But.

Here’s the other half of the lesson. And I think this is the part that doesn’t get told often enough.

The barrier to publishing a package you won’t be embarrassed by in six months is higher.

Let me tell you a story about that.

The first version of OwaspHeaders.Core used a JSON configuration file. The settings — which headers to include, what values to give them, all of it — lived in a file called secureHeaderSettings.json, sitting in the consumer’s project. And I’d helpfully configured it with reloadOnChange set to true. Because that’s the default. That’s what you’d expect.

Do you see the problem coming?

If a big application was serving real traffic, and somebody changed that JSON file on disk, the whole site would restart. The middleware would re-read its config, and ASP.NET Core would cycle the application along with it. Disastrous. I shipped that. People were using it.

So in February of 2018, I rewrote it. The configuration moved out of a JSON file and into a builder pattern. You wire the middleware up in code, at startup, and the configuration is baked in at the point your application boots. No file watcher. No restart-on-change footgun. It’s how the package has worked ever since.

That whole rewrite — the realisation, the redesign, the migration path for existing users — happened in public, on my blog, and partly on a live stream. Because that’s how I was working at the time. And because of that, the version where I shipped the bug is part of the story.

The barrier to entry is low. The barrier to shipping something you’d defend in front of a room is higher. But you only get to the second one by being willing to be wrong in front of people. That is the whole game.

2017 To April 2022: Living With CI/CD

Once you’ve published one version of a NuGet package, you very quickly realise that publishing the next version manually, from your own laptop, isn’t going to scale.

The reasons aren’t subtle. Doing it manually means there’s always a step you might forget. Doing it manually means the build environment is your machine, with whatever happens to be installed on it at the time. Doing it manually means a version of you, six months from now, in a hurry, on a Friday afternoon, can do something that you really wish past-you had made impossible.

Safia Abdalla came on the show earlier this season. She’s at Warp now, working on agentic developer tools; but at the time was a principal software engineer on Microsoft’s ASP .NET Core team. She told a story about her second internship, where she accidentally pushed an in-progress feature straight to production. The infrastructure made it trivially easy to do. She tried to fix it before anyone noticed. She didn’t. She ended up with a post-it note from the CTO on her monitor when she got back from lunch.

And the line she landed on, when she was telling that story, has stuck with me.

It’s not really an indictment of the engineer. It’s an indictment of the infrastructure that is set up to support deployment.

That’s the principle. The point of all of this isn’t to be a more careful engineer. The point of all of this is to build infrastructure that doesn’t need you to be a more careful engineer. Past-you can’t make certain mistakes impossible by trying harder. Past-you can make them impossible by automating them away.

You need automation. You need a pipeline. You need somewhere outside your own laptop that knows how to build, test, and publish the package in a way that is the same every single time.

In 2017, GitHub Actions did not exist as a public product.

That sentence is wild to say out loud now. It feels like a sentence about a different industry. But it’s true. For .NET open source projects at the time, you had a small handful of options, and the one that most of us reached for was AppVeyor.

So that’s where OwaspHeaders.Core started. The first appveyor.yml file landed in the repository on the 25th of July, 2017, two days before the first blog post in the middleware series went up. So this pipeline genuinely predates the package itself.

I remember the first green build. I really do. There’s a particular feeling, the first time you push a commit and watch a service somewhere else in the world pick it up, build it, run the tests, and report back green, that you don’t get from any other part of programming. It’s the moment where the project stops being a thing you have to manually keep alive and starts being a thing that can keep itself alive while you sleep.

AppVeyor served the project well. It served it for about four and a half years.

Then, on the eighth of April, 2022, the appveyor.yml file was deleted from the repository. On the same day, two new files appeared inside .github/workflows. One was called dotnet.yml. The other was called release.yml. The build had moved to GitHub Actions.

Same day. Out with one, in with the other.

The reasons for the move were pragmatic, not philosophical. The code already lived on GitHub. Actions had reached the point where it was a credible replacement. And there’s a particular kind of operational tax you pay when your CI and your source control are different services from different vendors, with different account systems, and different incident pages to watch when something breaks. Folding everything into one provider made sense.

I’m not going to walk you through the YAML. That’s not what this part of the episode is for. If you want to see the pipelines, they’re public, on GitHub, and I’ll link the repository in the show notes.

What I want you to take away is the principle. Because the principle is much more important than the choice of vendor.

The day you stop publishing your package from your own laptop is the day you start running a real package.

Until that moment, your release process is whatever happens to be in your shell history. After that moment, your release process is a thing that other people can see, audit, and reason about. Other people including future you. Other people including the contributors you’ll want to bring onto your project eventually. Other people including the consumers of your package who want to understand how it ends up on nuget.org.

Automation isn’t really about saving time. Or, it is, but that’s not the main thing. Automation is about giving up the ability to make certain mistakes. You can’t forget a step that has been removed from your control. You can’t accidentally publish from a branch the pipeline isn’t pointed at. You can’t ship a version that hasn’t been through the tests, because the pipeline simply will not let you.

That is the win. The vendor is the implementation detail.

2022: Scott Harden’s Pull Request

Now. I want to tell you about a pull request that changed how I think about NuGet packaging. It came from outside the project — from someone I’d actually known online for years. We’d talked plenty over in the Coding Blocks Slack group, and he’d written in regularly to Tabs and Spaces, a now-retired podcast I used to co-host with James Studdart and Zac Braddy. We hadn’t met in person. He hadn’t, until that day, touched the code in OwaspHeaders.Core. And the PR he opened lifted the entire project’s standard in a single review.

The pull request number is 96. The contributor is a developer called Scott Harden. You might know him as the author of ScottPlot, which is one of the most popular .NET plotting libraries. He’s also done three episodes of this show with me, so if any of his voice sounds familiar in a moment, that’s why.

Scott’s PR landed in 2022. And on the surface, it was a metadata cleanup. He added the MIT licence expression. He included debug symbols. He turned on Source Link. He enabled deterministic builds. And he designed a proper package icon.

Five things. That sounds like a polish pass.

It wasn’t. It was a step-change.

Let me explain why, starting with the most concrete one. Source Link.

The really cool thing is that now, if we enable this right combination of things, we can enable a feature called Source Link that when you press F12 it lets you jump, not just into the functions of your own code, but you can jump into the source code of a NuGet project that you’re using.

Think about what that gives the consumer of your package. A developer using OwaspHeaders.Core can press F12 in their IDE, and instead of getting a decompiled view of the DLL, they get the actual source code from the actual GitHub repository, at the exact commit that produced the version they have installed. They can step through it. They can read the comments. They can understand what’s happening.

That isn’t a cosmetic feature. That is a fundamental shift in the relationship between you and the people using your code. Your package goes from being an opaque box that they have to trust, to a completely transparent one that they can verify, line by line.

Deterministic builds work in the same spirit. They mean that if anybody else, anywhere, downloads the source code from the same commit and runs the same build, they will get a byte-identical copy of the package that’s on nuget.org. No surprises. No “well, on my machine it produced this DLL.” The same source produces the same output. Always.

Symbols and the licence expression round it out. Symbols let your users debug into your code from their production diagnostics. The licence expression — that’s the SPDX format, which is a small structured language for describing exactly which licence your package ships under — is machine readable, which means it survives every tool, every dashboard, every legal-review process that wants to understand what they’re allowed to do with your code.

None of these are cosmetic features. All of them are trust signals.

And here is the thing about how this PR got onto my project in the first place.

These type of code contributions are just unique. And I bet a lot of maintainers would really benefit from having pull requests like this show up in their inbox. And even if they don’t merge it, even if they don’t like the logo exactly, it can start a conversation that can lead to possibly something that might be a better fit for the project.

Scott knew more about modern NuGet packaging best practices than I did at that point. He could have written me an email. He could have raised an issue. Instead, he opened a pull request that fixed the things and explained the reasoning, and gave me the option to merge it or push back on any individual piece. That’s the spirit of open source done well.

If you ever spot something in an open source package that could be improved — even if it’s “just” metadata, “just” the documentation, “just” the package icon — consider raising the PR. Those contributions matter more than the maintainer is going to be able to tell you in the moment.

But — and this matters more now than it ever has — read the contribution guide first. Read enough of the code to understand the conventions. Match the format, the design, the philosophy of the project before you write a single line. A lot of open source maintainers right now are cutting back on external contributions, because they’re spending more time politely declining drive-by PRs that look plausible but don’t fit. Often that’s because the contributor asked a coding agent to “fix this bug” or “add this feature” without ever asking the agent to read and understand the codebase first. Don’t be part of that signal.

Scott’s PR worked because it was the opposite of that. He understood the project well enough to know exactly what was missing. The diff explained the reasoning. The conversation was already done by the time I looked at the code he’d written. That’s the bar.

Now. There was one more thing Scott said on that episode that has only grown more important since.

And the day that I realised you can just put arbitrary DLLs in NuGet packages, that’s when it really clicked for me that, wow, like security is a thing. You can’t just be installing random NuGet packages.

Scott said that in December 20th, 2024. 18 months later — 15 days ago, as I’m recording this — TanStack published a postmortem about what happened to them. The Shai-Hulud worm got into forty-two of their npm packages and pushed eighty-four malicious versions, in a 6 minute window.

The attack chain ended with malware reading /proc/PID/mem on a GitHub Actions runner, stealing an OIDC token, and using it to publish to npm directly. The token was never typed by a human. It was extracted from process memory.

And the line from their postmortem that I cannot get out of my head is this.

“No internal alerting. We learned about the compromise from a third party.”

Now. That was npm. Not NuGet. And that is the point. The .NET ecosystem has not been hit on the same scale. Yet. Which is exactly why everything I’m about to say in the next section is not theoretical hygiene. It is the difference between being TanStack on the 11 of May, 2026, and being someone who can prove to the world that their package came from their source code, built by their CI, with no hands in the middle.

That’s not “nice to have” any more.

That’s the price of being trusted.

2024 Into 2026: Supply Chain and Trust

Right. What does it actually look like to take supply chain seriously, in a NuGet package, in 2026?

Let me walk you through what OwaspHeaders.Core does now, and then I’ll come back to the principle behind all of it.

The first thing is build attestations. These were added in version 9.5.0. An attestation is a cryptographic record, produced by the CI pipeline at the moment it builds the package, that says: “this exact nupkg file came from this exact commit, in this exact repository, built by this exact workflow, on this exact runner.” It is signed by GitHub’s infrastructure. It is verifiable by anyone, after the fact, with a single command. You can take the nupkg off nuget.org right now, run a verify command, and it will tell you whether it matches the attestation or not.

That is what proof of provenance looks like. It is the answer to the question “how do I know this package came from where it claims to come from?”

The second thing is the OpenSSF Scorecard. The Scorecard project, run by the Open Source Security Foundation, runs a battery of automated checks against your repository, looking for things like whether your branch protection is sensible, whether your dependencies are pinned, whether you sign your releases, whether you have a security policy. The score is public. Anybody can look at it. And the workflow that produces it runs every week, on a schedule, so the data stays fresh.

Alongside the Scorecard, the project carries the OpenSSF Best Practices passing badge. As of this recording, the score is 96%. It was added on the 20th of Novemberm, 2024. Both links are in the show notes.

The third thing is CodeQL. CodeQL is an automated static analysis tool from GitHub. It looks for known patterns of vulnerable code, in your code, and flags them. The CodeQL workflow runs on every push, on every pull request, and on a weekly schedule, so even code that hasn’t changed gets re-evaluated against newer security rules over time.

Now. Here is the bit I want you to notice.

When the migration from AppVeyor to GitHub Actions happened in April 2022, the project had two workflows. The build pipeline. And the release pipeline. That was it.

Today, there are seven.

Build. Release. CodeQL. OpenSSF Scorecard. The documentation site build for GitHub Pages. A code coverage commenter that posts coverage reports onto pull requests. And a changelog sync that keeps the documentation site’s changelog in step with the root one.

Two became seven over about four years. And the reason there are seven, and not one giant mega-workflow, is something I want you to take with you if you take nothing else from this section.

One workflow. One concern. One permission scope.

The build pipeline only needs read access to the repository contents. The release pipeline needs the write attestations permission and the OIDC token to authenticate to nuget.org. CodeQL needs the security-events write permission. The Scorecard needs a different kind of token altogether. The coverage commenter needs to be able to write to pull requests. The changelog sync needs to be able to write to repository contents, but only on a very specific path.

If I’d bundled all of that into one workflow, that one workflow would have needed every single one of those permissions at once. And anything that compromised the workflow file, or any third-party action it called into, would have inherited the entire keyring.

Splitting them up means that if one workflow ever gets compromised, the blast radius is bounded by the permissions of that specific workflow. The build workflow can’t push to nuget.org. The Scorecard workflow can’t write to repository contents. The Pages workflow can’t see your secrets. Each one is small, on purpose.

Permissions are like keys. Fewer per workflow means less to lose if one of them ever gets compromised.

Look. None of this is hard to adopt. Most of it is templates you can copy directly from GitHub’s documentation. The bar to look trustworthy is lower than it should be, which means there is no excuse not to clear it.

Eight Years of Maintenance, and the People Who Showed Up

The package has been on nuget.org now for eight years. There have been ten major versions. There have been more bug fixes, more dependency bumps, more documentation updates than I want to try and count.

Maintenance, after the first year or two, becomes less about code and more about communication.

Let me walk you through four moments from the issue tracker that I think capture the shape of it.

The first one is issue number 51. Somebody opened it to point out that the middleware was wrapping URI values inside the Content Security Policy header in quotation marks. Quotation marks that, per the spec, should not have been there. The user was right. The middleware had been wrong. And Chrome — and this is the bit that genuinely humbled me — had been silently fixing the mistake in the background, without raising an error, so I had never noticed. I fixed the bug, thanked the person who reported it, and started building a stronger habit around reading specs end to end instead of relying on the browser to forgive me. The bug report wasn’t just a bug report. It was a free education.

The second one is issue number 170. Somebody opened it asking for support for the CSP report-to directive. The initial request was a little off — the way they’d described the syntax wasn’t quite right. So I asked for more context. They came back, refined the request, and between the two of us, we ended up with a design that was better than either of us would have produced on our own. That’s a small example, but those are the conversations I value the most. Both parties leave the issue knowing more than they did when it started.

The third one is issue number 168. Somebody asked whether the middleware could expose its configuration via feature flags, so they could toggle individual headers on and off at runtime without redeploying. It’s a reasonable thing to want. But it’s not what this middleware is for. The configuration is deliberately compile-time, so that the security posture of the application is fixed at the point of deployment, and not changeable by a runtime knob that somebody might forget to put back. I closed the issue. I explained why. And I tried very hard to do it in a way that respected the person who had taken the time to ask. Learning to say no, gracefully, in writing, on a public record, is a skill that doesn’t get talked about enough.

The fourth one is issue number 95. Somebody opened it asking how to allow certain domains. The request as written wasn’t quite clear what they were trying to achieve. I followed up. I followed up again. I followed up a third time. Eventually I closed it. Some conversations don’t finish. That’s also part of maintenance.

None of those four interactions involved writing very much code at all. They involved reading carefully, asking good questions, and being willing to either say yes, or say no, or to admit “I don’t fully understand what you’re trying to do, can you help me?”

But none of this is a solo act.

If you go to the contributors graph on the GitHub repository — and I’ll link it in the show notes — you will see that the project has been carried by a small, generous group of people who have shown up over the years and made it better. Scott Harden, who you’d find on GitHub as swharden, I’ve already talked about. The others, in no particular order, are Compufreak345. spSlaine. miguelcrpinto. rohitjha. jpenny1993. NickNiebling. And michaelm2.

And then there is mkokabi.

mkokabi gets a special mention because they took the OwaspHeaders.Core source and built a version of it that works inside Azure Isolated Functions. It’s a separate project — OwaspHeaders.IsolatedFunction — and it lives at github.com/mkokabi/OwaspHeaders.IsolatedFunction. I’ll link it in the show notes so you don’t have to type it all in.

I never built that. I never planned for that. Somebody else took the work, looked at where it didn’t yet reach, and extended it themselves. That’s the version of success no one tells you to plan for when you start out. And it might be the single most flattering thing that has ever happened to one of my projects.

Eight years across ten major versions is, in the end, less about technical skill and more about everyone who showed up. My name’s on the package as the author. The work behind it isn’t all mine.

Call to Action and Close

So. Let me try to land this whole story in one paragraph.

What started as a failed pentest in 2016 became a four-part blog series in 2017. That blog series became a NuGet package. That NuGet package grew a CI pipeline on AppVeyor, then moved to GitHub Actions, then a release process that signs build attestations and proves its own provenance, with CodeQL scanning every commit and the OpenSSF Scorecard scoring it every week, and a passing best practices badge sitting on the repository. 1.7 million downloads.

Almost none of that was part of my formal education. I learned every single layer by trying it, getting some of it wrong, putting the wrong version on the internet, getting better the next time, and being shown the way by other developers who knew more than I did.

Which leaves me with two requests, depending on where you are.

If you are a developer who has ever thought about turning something you’ve built into a package — do it. The barrier is lower than you think. Start with a blog post if it helps. Show your work. That is exactly what I did, and the package grew straight out of that.

If you are already maintaining a package — go and look at build attestations, at the OpenSSF Scorecard, and at CodeQL. The TanStack postmortem from earlier this month is what happens when those defaults haven’t been adopted. Your users deserve to know they can trust you. And while you are at it, go and listen to episode 159 of this show with Scott Harden — that episode is the deep dive on every NuGet packaging best practice I’ve touched on in this episode.

If you’ve not heard part one of this series, go back and listen. It tells the story of the pentest, the OWASP project, and the headers themselves.

Thank you for listening. Be kind to yourselves, be kind to each other. I’ll see you in the next one.

Wrapping Up

Thank you for listening to this episode of The Modern .NET Show with me, Jamie Taylor. Let me know if you found this monologue interesting or useful. I’d love to know if you did, and whether you’d like me to create more of them.

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