Goodbye .csproj Say Hello to One-File C# Apps

Goodbye .csproj Say Hello to One-File C# Apps

If you’re like me, you’ve spent years editing .csproj files, adding NuGet packages, tweaking build settings, juggling multi-targeting configurations…

It’s part of the job. But what if I told you that for many scenarios, you don’t need a .csproj file anymore?

With .NET 10 you have no folder structure, no boilerplate. Just a single app.cs file and a dotnet run command.

In this post, we’ll explore how this new approach works, when you should (and shouldn’t) use it, and why this seemingly small change might be one of the most developer-friendly features introduced in .NET lately.

Why This Is a Great Update

This feature isn’t intended to completely replace .csproj. But in some use cases, with small scripts or simplified development, it’s very useful.

This is part of a broader push by Microsoft to simplify how we build apps with .NET. Too much boilerplate and configuration has kept some developers from starting with the language, some are starting to say it’s feeling like a mix of Python and JavaScript, 

Whether that’s good or bad depends on your use case, but it’s clear .NET is becoming more flexible, especially for newcomers.

You don’t need to scaffold a project just to test a few lines of code, just one .cs file and:

				dotnet run app.cs
			

It’s ideal for:

  • quick experiments

  • automation scripts

  • teaching scenarios

  • trying out APIs

And yes, you still get full C# 13, top-level statements, and access to all .NET APIs, without bootstrapping a full app.

How to use it

Create a simple C# file:

C#
				Console.WriteLine("Hello from a file without .csproj!");

			

Save it as app.cs and run:

				dotnet run app.cs
			

This works anywhere the .NET SDK is installed, no need for IDEs or build tools.

You can add NuGet packages to a single C# file using the new #:package directive.

Here’s an example using Humanizer:

C#
				#:package Humanizer@2.*

using Humanizer;

Console.WriteLine(1234.ToWords());
			

IntelliSense in most IDEs (including VS and Rider) doesn’t fully support #:package yet. You might see false “unresolved type” warnings. For now, you’ll need to know the API or refer to docs manually. Full support will likely come in future updates.

Just run dotnet run once, and the errors go away.

But what if I want to build a Minimal API?

Yes, you can, and it’s actually supported.

Just like with console apps, all you need is a single file, you have to declare the correct SDK write the code and run:

C#
				#:sdk Microsoft.NET.Sdk.Web

var builder = WebApplication.CreateBuilder();

var app = builder.Build();

app.MapGet("/", () => "Hello from Minimal API");

app.Run();
			

That’s it…

 

What if I want to migrate to a project?

Started with app.cs and want to scale it up? You don’t need to recreate anything manually.

Just run:

				dotnet project convert app.cs
			

This command analyzes your .cs file, reads the #:sdk and #:package directives, and generates a proper .csproj file with all dependencies included.

ASP.NET (C#)
				<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Humanizer" Version="2.*" />
  </ItemGroup>
</Project>
			

This makes it easy to start small and grow as needed, without losing the simplicity of the initial script.

You keep the speed of a one-file prototype, and gain the structure of a full-blown project when you need it.

Final thoughts

.NET is becoming more flexible without compromising power. And that’s a step in the right direction.

Running .cs files directly with dotnet run isn’t here to replace projects, but it solves a different problem: lowering the barrier to writing and running C# code fast.

For seasoned devs, it’s a fast way to prototype without scaffolding.
For those starting out, it removes unnecessary barriers, write code, run it, and focus on learning the language.

Less time. More code. That’s a win.

Thank you for reading.

See you next time!

Share the Post:
plugins premium WordPress