Skip to content

Instantly share code, notes, and snippets.

@davidfowl
Last active April 18, 2024 23:31
Show Gist options
  • Save davidfowl/ed7564297c61fe9ab814 to your computer and use it in GitHub Desktop.
Save davidfowl/ed7564297c61fe9ab814 to your computer and use it in GitHub Desktop.
.NET project structure
$/
  artifacts/
  build/
  docs/
  lib/
  packages/
  samples/
  src/
  tests/
  .editorconfig
  .gitignore
  .gitattributes
  build.cmd
  build.sh
  LICENSE
  NuGet.Config
  README.md
  {solution}.sln
  • src - Main projects (the product code)
  • tests - Test projects
  • docs - Documentation stuff, markdown files, help files etc.
  • samples (optional) - Sample projects
  • lib - Things that can NEVER exist in a nuget package
  • artifacts - Build outputs go here. Doing a build.cmd/build.sh generates artifacts here (nupkgs, dlls, pdbs, etc.)
  • packages - NuGet packages
  • build - Build customizations (custom msbuild files/psake/fake/albacore/etc) scripts
  • build.cmd - Bootstrap the build for windows
  • build.sh - Bootstrap the build for *nix
  • global.json - ASP.NET vNext only

.gitignore

[Oo]bj/
[Bb]in/
.nuget/
_ReSharper.*
packages/
artifacts/
*.user
*.suo
*.userprefs
*DS_Store
*.sln.ide

There's probably more things that go in the ignore file.

  • Update: Added docs folder
  • Added README.md and LICENSE - Critical if you're OSS, if not ignore it
  • Renamed test to tests
  • Added lib for things that CANNOT exist in nuget packages
  • Removed NuGet.config for people using packet :)
  • Added global.json for ASP.NET vnext
  • Added .editorconfig file in the root (x-plat IDE settings)
  • Added NuGet.config back because people were confused about it missing
@sharpninja
Copy link

Is there a repo I can clone?

@tiny-dancer
Copy link

+1 to @kirkone

@davidfowl, i think it's time to evolve into a full repo :) similar to https://github.com/golang-standards/project-layout

@TheAngryByrd
Copy link

@sharpnina @tiny-dancer Take a look at MiniScaffold creates a repo via dotnet template. It's starts with F# but you can move over to C# pretty easily.

@virzak
Copy link

virzak commented Aug 21, 2020

Pretty sure these two are extremely common:

  • CHANGELOG.md
  • Directory.Build.props

Less common are:

  • git-hooks/
  • package.json
    • For packages like husky to run commit hooks like dotnet format for c# code and xstyler for xaml

@D3MaxT
Copy link

D3MaxT commented Aug 26, 2020

@davidfowl
Hello David.
Where would you recommend putting a self-signed ROOT certificate that gets added to docker images in local development only? Would that go under build or something else?

Thank you.

@sharpninja
Copy link

@davidfowl
Where would you recommend putting a self-signed ROOT certificate that gets added to docker images in local development only? Would that go under build or something else?

I would not put them in GIT, and GitHub may even block them. Instead, create a powershell script to create and register the cert and place it's path in an environment variable, then have the Dockerfile get the file path from the environment.

@D3MaxT
Copy link

D3MaxT commented Aug 26, 2020

@davidfowl
Where would you recommend putting a self-signed ROOT certificate that gets added to docker images in local development only? Would that go under build or something else?

I would not put them in GIT, and GitHub may even block them. Instead, create a powershell script to create and register the cert and place it's path in an environment variable, then have the Dockerfile get the file path from the environment.

Hello sharpninja,
I appreciate the response, but I am not sure this would work. This cert gets added to each image by using a dockerfile.dev and then the docker.compose file builds that docker dev file during local development only. So it uses a COPY instruction to copy the certificate into the image and a RUN instruction to run update-ca-certificates on the Debian Linux used by the container. As far as I know, you can't do this with PowerShell. Also, as far as I know, you can't use COPY with files outside of the docker build context, so you can't use files outside the directory where the docker files are.

I could not find a better way of getting a self-signed certificate into a docker image, so the certificate is included in the Solution (it's a public only side, no private key, so I don't mind putting into a Git repo).

