Installation was amazingly easy. < 2 minutes and dotnet
is available from the command line.
Don't forget to install the c# plugin for VS Code (powered by omnisharp).
Omnisharp ships with the C# plugin, and there is configuration to use a globally installed mono
. I did have mono installed but Omnisharp barfed with it. I uninstalled mono and changed the VS Code settings (search for mono
) to never
use globally installed Mono. Works great now! You can check the OmniSharp Log
in the Output tab for more info.
If you don't have mono installed, you shouldn't have to worry about OmniSharp. It'll just work.
Ran into an error that looks like Method 'Create' does not have an implementation
. Had to ensure that the right versions of psql and EF were installed (dont mix 5.x with 3.x). Ensure that .csproj file has the right versions of files and confirm at command line. Restart VS Code and Terminals if needed. Make sure 5.0.0
is not in your .csproj file (may be upgraded by accident).
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
<PackageReference Include="NpgSql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.1" />
</ItemGroup>
$ dotnet --list-runtimes
Microsoft.AspNetCore.App 3.1.4 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.4 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
$ dotnet list package
Project 'dotnet-bakery' has the following package references
[netcoreapp3.1]:
Top-level Package Requested Resolved
> Microsoft.AspNetCore.SpaServices.Extensions 3.1.5 3.1.5
> Microsoft.EntityFrameworkCore.Design 3.1.5 3.1.5
> Npgsql.EntityFrameworkCore.PostgreSQL 3.1.4 3.1.4
> NpgSql.EntityFrameworkCore.PostgreSQL.Design 1.1.1 1.1.1
In case of reinstalling EF 3.1.5:
$ dotnet tool uninstall --global dotnet-ef
$ dotnet tool update --global dotnet-ef --version 3.1.5
Restart VS Code and close out of all terminals, try again.
When running migrations, we got this error:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.TypeLoadException: Could not load type 'Microsoft.EntityFrameworkCore.Internal.SemanticVersionComparer' from assembly 'Microsoft.EntityFrameworkCore, Version=5.0.7.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
This was because EF was on 3.x but we've moved to .NET 5 (under .NET 6 runtime...)
First, upgraded the .csproj file to 5.0:
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="newtonsoft.json" Version="13.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.7" />
<PackageReference Include="NpgSql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.1" />
</ItemGroup>
Then do a dotnet restore
.
This will now cause Newtonsoft
namespace to be missing. Do this:
dotnet add package newtonsoft.json
And now dotnet build
should work.
C# Tutorials
- In-Browser Total Beginner C# Tutorial
- Lists, Numbers, etc. Interactive Tutorials
- C# Programming Guide
ASP.NET Core
Some general notes from dotnet scaffolding:
--no-https
will remove https support, which can help keep things simple (https complicates things for local development, and was giving me some trouble with delays and false starts. Can always use an https reverse proxy).-o folder-name
will put the project into a new folder instead of the current one
Example scaffolding recipes:
dotnet new console
will generate a blank console project (great for learning c#)dotnet new webapi
will generate a WebAPI project with a WeatherForecast API endpoint, great for learning the APIdotnet new react
will generate a WebAPI project with the same API as above, with react wired up and ready to go (no redux, jsx/ecmascript6).dotnet new reactredux
will generate the same as above, but with redux included AND in TypeScript instead of ECMAScript6.
dotnet run
will build and run the project, which will also launchnpm start
in the background on the client appdotnet watch run
will do the same, but restart the whole thing when any file is changeddotnet build
will just build the DLL files in thebuild/
folderdotnet publish -r osx-x64
publish an executable build targeted atosx-64
dotnet publish -r linux-x64 --stand-alone true
publish a stand-alone executable (targeted forlinux-64
)
By default, dotnet
will run webpack and npm start
etc in the background, which can take awhile and remove
some flexibility and control. Simple update Startup.cs
to 1) remove the call to npm and 2) forward any client requests
to port 3000
(which is exactly the opposite of the react/express dev cycle, which forwards port 3000
to 5000
).
The result is basically the same, just know that you don't want to visit http://localhost:3000
as that will just be
the react app itself, and all API calls wont work (unless of course you set up a second proxy in package.json
lol).
According to The Docs, in Startup.cs
replace spa.UseReactDevelopmentServer
with spa.UseProxyToSpaDevelopmentServer
like so:
if (env.IsDevelopment())
{
// spa.UseReactDevelopmentServer(npmScript: "start");
spa.UseProxyToSpaDevelopmentServer("http://localhost:3000");
}
For some reason I'm having a heck of a time with Azure CLI. I run az login
which says I am logged in,
but then immediately say "There are no subscriptions" and all future az
commands require logging in. Maybe
I have to do something else on the Azure web interface before it will work?
UPDATE: I finally can login to Azure. The issue was that previously I forgot my password, but resetting didnt work because MS wouldn't accept my email as my username (doh). So I was stuck. Well apparently I did that enough times that it locked my account, which sent me to another form that I was able to use to unlock my account. Through this process I was able to change my password (and save it!) and then log into MS Services.
Once logged in I went to the Azure portal, and verified my account (but did NOT put in credit card info). I don't know if the first step was required or not.
But not I can get into az which is great. It seems that the previous problem was that I did have a Microsoft account, but did not yet have an Azure account.
blaine$ az login
You have logged in. Now let us find all the subscriptions to which you have access...
The following tenants don't contain accessible subscriptions. Use 'az login --allow-no-subscriptions' to have tenant level access.
039d8805-2014-4214-880c-9c70fa38925e
No subscriptions found.
blaine$ az login --allow-no-subscriptions
You have logged in. Now let us find all the subscriptions to which you have access...
The following tenants don't contain accessible subscriptions. Use 'az login --allow-no-subscriptions' to have tenant level access.
039d8805-2014-4214-880c-9c70fa38925e
[
{
"cloudName": "AzureCloud",
"id": "039d8805-2014-4214-880c-9c70fa38925e",
"isDefault": true,
"name": "N/A(tenant level account)",
"state": "Enabled",
"tenantId": "039d8805-2014-4214-880c-9c70fa38925e",
"user": {
"name": "[email protected]",
"type": "user"
}
}
]
I can't find the command line instructions that I had before, but I did find some great documentation on simple deployment from VS Code. I installed the Azure App Service
extension and followed the directions to login to Azure. I now have a Deploy Web App...
option when I right click on a folder (for example, one generated with dotnet publish -c Release -o ./publish
When clicking Deploy App...
I am presented with a notification that I do not have any subscriptions (pretty much the same error as before), but with a link to go create one. I put in my CC info (to finish account verification), and Azure assures me I won't be charged as long as I don't specifically upgrade to a paid tier.
As soon as I verified, I get a TOO_MANY_REDIRECTS
error from Azure, lol.
I do see I have a default subscription now, but VS Code doesn't believe me. I guess I'll finish this another day.
UPDATE: Once you create a free 'web app' subscription on Azure, you can deploy through VS Code directly (select subscription, create a new app). Works pretty well.
Deploying to heroku worked surprisingly well. I did have one hiccup where npm
is used to build the client app, but Heroku can't install the node
buildpack since we don't have a package.json
in the top level directory of the project. I added a package.json and it works without a hitch (npm init --yes
will produce a basic one).
Make sure you have a git repo set up so that heroku remote will work properly.
Create the heroku app, install the dotnet buildpack, and set it to the project (not sure if necessary). It also helps to set your environment variable to production so that you dont end up building the development version.
heroku create --buildpack https://github.com/jincod/dotnetcore-buildpack.git
heroku buildpacks:set jincod/dotnetcore
heroku config:set ASPNETCORE_ENVIRONMENT=Production
# For NodeJS Support (building locally)
heroku buildpacks:add --index 1 heroku/nodejs
# Then to deploy, just commit and push:
git push heroku master
Surprisingly, it works great! The client gets built on Heroku and served out by the Kestrel engine. See the GitHub page for the buildpack on how to set up migrations, if necessary. I also disabled service workers because it made it difficult to figure out if the app was getting updated properly on deploy.
First, go through the standard heroku magic:
heroku addons:create heroku-postgresql:hobby-dev
heroku pg:push your_database DATABASE_URL
Now the database is set up, but we have to wire our app up to use it. To get postgres wired up, we have to create the proper connection string. The one that comes in from DATABASE_URL isnt in the right format. For now just manually create it and check for it in Startup.cs
heroku config:add DATABASE_URL_STR="Host=ec2-blah.compute-1.amazonaws.com;Port=5432;Username=...;Password=...;Database=...;"
Update Startup.cs
appropriately:
string DATABASE_URL = Environment.GetEnvironmentVariable("DATABASE_URL_STR");
string connectionString = (DATABASE_URL == null ? Configuration.GetConnectionString("DefaultConnection") : DATABASE_URL);
Console.WriteLine($"Using connection string: {connectionString}");
services.AddDbContext<ApplicationContext>(options =>
options.UseNpgsql(connectionString)
);
Its hard to believe it, but it works! heroku logs
will confirm that we can see the new connection string and everything works as expected when you visit the site (heroku open
). Wow!
Gotta install PostgreSQL and the EntityFarmeworkCore.Design library (so we can do code-first and migrations).
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package NpgSql.EntityFrameworkCore.PostgreSQL.Design
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet tool install --global dotnet-ef
Make a class, and add the class to the DB context. Add the DB Context to your setup in Startup.cs. Make sure each class at least has an id
defined: public int id { get; set; }
or Entity will (righly) complain about a missing primary key.
dotnet ef migrations add Initial
dotnet ef database update
To remove / reset the migrations:
dotnet ef migrations remove
To reset the database:
dotnet ef database update 0
- If you add a file (like a new controller) remember to restart dotnet :).
dotnet watch run
only hot reloads files it knows about. - Heroku Dotnet Build Pack Documentation
- Dotnet Core Web API Documentation
- Dotnet Tutorials Source Code
- Dotnet Student Manager Tutorial and Source Dode
- Code First Tutorial