Skip to content

Commit 05bfc61

Browse files
authored
Update to ASP.NET Core 3.0 (loic-sharma#444)
Updates BaGet to ASP.NET Core 3.0. This is based off @MarkZither's work (see loic-sharma#443). Thank you for all the help @MarkZither! ⚠️ Many of BaGet's projects will **temporarily** require .NET Core 3 because EF Core 3.0 requires .NET Standard 2.1. EF Core 3.1 reintroduced .NET Standard 2.0 support. I will re-add .NET Framework and .NET Standard 2.0 support once I've migrated BaGet to ASP.NET Core 3.1. Part of loic-sharma#439
1 parent dcbd51d commit 05bfc61

32 files changed

+230
-191
lines changed

.azure/pipelines/ci-official.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ jobs:
3939
pool:
4040
vmImage: vs2017-win2016
4141
steps:
42-
- task: DotNetCoreInstaller@0
43-
displayName: 'Use .NET Core SDK 2.2.100'
42+
- task: UseDotNet@2
43+
displayName: 'Use .NET Core SDK 3.0.X'
4444
inputs:
45-
version: 2.2.100
45+
version: 3.0.x
4646

4747
- task: Npm@1
4848
displayName: Install frontend dependencies

BaGet.sln

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ EndProject
2626
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0B44364D-952B-497A-82E0-C9AAE94E0369}"
2727
ProjectSection(SolutionItems) = preProject
2828
.editorconfig = .editorconfig
29+
src\Directory.Build.props = src\Directory.Build.props
30+
nuget.config = nuget.config
2931
EndProjectSection
3032
EndProject
3133
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BaGet.Core.Server", "src\BaGet.Core.Server\BaGet.Core.Server.csproj", "{D68B56AC-98DD-4DA7-B4F8-1243538A8A5C}"

Dockerfile

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
1+
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
22
WORKDIR /app
33
EXPOSE 80
44

5-
FROM microsoft/dotnet:2.2-sdk AS build
6-
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
5+
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
6+
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
77
RUN apt-get install -y nodejs
88
WORKDIR /src
99
COPY /src .

nuget.config

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<clear />
5+
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
6+
</packageSources>
7+
</configuration>

samples/BaGet.Protocol.Samples.Tests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netcoreapp2.2</TargetFramework>
4+
<TargetFramework>netcoreapp3.0</TargetFramework>
55

66
<IsPackable>false</IsPackable>
77
<NoWarn>IDE0007</NoWarn>

src/BaGet.Aws/BaGet.Aws.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
55

66
<PackageTags>NuGet;Amazon;Cloud</PackageTags>
77
<Description>The libraries to host BaGet on AWS.</Description>

src/BaGet.Azure/BaGet.Azure.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
55

66
<PackageTags>NuGet;Azure;Cloud</PackageTags>
77
<Description>The libraries to host BaGet on Azure.</Description>

src/BaGet.Core.Server/BaGet.Core.Server.csproj

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
55

66
<Description>BaGet's NuGet server implementation</Description>
77
</PropertyGroup>
88

99
<ItemGroup>
10-
<PackageReference Include="Microsoft.AspNetCore.HttpOverrides" version="$(MicrosoftAspNetCorePackageVersion)" />
11-
<PackageReference Include="Microsoft.AspNetCore.Mvc" version="$(MicrosoftAspNetCorePackageVersion)" />
10+
<FrameworkReference Include="Microsoft.AspNetCore.App" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(MicrosoftAspNetCorePackageVersion)" />
1215
</ItemGroup>
1316

1417
<ItemGroup>

src/BaGet.Core.Server/Extensions/IRouteBuilderExtensions.cs src/BaGet.Core.Server/Extensions/IEndpointRouteBuilderExtensions.cs

+51-61
Original file line numberDiff line numberDiff line change
@@ -4,119 +4,109 @@
44

55
namespace BaGet.Extensions
66
{
7-
public static class IRouteBuilderExtensions
7+
public static class IEndpointRouteBuilderExtensions
88
{
9-
public static IRouteBuilder MapServiceIndexRoutes(this IRouteBuilder routes)
9+
public static void MapServiceIndexRoutes(this IEndpointRouteBuilder endpoints)
1010
{
11-
return routes.MapRoute(
11+
endpoints.MapControllerRoute(
1212
name: Routes.IndexRouteName,
13-
template: "v3/index.json",
14-
defaults: new { controller = "ServiceIndex", action = "GetAsync" });
13+
pattern: "v3/index.json",
14+
defaults: new { controller = "ServiceIndex", action = "Get" });
1515
}
1616

17-
public static IRouteBuilder MapPackagePublishRoutes(this IRouteBuilder routes)
17+
public static void MapPackagePublishRoutes(this IEndpointRouteBuilder endpoints)
1818
{
19-
routes.MapRoute(
19+
endpoints.MapControllerRoute(
2020
name: Routes.UploadPackageRouteName,
21-
template: "api/v2/package",
21+
pattern: "api/v2/package",
2222
defaults: new { controller = "PackagePublish", action = "Upload" },
2323
constraints: new { httpMethod = new HttpMethodRouteConstraint("PUT") });
2424

25-
routes.MapRoute(
25+
endpoints.MapControllerRoute(
2626
name: Routes.DeleteRouteName,
27-
template: "api/v2/package/{id}/{version}",
27+
pattern: "api/v2/package/{id}/{version}",
2828
defaults: new { controller = "PackagePublish", action = "Delete" },
2929
constraints: new { httpMethod = new HttpMethodRouteConstraint("DELETE") });
3030

31-
routes.MapRoute(
31+
endpoints.MapControllerRoute(
3232
name: Routes.RelistRouteName,
33-
template: "api/v2/package/{id}/{version}",
33+
pattern: "api/v2/package/{id}/{version}",
3434
defaults: new { controller = "PackagePublish", action = "Relist" },
3535
constraints: new { httpMethod = new HttpMethodRouteConstraint("POST") });
36-
37-
return routes;
3836
}
3937

40-
public static IRouteBuilder MapSymbolRoutes(this IRouteBuilder routes)
38+
public static void MapSymbolRoutes(this IEndpointRouteBuilder endpoints)
4139
{
42-
routes.MapRoute(
40+
endpoints.MapControllerRoute(
4341
name: Routes.UploadSymbolRouteName,
44-
template: "api/v2/symbol",
42+
pattern: "api/v2/symbol",
4543
defaults: new { controller = "Symbol", action = "Upload" },
4644
constraints: new { httpMethod = new HttpMethodRouteConstraint("PUT") });
4745

48-
routes.MapRoute(
49-
name: Routes.SymbolDownloadRouteName,
50-
template: "api/download/symbols/{file}/{key}/{file2}",
51-
defaults: new { controller = "Symbol", action = "Get" });
52-
53-
routes.MapRoute(
46+
endpoints.MapControllerRoute(
5447
name: Routes.SymbolDownloadRouteName,
55-
template: "api/download/symbols/{prefix}/{file}/{key}/{file2}",
48+
pattern: "api/download/symbols/{file}/{key}/{file2}",
5649
defaults: new { controller = "Symbol", action = "Get" });
5750

58-
return routes;
51+
endpoints.MapControllerRoute(
52+
name: Routes.PrefixedSymbolDownloadRouteName,
53+
pattern: "api/download/symbols/{prefix}/{file}/{key}/{file2}",
54+
defaults: new { controller = "Symbol", action = "Get" });
5955
}
6056

61-
public static IRouteBuilder MapSearchRoutes(this IRouteBuilder routes)
57+
public static void MapSearchRoutes(this IEndpointRouteBuilder endpoints)
6258
{
63-
routes.MapRoute(
59+
endpoints.MapControllerRoute(
6460
name: Routes.SearchRouteName,
65-
template: "v3/search",
66-
defaults: new { controller = "Search", action = "SearchAsync" });
61+
pattern: "v3/search",
62+
defaults: new { controller = "Search", action = "Search" });
6763

68-
routes.MapRoute(
64+
endpoints.MapControllerRoute(
6965
name: Routes.AutocompleteRouteName,
70-
template: "v3/autocomplete",
71-
defaults: new { controller = "Search", action = "AutocompleteAsync" });
66+
pattern: "v3/autocomplete",
67+
defaults: new { controller = "Search", action = "Autocomplete" });
7268

7369
// This is an unofficial API to find packages that depend on a given package.
74-
routes.MapRoute(
70+
endpoints.MapControllerRoute(
7571
name: Routes.DependentsRouteName,
76-
template: "v3/dependents",
77-
defaults: new { controller = "Search", action = "DependentsAsync" });
78-
79-
return routes;
72+
pattern: "v3/dependents",
73+
defaults: new { controller = "Search", action = "Dependents" });
8074
}
8175

82-
public static IRouteBuilder MapPackageMetadataRoutes(this IRouteBuilder routes)
76+
public static void MapPackageMetadataRoutes(this IEndpointRouteBuilder endpoints)
8377
{
84-
routes.MapRoute(
78+
endpoints.MapControllerRoute(
8579
name: Routes.RegistrationIndexRouteName,
86-
template: "v3/registration/{id}/index.json",
87-
defaults: new { controller = "PackageMetadata", action = "RegistrationIndexAsync" });
80+
pattern: "v3/registration/{id}/index.json",
81+
defaults: new { controller = "PackageMetadata", action = "RegistrationIndex" });
8882

89-
routes.MapRoute(
83+
endpoints.MapControllerRoute(
9084
name: Routes.RegistrationLeafRouteName,
91-
template: "v3/registration/{id}/{version}.json",
92-
defaults: new { controller = "PackageMetadata", action = "RegistrationLeafAsync" });
93-
94-
return routes;
85+
pattern: "v3/registration/{id}/{version}.json",
86+
defaults: new { controller = "PackageMetadata", action = "RegistrationLeaf" });
9587
}
9688

97-
public static IRouteBuilder MapPackageContentRoutes(this IRouteBuilder routes)
89+
public static void MapPackageContentRoutes(this IEndpointRouteBuilder endpoints)
9890
{
99-
routes.MapRoute(
91+
endpoints.MapControllerRoute(
10092
name: Routes.PackageVersionsRouteName,
101-
template: "v3/package/{id}/index.json",
102-
defaults: new { controller = "PackageContent", action = "GetPackageVersionsAsync" });
93+
pattern: "v3/package/{id}/index.json",
94+
defaults: new { controller = "PackageContent", action = "GetPackageVersions" });
10395

104-
routes.MapRoute(
96+
endpoints.MapControllerRoute(
10597
name: Routes.PackageDownloadRouteName,
106-
template: "v3/package/{id}/{version}/{idVersion}.nupkg",
107-
defaults: new { controller = "PackageContent", action = "DownloadPackageAsync" });
98+
pattern: "v3/package/{id}/{version}/{idVersion}.nupkg",
99+
defaults: new { controller = "PackageContent", action = "DownloadPackage" });
108100

109-
routes.MapRoute(
101+
endpoints.MapControllerRoute(
110102
name: Routes.PackageDownloadManifestRouteName,
111-
template: "v3/package/{id}/{version}/{id2}.nuspec",
112-
defaults: new { controller = "PackageContent", action = "DownloadNuspecAsync" });
103+
pattern: "v3/package/{id}/{version}/{id2}.nuspec",
104+
defaults: new { controller = "PackageContent", action = "DownloadNuspec" });
113105

114-
routes.MapRoute(
106+
endpoints.MapControllerRoute(
115107
name: Routes.PackageDownloadReadmeRouteName,
116-
template: "v3/package/{id}/{version}/readme",
117-
defaults: new { controller = "PackageContent", action = "DownloadReadmeAsync" });
118-
119-
return routes;
108+
pattern: "v3/package/{id}/{version}/readme",
109+
defaults: new { controller = "PackageContent", action = "DownloadReadme" });
120110
}
121111
}
122112
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
using BaGet.Core;
4+
using Microsoft.EntityFrameworkCore;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Hosting;
7+
using Microsoft.Extensions.Options;
8+
9+
namespace BaGet.Extensions
10+
{
11+
public static class IHostExtensions
12+
{
13+
public static async Task RunMigrationsAsync(this IHost host, CancellationToken cancellationToken)
14+
{
15+
// Run migrations if necessary.
16+
var options = host.Services.GetRequiredService<IOptions<BaGetOptions>>();
17+
18+
if (options.Value.RunMigrationsAtStartup && options.Value.Database.Type != DatabaseType.AzureTable)
19+
{
20+
using (var scope = host.Services.CreateScope())
21+
{
22+
var ctx = scope.ServiceProvider.GetRequiredService<IContext>();
23+
24+
// TODO: An "InvalidOperationException" is thrown and caught due to a bug
25+
// in EF Core 3.0. This is fixed in 3.1.
26+
// See: https://github.com/dotnet/efcore/issues/18307
27+
await ctx.Database.MigrateAsync(cancellationToken);
28+
}
29+
}
30+
}
31+
}
32+
}

src/BaGet.Core.Server/Extensions/IServiceCollectionExtensions.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BaGet.Configuration;
2+
using BaGet.Controllers;
23
using Microsoft.AspNetCore.Builder;
34
using Microsoft.AspNetCore.Cors.Infrastructure;
45
using Microsoft.AspNetCore.Http.Features;
@@ -14,15 +15,14 @@ public static class IServiceCollectionExtensions
1415
public static IServiceCollection ConfigureHttpServices(this IServiceCollection services)
1516
{
1617
services
17-
.AddMvc()
18-
.AddApplicationPart(typeof(BaGet.Controllers.PackageContentController).Assembly)
19-
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
20-
.AddJsonOptions(options =>
18+
.AddControllers()
19+
.AddApplicationPart(typeof(PackageContentController).Assembly)
20+
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
21+
.AddNewtonsoftJson(options =>
2122
{
2223
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
2324
});
2425

25-
2626
services.AddCors();
2727
services.AddHttpContextAccessor();
2828
services.AddSingleton<IConfigureOptions<CorsOptions>, ConfigureCorsOptions>();

src/BaGet.Core.Server/Routes.cs

+1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ public class Routes
1717
public const string PackageDownloadManifestRouteName = "package-download-manifest";
1818
public const string PackageDownloadReadmeRouteName = "package-download-readme";
1919
public const string SymbolDownloadRouteName = "symbol-download";
20+
public const string PrefixedSymbolDownloadRouteName = "prefixed-symbol-download";
2021
}
2122
}

src/BaGet.Core/BaGet.Core.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
55

66
<Description>The core libraries that power BaGet.</Description>
77
</PropertyGroup>

src/BaGet.Core/Search/DatabaseSearchService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ IQueryable<Package> AddSearchFilters(IQueryable<Package> packageQuery)
214214
}
215215

216216
var packageIds = search.Select(p => p.Id)
217-
.OrderBy(id => id)
218217
.Distinct()
218+
.OrderBy(id => id)
219219
.Skip(skip)
220220
.Take(take);
221221

src/BaGet.Core/Storage/PackageStorageService.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public async Task SavePackageContentAsync(
6262
lowercasedNormalizedVersion,
6363
packagePath);
6464

65-
throw new InvalidOperationException($"Failed to store package {lowercasedId} {lowercasedNormalizedVersion}");
65+
throw new InvalidOperationException($"Failed to store package {lowercasedId} {lowercasedNormalizedVersion} due to conflict");
6666
}
6767

6868
// Store the package's nuspec.
@@ -82,7 +82,7 @@ public async Task SavePackageContentAsync(
8282
lowercasedNormalizedVersion,
8383
nuspecPath);
8484

85-
throw new InvalidOperationException($"Failed to store package {lowercasedId} {lowercasedNormalizedVersion} nuspec");
85+
throw new InvalidOperationException($"Failed to store package {lowercasedId} {lowercasedNormalizedVersion} nuspec due to conflict");
8686
}
8787

8888
// Store the package's readme, if one exists.
@@ -104,7 +104,7 @@ public async Task SavePackageContentAsync(
104104
lowercasedNormalizedVersion,
105105
readmePath);
106106

107-
throw new InvalidOperationException($"Failed to store package {lowercasedId} {lowercasedNormalizedVersion} readme");
107+
throw new InvalidOperationException($"Failed to store package {lowercasedId} {lowercasedNormalizedVersion} readme due to conflict");
108108
}
109109
}
110110

src/BaGet.Database.MySql/BaGet.Database.MySql.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BaGet.Database.PostgreSql/BaGet.Database.PostgreSql.csproj

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
4+
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.2.0" />
8+
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.1" />
99
</ItemGroup>
1010

1111
<ItemGroup>

0 commit comments

Comments
 (0)