Thank you.

@sharpninja
Copy link

As far as I know, you can't do this with PowerShell.

There is quit literally nothing you cannot do with PowerShell. Read about New-SelfSignedCertificate which generates a cert you can keep locally and include in your Dockerfile.

@gigi81
Copy link

gigi81 commented Apr 2, 2021

Hi, I created a tool to automate this process https://github.com/gigi81/dotnet-newrepo/
It doesn't include everything mentioned here but most of it is there. I would appreciate anyone taking the time to try it and give some feedback. In short here is how to use it (more details on the readme of the project):

dotnet tool install dotnet-newrepo --global

#first create a directory host your repo
mkdir Organization.Project
cd Organization.Project
#then create the init.yml file (this file is used to specify a few settings like your github username/repo)
newrepo init
#customize the init.yml file with your custom settings
notepad init.yml
#then finally create the repo
newrepo

@agilenut
Copy link

agilenut commented Apr 19, 2021

@davidfowl - Curious if you still consider this current or if there are some lessons learned since it was created.

@ShreyasJejurkar
Copy link

I created a .NET CLI tool for this => https://github.com/MCCshreyas/Project

@tombohub
Copy link

how do you organize src folder?

@sarvasana
Copy link

By dragging files and folders around until you are happy.

@fgimian
Copy link

fgimian commented Jul 12, 2021

This is a great starting point, thanks!

For generating the gitignore file, you can always use the dotnet CLI as follows;

dotnet new gitignore

Also, I think we should pretend batch scripts never existed and always assume that it will be a PowerShell script build.ps1 that starts the build 😄 PowerShell is a significantly more robust scripting language and well worth knowing IMHO.

I think it also would be good to clarify whether sub-directories should be present in src and tests if there's only one project. For example, dotnet-format places the project at the root of src and tests directories which may be appropriate if only one project is present, but is this a good approach?

Huge thanks for the gist 😄
Fotis

@ambrosektal
Copy link

Can someone help me understand this? What is an example of:
"lib - Things that can NEVER exist in a nuget package"?
I thought I could build a nuget package to hold anything?

@fvilches17
Copy link

Hi @davidfowl thanks for sharing. Where would you put pipeline-related files? (e.g. azure-pipelines.yaml, resource-group.bicep, etc.)

@jedjohan
Copy link

Hi @davidfowl thanks for sharing. Where would you put pipeline-related files? (e.g. azure-pipelines.yaml, resource-group.bicep, etc.)

Sorry not David but a tip:

  • we put pipelines in /build (yaml pipes)
  • we put IaC (.bicep) in a folder named /infra

@fgimian
Copy link

fgimian commented Aug 19, 2021

I have a further thought too. I realise I'm in the absolute minority here, but I find it odd that we shorten source to src and libraries to lib yet there's no good reason to do this and we don't do this for any other folder. This really feels more historical than logical to me personally and doesn't make my OCD happy 😄

As such, I'm personally using source as my source folder ... does that make me a bit of an outcast? 😨

I personally put my azure-pipelines.yaml in the root folder but agree that it probably would be better in the build directory.

@fvilches17
Copy link

Hi @davidfowl thanks for sharing. Where would you put pipeline-related files? (e.g. azure-pipelines.yaml, resource-group.bicep, etc.)

Sorry not David but a tip:

  • we put pipelines in /build (yaml pipes)
  • we put IaC (.bicep) in a folder named /infra

👍

@TechWatching
Copy link

If your git repository also contains the frontend that consumes the dotnet API, where would you put the front code? The application code in /src and the tests code in /tests ?

@jedjohan
Copy link

jedjohan commented Nov 7, 2022

If your git repository also contains the frontend that consumes the dotnet API, where would you put the front code? The application code in /src and the tests code in /tests ?

Sorry not David again but an opinion:
1: keep it in a separate repo
2: if #1 not possible --> create folders below src: src/backend + src/frontend

@fvilches17
Copy link

Just a matter of preference of course, but since all ci-cd related files are used in an Azure/Azure DevOps context, I've started having a preference to putting yaml and bicep files in a folder called .azuredevops

I got the idea from GitHub actions' default root folder (.github)

@TechWatching
Copy link

