1# Dotnet {#dotnet} 2 3## Local Development Workflow {#local-development-workflow} 4 5For local development, it's recommended to use nix-shell to create a dotnet environment: 6 7```nix 8# shell.nix 9with import <nixpkgs> {}; 10 11mkShell { 12 name = "dotnet-env"; 13 packages = [ 14 dotnet-sdk_3 15 ]; 16} 17``` 18 19### Using many sdks in a workflow {#using-many-sdks-in-a-workflow} 20 21It's very likely that more than one sdk will be needed on a given project. Dotnet provides several different frameworks (E.g dotnetcore, aspnetcore, etc.) as well as many versions for a given framework. Normally, dotnet is able to fetch a framework and install it relative to the executable. However, this would mean writing to the nix store in nixpkgs, which is read-only. To support the many-sdk use case, one can compose an environment using `dotnetCorePackages.combinePackages`: 22 23```nix 24with import <nixpkgs> {}; 25 26mkShell { 27 name = "dotnet-env"; 28 packages = [ 29 (with dotnetCorePackages; combinePackages [ 30 sdk_3_1 31 sdk_5_0 32 ]) 33 ]; 34} 35``` 36 37This will produce a dotnet installation that has the dotnet 3.1, 3.0, and 2.1 sdk. The first sdk listed will have it's cli utility present in the resulting environment. Example info output: 38 39```ShellSession 40$ dotnet --info 41.NET Core SDK (reflecting any global.json): 42 Version: 3.1.101 43 Commit: b377529961 44 45... 46 47.NET Core SDKs installed: 48 2.1.803 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/sdk] 49 3.0.102 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/sdk] 50 3.1.101 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/sdk] 51 52.NET Core runtimes installed: 53 Microsoft.AspNetCore.All 2.1.15 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.All] 54 Microsoft.AspNetCore.App 2.1.15 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.App] 55 Microsoft.AspNetCore.App 3.0.2 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.App] 56 Microsoft.AspNetCore.App 3.1.1 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.AspNetCore.App] 57 Microsoft.NETCore.App 2.1.15 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.NETCore.App] 58 Microsoft.NETCore.App 3.0.2 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.NETCore.App] 59 Microsoft.NETCore.App 3.1.1 [/nix/store/iiv98i2jdi226dgh4jzkkj2ww7f8jgpd-dotnet-core-combined/shared/Microsoft.NETCore.App] 60``` 61 62## dotnet-sdk vs dotnetCorePackages.sdk {#dotnet-sdk-vs-dotnetcorepackages.sdk} 63 64The `dotnetCorePackages.sdk_X_Y` is preferred over the old dotnet-sdk as both major and minor version are very important for a dotnet environment. If a given minor version isn't present (or was changed), then this will likely break your ability to build a project. 65 66## dotnetCorePackages.sdk vs dotnetCorePackages.runtime vs dotnetCorePackages.aspnetcore {#dotnetcorepackages.sdk-vs-dotnetcorepackages.runtime-vs-dotnetcorepackages.aspnetcore} 67 68The `dotnetCorePackages.sdk` contains both a runtime and the full sdk of a given version. The `runtime` and `aspnetcore` packages are meant to serve as minimal runtimes to deploy alongside already built applications. 69 70## Packaging a Dotnet Application {#packaging-a-dotnet-application} 71 72To package Dotnet applications, you can use `buildDotnetModule`. This has similar arguments to `stdenv.mkDerivation`, with the following additions: 73 74* `projectFile` has to be used for specifying the dotnet project file relative to the source root. These usually have `.sln` or `.csproj` file extensions. This can be an array of multiple projects as well. 75* `nugetDeps` has to be used to specify the NuGet dependency file. Unfortunately, these cannot be deterministically fetched without a lockfile. This file should be generated using `nuget-to-nix` tool, which is available in nixpkgs. 76* `executables` is used to specify which executables get wrapped to `$out/bin`, relative to `$out/lib/$pname`. If this is unset, all executables generated will get installed. If you do not want to install any, set this to `[]`. 77* `runtimeDeps` is used to wrap libraries into `LD_LIBRARY_PATH`. This is how dotnet usually handles runtime dependencies. 78* `buildType` is used to change the type of build. Possible values are `Release`, `Debug`, etc. By default, this is set to `Release`. 79* `dotnet-sdk` is useful in cases where you need to change what dotnet SDK is being used. 80* `dotnet-runtime` is useful in cases where you need to change what dotnet runtime is being used. This can be either a regular dotnet runtime, or an aspnetcore. 81* `dotnet-test-sdk` is useful in cases where unit tests expect a different dotnet SDK. By default, this is set to the `dotnet-sdk` attribute. 82* `testProjectFile` is useful in cases where the regular project file does not contain the unit tests. By default, this is set to the `projectFile` attribute. 83* `disabledTests` is used to disable running specific unit tests. This gets passed as: `dotnet test --filter "FullyQualifiedName!={}"`, to ensure compatibility with all unit test frameworks. 84* `dotnetRestoreFlags` can be used to pass flags to `dotnet restore`. 85* `dotnetBuildFlags` can be used to pass flags to `dotnet build`. 86* `dotnetTestFlags` can be used to pass flags to `dotnet test`. 87* `dotnetInstallFlags` can be used to pass flags to `dotnet install`. 88* `dotnetFlags` can be used to pass flags to all of the above phases. 89 90Here is an example `default.nix`, using some of the previously discussed arguments: 91```nix 92{ lib, buildDotnetModule, dotnetCorePackages, ffmpeg }: 93 94buildDotnetModule rec { 95 pname = "someDotnetApplication"; 96 version = "0.1"; 97 98 src = ./.; 99 100 projectFile = "src/project.sln"; 101 nugetDeps = ./deps.nix; # File generated with `nuget-to-nix path/to/src > deps.nix`. 102 103 dotnet-sdk = dotnetCorePackages.sdk_3_1; 104 dotnet-runtime = dotnetCorePackages.net_5_0; 105 dotnetFlags = [ "--runtime linux-x64" ]; 106 107 executables = [ "foo" ]; # This wraps "$out/lib/$pname/foo" to `$out/bin/foo`. 108 executables = []; # Don't install any executables. 109 110 runtimeDeps = [ ffmpeg ]; # This will wrap ffmpeg's library path into `LD_LIBRARY_PATH`. 111} 112```