1"use strict";(self.webpackChunkblog=self.webpackChunkblog||[]).push([[9198],{3149:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var o=n(6581),s=n(4848),i=n(8453);const r={title:"ASP.NET Core default project structure explained (part 1)",tags:["ASP-NET-CORE","JAVASCRIPT","TYPESCRIPT"],slug:"asp-net-core-project-structure-explained-part-1"},a="ASP.NET Core default project structure explained (part 1)",l={authorsImageUrls:[]},c=[{value:"Introduction",id:"introduction",level:2},{value:"Creating a New Web Project",id:"creating-a-new-web-project",level:2},{value:"Project Structure",id:"project-structure",level:2},{value:"1. Connected Services",id:"1-connected-services",level:3},{value:"2. Dependencies",id:"2-dependencies",level:3},{value:"3. Properties",id:"3-properties",level:3},{value:"4. wwwroot",id:"4-wwwroot",level:3},{value:"5. Areas",id:"5-areas",level:3},{value:"6. Data",id:"6-data",level:3},{value:"7. Pages",id:"7-pages",level:3},{value:"8. Root Folder Files",id:"8-root-folder-files",level:3},{value:"Program.cs",id:"programcs",level:4},{value:"application.settings",id:"applicationsettings",level:4},{value:"Startup.cs",id:"startupcs",level:4}];function d(e){const t={a:"a",blockquote:"blockquote",br:"br",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{src:n(1954).A+"",width:"1920",height:"1282"})}),"\n",(0,s.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)(t.p,{children:"When you start learning a programming language, one of your first exercises will probably be to write a \u201cHello World\u201d application to figure out the basic concepts.\nThis exercise works well if you\u2019re writing a simple console program that will only print out the greetings on the screen."}),"\n",(0,s.jsx)(t.p,{children:"However, once you move onto learning to write web apps using a new framework, such as ASP.NET Core, such a simple code is not enough \u2014 partially because web apps are more complex.\nAnd also because, right off the bat, the tools and frameworks used for writing web apps try to introduce advanced techniques and approaches for building and maintaining them once they scale."}),"\n",(0,s.jsx)(t.p,{children:"It all can seem like too much for a beginner.\nHere we will take apart the default ASP.NET Core solution template piece by piece, then figure out the purpose of each piece and how exactly it works."}),"\n",(0,s.jsx)(t.p,{children:"Please note that this isn\u2019t a full-scale tutorial on all the aspects of creating web apps in ASP.NET Core.\nRather, it is a short guide where you can check why a particular part is added to your project or find a piece of code and a link to the relevant documentation that explains it in detail."}),"\n",(0,s.jsx)(t.p,{children:"As an example, I used a new solution that targets .NET 5.\nHowever, most of this article's information will also be relevant for the ASP.NET Core projects that target .NET Core 3.1 or the upcoming .NET 6."}),"\n",(0,s.jsx)(t.h2,{id:"creating-a-new-web-project",children:"Creating a New Web Project"}),"\n",(0,s.jsx)(t.p,{children:"Let\u2019s start with creating a new empty web app with the \u201cCreate a new project\u201d wizard in Visual Studio."}),"\n",(0,s.jsx)(t.p,{children:"Here is how this step should look:"}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Create new project dialog in Visual Studio",src:n(2355).A+"",width:"1277",height:"841"})}),"\n",(0,s.jsx)(t.p,{children:"When you press Next, the wizard will ask you to choose the names of the new solution and project and the folder to place the solution files in:"}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Configure new project dialog in Visual Studio",src:n(5548).A+"",width:"1236",height:"809"})}),"\n",(0,s.jsxs)(t.blockquote,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Tip #1"}),": Place the project and the solution into separate folders. Choosing the same location for both is convenient only for very small applications. Once you start adding other layers to your solution (domain classes, data layers, API, etc.), having them in separate projects will be more practical."]}),"\n"]}),"\n",(0,s.jsxs)(t.blockquote,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Tip #2"}),": Use the general name of your application for the name of the solution (like \u201cMyCoolApp\u201d) and add the \u201c.Web\u201d suffix for the project name (e.g., \u201cMyCoolApp.Web\u201d)."]}),"\n"]}),"\n",(0,s.jsxs)("div",{id:"projectCreationFinalStep",children:[(0,s.jsx)(t.p,{children:"Finally, you will need to choose some additional project options."}),(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Additional information for the new project",src:n(168).A+"",width:"1022",height:"677"})}),(0,s.jsx)(t.p,{children:"The most important options here are:"}),(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Target Framework"}),". I suggest selecting the latest one (for the moment), .NET 5, but all the information in this article is relevant for .NET Core 3.1 or .NET 6 (it\u2019s in the pre-release state now) projects as well."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Authentication Type"}),". In this article, we suppose this option is set to ",(0,s.jsx)(t.em,{children:"Individual Accounts"}),". This value means that our new web project will contain some means for managing user accounts and provide UI for the basic authentication operations: Login, Registration, Reset Password, etc."]}),"\n"]}),"\n"]}),(0,s.jsx)(t.p,{children:'Let\'s click on "Create" when everything is set and get our new solution.'})]}),"\n",(0,s.jsx)(t.h2,{id:"project-structure",children:"Project Structure"}),"\n",(0,s.jsx)(t.p,{children:"After finishing the steps described above, you will get a new solution with one project inside it."}),"\n",(0,s.jsx)(t.p,{children:"The structure of that project will look similar (or even the same) to the following one:"}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Default ASP.NET Core project structure",src:n(9034).A+"",width:"305",height:"301"})}),"\n",(0,s.jsx)(t.p,{children:"Let\u2019s take a closer look at each part of your new project."}),"\n",(0,s.jsx)(t.h3,{id:"1-connected-services",children:"1. Connected Services"}),"\n",(0,s.jsx)(t.p,{children:"This is the first node in your project\u2019s structure and possibly the less-used one.\nIt is intended to automate the multiple steps
1necessary to connect a project to an external service (like Azure Storage or Application Insights).\nYou can right-click on this node and select \u201cAdd connected service\u2026\u201d to run a wizard that will lead you through the process.\nUsually, it just adds necessary packages and gives you basic instructions on how to start using your app's service.\nAs I\u2019ve already mentioned, there is a good chance you will not use this node during your project\u2019s lifetime."}),"\n",(0,s.jsx)(t.h3,{id:"2-dependencies",children:"2. Dependencies"}),"\n",(0,s.jsx)(t.p,{children:"This element of your project structure contains all packets or other projects on which your project depends."}),"\n",(0,s.jsx)(t.p,{children:"There are four main folders inside this node:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Analyzers"}),(0,s.jsx)(t.br,{}),"\n","They help you make your code better: cleaner, error-free. Each analyzer checks that your code satisfies a list of rules incorporated in it. If any part of your co
1de does not apply to one of the rules, you will see either a Warning or an Error while you build your project."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"Please note that analyzers work only at compile time and do not affect your resulting application."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Frameworks"}),(0,s.jsx)(t.br,{}),"\n","This folder contains a list of frameworks your project depends on. This information is important if you ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/dotnet/core/deploying/",children:"publish your web app as a runtime-dependent"})," (as opposed to a self-contained one). In this case, all the frameworks listed here must be installed on the server where you will run your app."]}),"\n"]}),"\n",(0,s.jsxs)(t.blockquote,{children:["\n",(0,s.jsxs)(t.p,{children:["NB: You can use ",(0,s.jsx)(t.code,{children:"dotnet --info"})," console command to check the list of installed frameworks.*"]}),"\n"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Packages"}),(0,s.jsx)(t.br,{}),"\n","This is the main item in this node. It lists all NuGet packages you added (installed) to your project. If any of those packages depend on other packages, they will be installed automatically and listed as sub-nodes of the root-level packages. You can remove each installed package here (right-click / Remove)."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Projects"}),(0,s.jsx)(t.br,{}),"\n","This is the list of other projects in this solution your current project depends on.\nYou can reference other projects using the \u201cAdd reference\u201d command from the right-click menu.\nObviously, this node is empty now since we have only one project in the solution."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"3-properties",children:"3. Properties"}),"\n",(0,s.jsx)(t.p,{children:"This part contains different properties of your project that you can modify by double-clicking on this node in the Solution Explorer. Most of the properties there affect the compile- and debug-time behavior of your project."}),"\n",(0,s.jsx)(t.p,{children:"The only item inside this node is a \u201claunchSettings.json\u201d file containing the launch profiles. Each profile defines how to run your project when you click on the \u201cRun\u201d button in Visual Studio."}),"\n",(0,s.jsx)(t.h3,{id:"4-wwwroot",children:"4. wwwroot"}),"\n",(0,s.jsx)(t.p,{children:"This folder contains all the static files of your web application: CSS files, JavaScript files, images, and icons.\nAs you might figure out from its name, this will be the root folder of your web app.\nSo if you put an \u201cimage1.png\u201d file into the \u201cwwwroot/images/dir1\u201d folder, it will be accessible in the browser by the \u201c/images/dir/image1.png\u201d address."}),"\n",(0,s.jsx)(t.h3,{id:"5-areas",children:"5. Areas"}),"\n",(0,s.jsx)(t.p,{children:"This folder is added because we selected the \u201cIndividual Accounts\u201d value for the \u201cAuthentication Type\u201d option when created the project."}),"\n",(0,s.jsxs)(t.p,{children:["In addition to the core authentication/authorization packages (which is called ASP.NET Core Identity), the default template also adds the \u201cMicrosoft.AspNetCore.Identity.UI\u201d package. This is a Razor-class library that contains all forms and partial views for authentication and user management: Login, Registration, Reset Password, User Profile, and many others.\nAll these forms will use your layout (defined in ",(0,s.jsx)(t.em,{children:"Pages/Shared/_Layout.cshtml"}),") and so will match your website\u2019s design."]}),"\n",(0,s.jsxs)(t.p,{children:["However, you still might want to change some of those forms (or even all of them).\nIn this case, you can use the Scaffold command and add the necessary files to your project. The scaffolded files will be added to the ",(0,s.jsx)(t.em,{children:"Areas/Identity"})," folder."]}),"\n",(0,s.jsx)(t.h3,{id:"6-data",children:"6. Data"}),"\n",(0,s.jsx)(t.p,{children:"As in the previous case, this folder appears in our new project because of the \u201cAuthentication Type\u201d option that was turned on at the beginning."}),"\n",(0,s.jsxs)(t.p,{children:["By default, all user-related information (users, their roles, claims, etc.) is stored in a database accessed with ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us
1/ef/core/",children:"Entity Framework Core"})," ORM (object-relational mapping) framework. If you are not familiar with EF Core, you can find a lot of tutorials on ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/ef/core/get-started/",children:"Microsoft Docs"}),"."]}),"\n",(0,s.jsx)(t.p,{children:"The \u201cData\u201d folder contains your DB context class named \u201cApplicationDbContext.\u201d This class is derived from the \u201cIdentityDbContext\u201d class defined in the \u201cMicrosoft.AspNetCore.Identity.EntityFrameworkCore\u201d assembly, and it includes all DB sets (tables) necessary to store user-related information."}),"\n",(0,s.jsx)(t.p,{children:"You can use this class or create another DbContext class to add your models."}),"\n",(0,s.jsx)(t.p,{children:"Additionally, the \u201cData\u201d folder also includes \u201cMigrations\u201d sub-folder with all your Entity Framework Core migrations."}),"\n",(0,s.jsx)(t.h3,{id:"7-pages",children:"7. Pages"}),"\n",(0,s.jsxs)(t.p,{children:["This folder contains all pages (forms) of your web applications. ASP.NET Core has two default approaches for content rendering: MVC (Model View Controller) and ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/aspnet/core/razor-pages",children:"Razor Pages"})," (which is, actually, a kind of MVC, where each controller and the corresponding view are stored together). Both approaches use ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/aspnet/core/mvc/views/razor",children:"Razor syntax"})," that you can think of as HTML + C#."]}),"\n",(0,s.jsx)(t.p,{children:"Each Razor page is represented by a \u201c.cshtml\u201d file. The code related to it is stored in a so-called \u201ccode-behind\u201d file with the same name and a \u201c.cshtml.cs\u201d extension."}),"\n",(0,s.jsx)(t.p,{children:"From the start, the \u201cPages\u201d folder contains a few default pages, such as Index (the home page of your web app), Privacy, and Error. Additionally, you can find the main layout file (_Layout.cshtml) and some partial views in the \u201cPages/Shared\u201d folder."}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"NB"}),": It\u2019s a common practice to prefix the names of the layouts and partial views with ",(0,s.jsx)(t.code,{children:"_"})," symbol."]}),"\n",(0,s.jsx)(t.h3,{id:"8-root-folder-files",children:"8. Root Folder Files"}),"\n",(0,s.jsx)(t.p,{children:"Now, when we\u2019ve looked over all the main folders created with the default ASP.NET Core application template, let\u2019s take a closer look at the files stored in the project\u2019s root folder. They are the most important part of the project."}),"\n",(0,s.jsx)(t.h4,{id:"programcs",children:"Program.cs"}),"\n",(0,s.jsx)(t.p,{children:"This file defines the \u201cProgram\u201d class with one static method, \u201cMain,\u201d which is the entry point of your web application."}),"\n",(0,s.jsxs)(t.p,{children:["The only purpose of this method is to define the ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/?view=aspnetcore-3.1#host",children:"host"})," and then pass the control to the Startup class. For more information about the default host builder, look at an article about ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host",children:"Generic Host"})," on Microsoft\u2019s Docs."]}),"\n",(0,s.jsx)(t.h4,{id:"applicationsettings",children:"application.settings"}),"\n",(0,s.jsx)(t.p,{children:"This is a JSON file that stores the application\u2019s settings. The settings have a hierarchical structure and can be accessed with the Configuration object defined in the Startup class or in any other place of your program where you injected IConfiguration service. For example:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:'var defaultLogLevel = Configuration.GetValue<string>("Logging:LogLevel:Default");\n'})}),"\n",(0,s.jsxs)(t.p,{children:["The different levels of hierarchy are separated by the colon (",(0,s.jsx)(t.code,{children:":"}),") symbol."]}),"\n",(0,s.jsxs)(t.p,{children:["By default, in addition to \u201capplication.settings\u201d, the ASP.NET Core template also includes an \u201capplication.Development.settings\u201d file.\nThe settings defined in this file are loaded only into the Development environment and are not available in production.\nTo learn more about the \u201c.settings\u201d files and configuration in ASP.NET Core projects in general, please read ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us
1/aspnet/core/fundamentals/configuration/",children:"this article"})," on Microsoft\u2019s Docs."]}),"\n",(0,s.jsx)(t.h4,{id:"startupcs",children:"Startup.cs"}),"\n",(0,s.jsx)(t.p,{children:"This is the final part of the ASP.NET Core project\u2019s structure. The \u201cStartup\u201d class serves three main purposes:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:"It performs all initialization tasks (setting application-wide constants, DB seeding, migrations, etc.)."}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["It registers all services used in this project in the ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection",children:"DI (dependency injection) container"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["It defines the ",(0,s.jsx)(t.a,{href:"https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection",children:"middleware pipeline"})," of your web-application."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"This class contains a lot of code (as for a project that has just been created) from the beginning and will become even bigger when you start adding new features to your application."}),"\n",(0,s.jsxs)(t.p,{children:["We will take a look at it in more detail in the ",(0,s.jsx)(t.a,{href:"asp-net-core-project-structure-explained-part2",children:"next article"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},1954:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/computer-coffee-01-a7e2ae32ba982b004b23d7282738dc5d.jpg"},5548:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/configure-project-dlg-65dcd774eb05a670e8b3c0ec8197755c.png"},2355:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/create-new-project-dlg-f293c181a454d844f19b7dc618cab490.png"},9034:(e,t,n)=>{n.d(t,{A:()=>o});const o=n.p+"assets/images/default-asp-net-project-structure-4205075f264d2c23cd63b1c974d70a19.png"},168:(e,t,n)=>{n.d(t,{A:()=>o});
1const o=n.p+"assets/images/project-additional-info-a0828b7b4bd4cede3dd83121c611b712.png"},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var o=n(6540);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}},6581:e=>{e.exports=JSON.parse('{"permalink":"/blog/asp-net-core-project-structure-explained-part-1","source":"@site/blog/2020-05-23-asp-net-core-project-structure-explained-part-1/index.md","title":"ASP.NET Core default project structure explained (part 1)","description":"Introduction","date":"2020-05-23T00:00:00.000Z","tags":[{"inline":true,"label":"ASP-NET-CORE","permalink":"/blog/tags/asp-net-core"},{"inline":true,"label":"JAVASCRIPT","permalink":"/blog/tags/javascript"},{"inline":true,"label":"TYPESCRIPT","permalink":"/blog/tags/typescript"}],"readingTime":9.055,"hasTruncateMarker":true,"authors":[],"frontMatter":{"title":"ASP.NET Core default project structure explained (part 1)","tags":["ASP-NET-CORE","JAVASCRIPT","TYPESCRIPT"],"slug":"asp-net-core-project-structure-explained-part-1"},"unlisted":false,"prevItem":{"title":"ASP.NET Core default project structure explained (part 2)","permalink":"/blog/asp-net-core-project-structure-explained-part2"},"nextItem":{"title":".NET vs. Java - Which Platform Is Better for Your Software Developer Career?","permalink":"/blog/dotnet-vs-java-what-development-platform-better"}}')}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.