If your git repository also contains the frontend that consumes the dotnet API, where would you put the front code? The application code in /src and the tests code in /tests ?

Sorry not David again but an opinion: 1: keep it in a separate repo 2: if #1 not possible --> create folders below src: src/backend + src/frontend

src/projectname.api and src/projectName.Front is what I did. But it felt weird to do the same for tests : tests/projectName.api.Tests tests/projectName.Front.Test

Just a matter of preference of course, but since all ci-cd related files are used in an Azure/Azure DevOps context, I've started having a preference to putting yaml and bicep files in a folder called .azuredevops

I got the idea from GitHub actions' default root folder (.github)

@fvilches17 I understand your point, but I am personally not a big fan of using dot folders that are platform specific. You are right, that's how github does it and if your ci-cd related files are only used in an Azure/Azure DevOps context, maybe it makes sense in your context.
However, I think that infrastructure files, ci files, or cd files should not be stored in a folder dependent on the platform (even if for github they don't really let you the choice).

Because maybe someday you will migrate from Azure DevOps to another platform, your application could be multi-cloud (with some resources in one cloud, and other in another) or even if it's an azure only application it coud use specific services (authentication, monitoring ...) outside Azure. Moreover, CI/CD files could contain other files than the Azure pipelines YAML files like scripts, configuration files, or even code files. That's why I prefer using an "infra" folder, a "build" or "pipelines" folder .... By the way, by default Azure Developer CLI (preview) uses an infra folder.

@mcintyre321
Copy link

If your git repository also contains the frontend that consumes the dotnet API, where would you put the front code? The application code in /src and the tests code in /tests ?

If UI and backend are worked on by the same team/organisation, they are the same app, and they should be versioned together (i.e. in the same repo) and deployed together.

@TechWatching
Copy link

If your git repository also contains the frontend that consumes the dotnet API, where would you put the front code? The application code in /src and the tests code in /tests ?

If UI and backend are worked on by the same team/organisation, they are the same app, and they should be versioned together (i.e. in the same repo) and deployed together.

I agree, I was just wondering what it means for the folder organization.

@mcintyre321
Copy link

mcintyre321 commented Nov 7, 2022 via email

@fvilches17
Copy link

thought I'd share,

this is the structure I follow for some projects. you can imagine that at root, besides the .azuredevops folder, there's src, test etc. folders

the name .azuredevops was chosen because back in Azure DevOps when you place a pull_request_template.md file in a folder with set name, then the repo's PR descriptions use the content of that file, pretty much used like a template for PR descriptions

however, the name can be anything of course. e.g. something generic like .devops

folder structure

@peteraritchie
Copy link

This thread makes me think there are several intents within the discussion. Is @davidfowl 's intent to outline a dotnet project for a monorepo, for deployment to custom infrastructure, for delivery of a package, etc.?

@agilenut
Copy link

This thread makes me think there are several intents within the discussion. Is @davidfowl 's intent to outline a dotnet project for a monorepo, for deployment to custom infrastructure, for delivery of a package, etc.?

My 2 cents:

I follow this structure when I'm not building a monorepo.

When I do build a monorepo, I wrap this structure in another set of folders at the root of the repository (one for each service, library, or app). But I might keep a few things like shared build pipelines, docs, and editorconfig in the root.

@tonidy
Copy link

tonidy commented Jun 4, 2023

@sharpninja @tiny-dancer I've created https://github.com/dotnet-template/project-layout, feel free to fork it and maybe contribute to it.

@aspeckt-112
Copy link

Could someone please explain to me the difference between putting nupkgs in the artefacts directory vs the packages directory?

@Layoric
Copy link

Layoric commented Jan 26, 2024

My understanding is the Artefacts is the output of your project, much could include NuGet packages, packages directory contains your projects dependencies.

@aspeckt-112
Copy link

Ahhh OK. For when a packages.config is being used. Not applicable to me and I think I was tunnel visioning past it.

Thanks, @Layoric

@oxygen
Copy link

oxygen commented Apr 12, 2024

@D3MaxT
Never distribute [the same] private cert to multiple distinct clients, even if you do it securely - you might as well drop encryption altogether.
For self signed certificates just generate them on the client machine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment