Warning:
Most of this will be .NET core stuff, since that is where I am starting with my learning / first project. I tend to focus on web stuff, so notes will probably also be heavy on the ASP.NET MVC side of things vs Mono / apps.
I also tend to make a lot of comparisons to other frameworks, especially Laravel, as I see a lot of overlap (.NET CLI vs Artisan, Razor vs Blade, etc.)
Resources
What | Type | Link |
---|---|---|
My C# Cheatsheet | Cheatsheet | Link |
.NET Videos | Video Series | .NET Learning Center |
Breakdown of JSON config files in a .NET Core project | Guide | TalkingDotnet |
Default .gitignore | Documentation | .gitignore |
.NET Core MVC Overview | Overview Guide | MSDocs |
awesome-dotnet-core | Collection | Github |
How to run / where is my package.json
?
Typically .NET apps have the parts of a normal node/JS package.json
file broken up into different parts and files.
- Dependencies
- Managed through either
{ProjectName}.csproj
(project file) orpackages.config
- Within a
.csproj
file, NuGet packages are referenced by<PackageReference Include="" Version="" />
XML
- Within a
obj/project.assets.json
is equivalent topackage-lock.json
, but unlike the typical recommendation for NPM, MS recommends that you do not commit this file to VC.
- Managed through either
- Tasks
- Things like building and launching are normally handled through the .NET CLI commands, and it would be up to you to integrate a task handler (like grunt) if you wanted to automate those commands
- However
Properties/launchSettings.json
does affect how those CLI commands execute - Many IDE's will create their own task config files when it notices you are trying to run a C#/DotNet app. These files usually just automate the running of CLI commands. For example, VSCode will create two files:
.vscode/launch.json
.vscode/tasks.json
- However
- Things like building and launching are normally handled through the .NET CLI commands, and it would be up to you to integrate a task handler (like grunt) if you wanted to automate those commands
- Version # / Meta information about your own project
- Should be in your
{ProjectName}.csproj
(project file) - You can add tons of key pairs under
PropertyGroup
:<PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <Authors>Larry Fine</Authors> <Company>Howard, Howard, and Fine INC</Company> <Copyright>Copyright 2019</Copyright> <!-- etc --> </PropertyGroup>
- Full list of respected metadata inputs here
- Should be in your
An actual NPM package.json
file might or might not exist in your project depending on how you scaffolded the project and what the stack looks like. If it was not generated / included, there is nothing stopping you from adding one yourself; just keep in mind how Core handles the stuff above.
Hot rebuilding / hot reloading
The new .NET core CLI includes a command for file watching and hot-rebuilding:
dotnet watch run
However, that only handles the live-rebuilding of the server-side stuff; it won't auto-refresh your browser window like other hot-reload tools. To do that, you need to add an external dependency, the recommended tool being browsersync
. You can find instructions for this step here.
Scaffolding / creating solutions
Similar to other in-all-one frameworks like Laravel, .NET has a substantial amount of boilerplate scaffolding. If you are using Visual Studio (note: not VSCode), the recommended way to create new things is with the Solution Explorer. For example, if you are building a MVC app and wanted to add a new Controller, you would select Controllers > Add > Controller
, and then pick a Add Scaffold
type (empty, API controller, pre-wired to EF, etc.).
Without Visual Studio, for example if you are using VSCode, there are two possible ways to accomplish the same thing as above. The first is to just manually create your files by hand; this is what some of the official guide pages recommend (for example, to add a controller). However, this really is not the same thing as a scaffolding, now is it?
Another option is to install a special scaffolding CLI tool. The tool of choice seems to be aspnet-codegenerator
, and a guide for its initial setup can be found here or here. Once it is installed and setup, you can call it from the command line and scaffold most of the same types that you would normally use the Solution Explorer for if you had Visual Studio installed. For example, to accomplish the task of adding a controller, we might use something like:
dotnet aspnet-codegenerator controller \
-name UserController \
-api \
[... more options]
.NET Core MVC or API
Example projects
- .NET API Backend (not frontend)- gh search
- https://github.com/AnkitSharma-007/CRUD.ASPCore.Reactjs.WebAPI.EF
- https://github.com/mdamyanova/ASP.NET-Core-ReactJS-Example
- https://github.com/magicxor/AspNetReactReduxTodo
- https://github.com/borschetsky/WebChat
- https://github.com/jmpichardo/aspnet-core-react-redux-boilerplate
- https://github.com/cornflourblue/aspnet-core-jwt-authentication-api
- https://github.com/santiagorp/auth0-spa-api-ae
- https://github.com/cornflourblue/aspnet-core-registration-login-api
- https://github.com/mmacneil/AspNetCoreApiStarter
Using .NET API as backend with SPA frontend
There is built-in scaffolding to build this out. For example, dotnet new react -au Individual
will create React project with built-in authorization. See this page for details.
If you want to custom build everything yourself, you can still use .NET to serve the static SPA files. Know how to use these things:
services.AddSpaStaticFiles
app.UseStaticFiles
app.UseSpaStaticFiles
app.UseSpa
Here is a guide for getting this to work with Vue.
Guides:
EF Core
General initial steps:
- Install nuget packages (EF Core & the driver you need, such as SQLite)
- Create DbContext based class to provide DB connection
- Set connection string (either through DbContext or startup)
- Add DbContext through
Startup.cs
->services.addDbContext<{YourDbContextClass}>();
- Make migration files
dotnet tool install --global dotnet-ef
&dotnet add package Microsoft.EntityFrameworkCore.Design
(one time install)dotnet ef migrations add InitialCreate
- Run initial migration:
dotnet ef database update
Common commands- see EF Core Tools CLI reference
- Help
dotnet ef -h
Data Context Class & Objects
Docs:
As I understand it, a Data Context
is a short-lived instance (aka session
) that represents the connection established between a database (such as SQL) and the running code itself. A Data Context Class
is what defines the generic parameters of this context, and does so by implementing the system.IDisposable
interface, or in the case of EF6, implements DbContext
which implements system.IDisposable
.
It exposes direct methods to use the DB, such as executeQuery()
, or certain framework components, such as Entity Framework, wrap the connection in further methods and exposed interfaces.
This is pretty similar to other languages and frameworks; it is very common with databases to have a class that abstracts the startup and teardown process of handling a DB connection.
ORM
Most of the docs and solutions will point you towards using EF (Entity Framework) as your ORM. However, most people will recommend that, if you are concerned about performance, you switch to using Dapper (built by StackExchange).
See this,and this, and Dapper's own performance measurements here.
Authentication
Pretty much anything having to do with .NET Core auth is going to involve the Microsoft.AspNetCore.Identity
namespace and dependencies, and this is the general starting spot.
If you want to use automatic scaffolding, you can either do it while setting up a brand new project, or use the solutions explorer -> add -> identity.
Some standard considerations:
- The user model should extend
IdentityUser
- Startup.Configure should call
app.UseAuthentication()
- Also
app.UseIdentityServer()
if using OpenID
- Also
- Startup.Services should call
services.AddDefaultIdentity
orservices.AddIdentity
.AddEntityFrameworkStores
- No matter how you scaffolded (or didn't) identity, you will also need to make EF migrations:
dotnet ef migrations add CreateIdentitySchema
dotnet ef database update
See this, this, and this for guides on manual overrides.
API controllers and routing
Returning JSON
public JsonResult get(int id){
return Json(new {
keyAlpha = "valueAlpha",
keyBeta = "valueBeta"
});
}
Reading POST form data
The default syntax for using [FromBody]
is rather misleading...
[HttpPost]
public void Post([FromBody] string name) {
User user = new User { Name = name };
}
If you make a typical POST with a JSON body that looks like this:
{
"name": "Mad Hatter"
}
The value of name
will actually be null! This is because, if there is only one parameter taken in via FromBody
, .NET expects that the body of the POST is not json
, but instead is just the value. See this S/O.
So how do you accept complex bodies? You have a few options...
Use a model
Assuming you have a model setup to mirror the body, you can map the POST body to the model easily:
[HttpPost]
public void Post([FromBody] User userFromPost) {
// No code needed! `userFromPost` is ready to use!
}
Be very careful about this sort of direct model binding though; this allows all properties of the bound model to be set via API request, whereas you might want certain things (user.isAdmin
) to be read-only via API. In this case, use one of the solutions outlined here, or manually instantiate a new object and map the input:
[HttpPost]
public void Post([FromBody] User data) {
User user = new User { Name = data.Name };
}
Manual parsing
If you don't declare any arguments, you can read off raw things from the request, like Request.Body
, or Request.Headers
, and so on.
Example:
using Newtonsoft.Json;
using System.Text;
// ...
[HttpPost]
public async void Post() {
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
string bodyText = await reader.ReadToEndAsync();
User userJson = JsonConvert.DeserializeObject<User>(bodyText);
User user = new User { Name = userJson.Name };
}
}
See this in-depth post that explains this in detail.
Accessing appsettings.json values inside classes
See StackOverflow (1) and MSDocs
Dependency Injection (DI)
Dependency Injection, often just referred to as DI, is a concept common both in and outside of .NET and C#. Please see my notes here
Logging
Usually, if you are starting with a scaffolded app, VisualStudio will have already included the standard MS logging packages, such as Microsoft.Extensions.Logging
.
To use the standard logging library, you need to add the namespace, and either take an instance of the logger via DI, or via LoggerFactory
instantiation.
public class HomeController : Controller {
private readonly ILogger _logger;
public HomeController(ILogger<HomeController> logger) {
_logger = logger;
}
}
Visual Studio stuff
Moving .sln (solution) file
- Open the file and edit the path string
- Delete any
.suo
files in dir (they will be hidden files, and will rebuild on relaunch)
CLI
Troubleshooting
Use -v
"verbose" flag with many commands for more details, such as failed migrations