diff --git a/.github/workflows/openactive-test-suite.yml b/.github/workflows/openactive-test-suite.yml
index 06f8780c..a20afc24 100644
--- a/.github/workflows/openactive-test-suite.yml
+++ b/.github/workflows/openactive-test-suite.yml
@@ -182,8 +182,8 @@ jobs:
needs:
- test-server
- test-fake-database
- # runs on an Windows 2019 virtual machine, not an Ubuntu machine
- runs-on: windows-2019
+ # runs on a Windows virtual machine, not an Ubuntu virtual machine (latest is used to force failure if dependencies become outdated)
+ runs-on: windows-latest
strategy:
fail-fast: false
@@ -213,9 +213,9 @@ jobs:
# Building and deploying Framework is done using `msbuild` as opposed to `dotnet build`/`dotnet run`. It is started
# using IIS Express
- name: Setup MSBuild path
- uses: microsoft/setup-msbuild@v1.0.2
+ uses: microsoft/setup-msbuild@v2
- name: Setup NuGet
- uses: NuGet/setup-nuget@v1.0.5
+ uses: NuGet/setup-nuget@v2
- name: Install OpenActive.Server.NET dependencies
run: nuget restore .\server\
- name: Build .NET Framework Reference Implementation
diff --git a/Examples/BookingSystem.AspNetCore.IdentityServer/BookingSystem.AspNetCore.IdentityServer.csproj b/Examples/BookingSystem.AspNetCore.IdentityServer/BookingSystem.AspNetCore.IdentityServer.csproj
index fb12cf38..bf22aa27 100644
--- a/Examples/BookingSystem.AspNetCore.IdentityServer/BookingSystem.AspNetCore.IdentityServer.csproj
+++ b/Examples/BookingSystem.AspNetCore.IdentityServer/BookingSystem.AspNetCore.IdentityServer.csproj
@@ -2,6 +2,7 @@
netcoreapp3.1
+ 8.0
diff --git a/Examples/BookingSystem.AspNetCore/BookingSystem.AspNetCore.csproj b/Examples/BookingSystem.AspNetCore/BookingSystem.AspNetCore.csproj
index 62f36fd2..56ca4b98 100644
--- a/Examples/BookingSystem.AspNetCore/BookingSystem.AspNetCore.csproj
+++ b/Examples/BookingSystem.AspNetCore/BookingSystem.AspNetCore.csproj
@@ -2,6 +2,7 @@
netcoreapp3.1
+ 8.0
aspnet-BookingSystem.AspNetCore-443B4F82-A20C-41CE-9924-329A0BCF0D14
Release;Debug
diff --git a/Examples/BookingSystem.AspNetFramework.Tests/BookingSystem.AspNetFramework.Tests.csproj b/Examples/BookingSystem.AspNetFramework.Tests/BookingSystem.AspNetFramework.Tests.csproj
index 3fa756ef..0a5c449f 100644
--- a/Examples/BookingSystem.AspNetFramework.Tests/BookingSystem.AspNetFramework.Tests.csproj
+++ b/Examples/BookingSystem.AspNetFramework.Tests/BookingSystem.AspNetFramework.Tests.csproj
@@ -12,6 +12,7 @@
BookingSystem.AspNetFramework.Tests
BookingSystem.AspNetFramework.Tests
v4.6.2
+ 8.0
512
{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
@@ -132,4 +133,4 @@
-->
-
\ No newline at end of file
+
diff --git a/Examples/BookingSystem.AspNetFramework/BookingSystem.AspNetFramework.csproj b/Examples/BookingSystem.AspNetFramework/BookingSystem.AspNetFramework.csproj
index c89ec8a1..8efa888e 100644
--- a/Examples/BookingSystem.AspNetFramework/BookingSystem.AspNetFramework.csproj
+++ b/Examples/BookingSystem.AspNetFramework/BookingSystem.AspNetFramework.csproj
@@ -15,6 +15,7 @@
BookingSystem.AspNetFramework
BookingSystem.AspNetFramework
v4.6.2
+ 8.0
false
true
@@ -316,6 +317,7 @@
+
True
@@ -448,6 +450,7 @@
Global.asax
+
@@ -460,6 +463,7 @@
+
@@ -540,4 +544,4 @@
-->
-
\ No newline at end of file
+
diff --git a/Examples/BookingSystem.AspNetFramework/Feeds/FacilitiesFeeds.cs b/Examples/BookingSystem.AspNetFramework/Feeds/FacilitiesFeeds.cs
index c9c7b496..4b613cf4 100644
--- a/Examples/BookingSystem.AspNetFramework/Feeds/FacilitiesFeeds.cs
+++ b/Examples/BookingSystem.AspNetFramework/Feeds/FacilitiesFeeds.cs
@@ -1,5 +1,5 @@
using Bogus;
-using BookingSystem.AspNetCore.Helpers;
+using BookingSystem.AspNetFramework.Helpers;
using OpenActive.DatasetSite.NET;
using OpenActive.FakeDatabase.NET;
using OpenActive.NET;
@@ -305,4 +305,4 @@ Offer GenerateOffer(SlotTable slot, QuantitativeValue ageRange)
}
}
-}
\ No newline at end of file
+}
diff --git a/Examples/BookingSystem.AspNetFramework/Feeds/SessionsFeeds.cs b/Examples/BookingSystem.AspNetFramework/Feeds/SessionsFeeds.cs
index 302aa382..3dd233e1 100644
--- a/Examples/BookingSystem.AspNetFramework/Feeds/SessionsFeeds.cs
+++ b/Examples/BookingSystem.AspNetFramework/Feeds/SessionsFeeds.cs
@@ -9,7 +9,7 @@
using System.Linq;
using System.Threading.Tasks;
using Bogus;
-using BookingSystem.AspNetCore.Helpers;
+using BookingSystem.AspNetFramework.Helpers;
using ServiceStack;
using System.Globalization;
diff --git a/Examples/BookingSystem.AspNetFramework/Helpers/FeedGenerationHelper.cs b/Examples/BookingSystem.AspNetFramework/Helpers/FeedGenerationHelper.cs
new file mode 100644
index 00000000..16214545
--- /dev/null
+++ b/Examples/BookingSystem.AspNetFramework/Helpers/FeedGenerationHelper.cs
@@ -0,0 +1,305 @@
+using System;
+using OpenActive.NET;
+using System.Collections.Generic;
+using OpenActive.FakeDatabase.NET;
+using Bogus;
+using System.Linq;
+using Bogus.DataSets;
+using OpenActive.Server.NET.OpenBookingHelper;
+using System.Security.Policy;
+
+
+
+namespace BookingSystem.AspNetFramework.Helpers
+{
+ public static class FeedGenerationHelper
+ {
+ public static IList GetRandomElementsOf(Faker faker, IList list, bool isGoldenRecord, int minimumNumberOfElements = 0, int maximumNumberOfElements = 0)
+ {
+ // If this is for the golden record, return the whole list so that all the possible data values are returned
+ if (isGoldenRecord) return list;
+
+ // If maximumNumberOfElements is the default value, use list.Count, if it's been set, use that
+ var max = maximumNumberOfElements == 0 ? list.Count : maximumNumberOfElements;
+ // Otherwise return a random number of elements from the list
+ var randomNumberOfElementsToReturn = faker.Random.Number(minimumNumberOfElements, max);
+ return faker.Random.ListItems(list, randomNumberOfElementsToReturn);
+ }
+
+
+ public static Place GetPlaceById(long placeId)
+ {
+ // Three hardcoded fake places
+ switch (placeId)
+ {
+ case 1:
+ return new Place
+ {
+ Identifier = 1,
+ Id = new Uri($"https://example.com/place/{placeId}"),
+ Name = "Post-ercise Plaza",
+ Description = "Sorting Out Your Fitness One Parcel Lift at a Time! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+ Address = new PostalAddress
+ {
+ StreetAddress = "Kings Mead House",
+ AddressLocality = "Oxford",
+ AddressRegion = "Oxfordshire",
+ PostalCode = "OX1 1AA",
+ AddressCountry = "GB"
+ },
+ Geo = new GeoCoordinates
+ {
+ Latitude = (decimal?)51.7502,
+ Longitude = (decimal?)-1.2674
+ },
+ Image = new List {
+ new ImageObject
+ {
+ Url = new Uri("https://upload.wikimedia.org/wikipedia/commons/e/e5/Oxford_StAldates_PostOffice.jpg")
+ },
+ },
+ Telephone = "01865 000001",
+ Url = new Uri("https://en.wikipedia.org/wiki/Post_Office_Limited"),
+ AmenityFeature = new List
+ {
+ new ChangingFacilities { Name = "Changing Facilities", Value = true },
+ new Showers { Name = "Showers", Value = true },
+ new Lockers { Name = "Lockers", Value = true },
+ new Towels { Name = "Towels", Value = false },
+ new Creche { Name = "Creche", Value = false },
+ new Parking { Name = "Parking", Value = false }
+ },
+ OpeningHoursSpecification = new List
+ {
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Sunday }, Opens = "09:00", Closes = "17:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Monday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Tuesday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Wednesday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Thursday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Friday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Saturday }, Opens = "09:00", Closes = "17:30"}
+ }
+ };
+ case 2:
+ return new Place
+ {
+ Identifier = 2,
+ Id = new Uri($"https://example.com/place/{placeId}"),
+ Name = "Premier Lifters",
+ Description = "Where your Fitness Goals are Always Inn-Sight. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+ Address = new PostalAddress
+ {
+ StreetAddress = "Greyfriars Court, Paradise Square",
+ AddressLocality = "Oxford",
+ AddressRegion = "Oxfordshire",
+ PostalCode = "OX1 1BB",
+ AddressCountry = "GB"
+ },
+ Geo = new GeoCoordinates
+ {
+ Latitude = (decimal?)51.7504933,
+ Longitude = (decimal?)-1.2620685
+ },
+ Image = new List {
+ new ImageObject
+ {
+ Url = new Uri("https://upload.wikimedia.org/wikipedia/commons/5/53/Cambridge_Orchard_Park_Premier_Inn.jpg")
+ },
+ },
+ Telephone = "01865 000002",
+ Url = new Uri("https://en.wikipedia.org/wiki/Premier_Inn"),
+ AmenityFeature = new List
+ {
+ new ChangingFacilities { Name = "Changing Facilities", Value = false },
+ new Showers { Name = "Showers", Value = false },
+ new Lockers { Name = "Lockers", Value = false },
+ new Towels { Name = "Towels", Value = true },
+ new Creche { Name = "Creche", Value = true },
+ new Parking { Name = "Parking", Value = true }
+ },
+ OpeningHoursSpecification = new List
+ {
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Sunday }, Opens = "09:00", Closes = "17:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Monday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Tuesday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Wednesday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Thursday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Friday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Saturday }, Opens = "09:00", Closes = "17:30"}
+ }
+ };
+ case 3:
+ return new Place
+ {
+ Identifier = 3,
+ Id = new Uri($"https://example.com/place/{placeId}"),
+ Name = "Stroll & Stretch",
+ Description = "Casual Calisthenics in the Heart of Commerce. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
+ Address = new PostalAddress
+ {
+ StreetAddress = "Norfolk Street",
+ AddressLocality = "Oxford",
+ AddressRegion = "Oxfordshire",
+ PostalCode = "OX1 1UU",
+ AddressCountry = "GB"
+ },
+ Geo = new GeoCoordinates
+ {
+ Latitude = (decimal?)51.749826,
+ Longitude = (decimal?)-1.261492
+ },
+ Image = new List {
+ new ImageObject
+ {
+ Url = new Uri("https://upload.wikimedia.org/wikipedia/commons/2/28/Westfield_Garden_State_Plaza_-_panoramio.jpg")
+ },
+ },
+ Telephone = "01865 000003",
+ Url = new Uri("https://en.wikipedia.org/wiki/Shopping_center"),
+ OpeningHoursSpecification = new List
+ {
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Sunday }, Opens = "09:00", Closes = "17:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Monday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Tuesday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Wednesday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Thursday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Friday }, Opens = "06:30", Closes = "21:30"},
+ new OpeningHoursSpecification {DayOfWeek = new List {Schema.NET.DayOfWeek.Saturday }, Opens = "09:00", Closes = "17:30"}
+ }
+ };
+ default:
+ return null;
+ }
+ }
+
+ public static List OpenBookingFlowRequirement(bool requiresApproval, bool requiresAttendeeValidation, bool requiresAdditionalDetails, bool allowsProposalAmendment)
+ {
+ List openBookingFlowRequirement = null;
+
+ if (requiresApproval)
+ {
+ openBookingFlowRequirement = openBookingFlowRequirement ?? new List();
+ openBookingFlowRequirement.Add(OpenActive.NET.OpenBookingFlowRequirement.OpenBookingApproval);
+ }
+
+ if (requiresAttendeeValidation)
+ {
+ openBookingFlowRequirement = openBookingFlowRequirement ?? new List();
+ openBookingFlowRequirement.Add(OpenActive.NET.OpenBookingFlowRequirement.OpenBookingAttendeeDetails);
+ }
+
+ if (requiresAdditionalDetails)
+ {
+ openBookingFlowRequirement = openBookingFlowRequirement ?? new List();
+ openBookingFlowRequirement.Add(OpenActive.NET.OpenBookingFlowRequirement.OpenBookingIntakeForm);
+ }
+
+ if (allowsProposalAmendment)
+ {
+ openBookingFlowRequirement = openBookingFlowRequirement ?? new List();
+ openBookingFlowRequirement.Add(OpenActive.NET.OpenBookingFlowRequirement.OpenBookingNegotiation);
+ }
+ return openBookingFlowRequirement;
+ }
+
+ public static string GenerateAttendeeInstructions(Faker faker, bool isGoldenRecord)
+ {
+ var listOfPossibleInstructions = new List(){
+ "wear sportswear/gym clothes",
+ "wear comfortable loose clothing",
+ "come as you are",
+ "bring trainers",
+ "wear flat shoes",
+ "no footwear required"
+ };
+
+ return $"Clothing instructions: {string.Join(", ", GetRandomElementsOf(faker, listOfPossibleInstructions, isGoldenRecord, 1))}";
+ }
+
+ public static List GenerateAccessibilitySupport(Faker faker, bool isGoldenRecord)
+ {
+ var listOfAccessibilitySupports = new List
+ {
+ new Concept {Id = new Uri("https://openactive.io/accessibility-support#1393f2dc-3fcc-4be9-a99f-f1e51f5ad277"), PrefLabel = "Visual Impairment", InScheme = new Uri("https://openactive.io/accessibility-support")},
+ new Concept {Id = new Uri("https://openactive.io/accessibility-support#2bfb7228-5969-4927-8435-38b5005a8771"), PrefLabel = "Hearing Impairment", InScheme = new Uri("https://openactive.io/accessibility-support")},
+ new Concept {Id = new Uri("https://openactive.io/accessibility-support#40b9b11f-bdd3-4aeb-8984-2ecf74a14c7a"), PrefLabel = "Mental health issues", InScheme = new Uri("https://openactive.io/accessibility-support")}
+ };
+
+ return GetRandomElementsOf(faker, listOfAccessibilitySupports, isGoldenRecord, 1, 2).ToList();
+ }
+
+ public static List GenerateImages(Faker faker, bool isGoldenRecord)
+ {
+ static Uri GenerateImageUrl(int width, int height, int seed)
+ {
+ return new Uri($"https://picsum.photos/{width}/{height}?image={seed}");
+ }
+
+ var images = new List();
+ var min = isGoldenRecord ? 4 : 1;
+ var imageCount = faker.Random.Number(min, 3);
+ for (var i = 0; i < imageCount; i++)
+ {
+ var imageSeed = faker.Random.Number(1083);
+ var thumbnails = new List {
+ new ImageObject{Url = GenerateImageUrl(672, 414, imageSeed), Width = 672, Height = 414},
+ new ImageObject{Url = GenerateImageUrl(300, 200, imageSeed), Width = 300, Height = 200},
+ new ImageObject{Url = GenerateImageUrl(100, 100, imageSeed), Width = 100, Height = 100}
+ };
+ var image = new ImageObject
+ {
+ Url = GenerateImageUrl(1024, 724, imageSeed),
+ Thumbnail = GetRandomElementsOf(faker, thumbnails, isGoldenRecord, 1, 1).ToList()
+ };
+ images.Add(image);
+ }
+ return images;
+ }
+
+ public static Organization GenerateOrganization(Faker faker, SellerTable seller, bool isSingleSeller, Uri organizationId)
+ {
+ if (isSingleSeller)
+ return new Organization
+ {
+ Id = organizationId,
+ Name = "Test Seller",
+ TaxMode = TaxMode.TaxGross,
+ TermsOfService = new List
+ {
+ new PrivacyPolicy
+ {
+ Name = "Privacy Policy",
+ Url = new Uri("https://example.com/privacy.html"),
+ RequiresExplicitConsent = false
+ }
+ },
+ IsOpenBookingAllowed = true,
+ Telephone = faker.Phone.PhoneNumber("0#### ######"),
+ SameAs = new List { new Uri("https://socialmedia.com/testseller") }
+ };
+
+ return new Organization
+ {
+ Id = organizationId,
+ Name = seller.Name,
+ TaxMode = seller.IsTaxGross ? TaxMode.TaxGross : TaxMode.TaxNet,
+ TermsOfService = new List
+ {
+ new PrivacyPolicy
+ {
+ Name = "Privacy Policy",
+ Url = new Uri("https://example.com/privacy.html"),
+ RequiresExplicitConsent = false
+ }
+ },
+ IsOpenBookingAllowed = true,
+ Url = new Uri(faker.Internet.Url()),
+ Telephone = faker.Phone.PhoneNumber("0#### ######"),
+ SameAs = new List { new Uri($"https://socialmedia.com/{seller.Name.Replace(" ", "")}") }
+ };
+
+
+ }
+
+ }
+}
diff --git a/Examples/BookingSystem.AspNetFramework/Stores/FacilityStore.cs b/Examples/BookingSystem.AspNetFramework/Stores/FacilityStore.cs
index f506d119..3273aca9 100644
--- a/Examples/BookingSystem.AspNetFramework/Stores/FacilityStore.cs
+++ b/Examples/BookingSystem.AspNetFramework/Stores/FacilityStore.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using BookingSystem.AspNetCore.Helpers;
+using BookingSystem.AspNetFramework.Helpers;
using OpenActive.DatasetSite.NET;
using OpenActive.FakeDatabase.NET;
using OpenActive.NET;
diff --git a/Examples/BookingSystem.AspNetFramework/Stores/SessionStore.cs b/Examples/BookingSystem.AspNetFramework/Stores/SessionStore.cs
index 912579f7..7a14b1ed 100644
--- a/Examples/BookingSystem.AspNetFramework/Stores/SessionStore.cs
+++ b/Examples/BookingSystem.AspNetFramework/Stores/SessionStore.cs
@@ -8,7 +8,7 @@
using OpenActive.FakeDatabase.NET;
using RequiredStatusType = OpenActive.FakeDatabase.NET.RequiredStatusType;
using System.Threading.Tasks;
-using BookingSystem.AspNetCore.Helpers;
+using BookingSystem.AspNetFramework.Helpers;
namespace BookingSystem
{
diff --git a/Examples/BookingSystem.AspNetFramework/Utils/ServiceConfig.cs b/Examples/BookingSystem.AspNetFramework/Utils/ServiceConfig.cs
index 340ea85c..589f2d0e 100644
--- a/Examples/BookingSystem.AspNetFramework/Utils/ServiceConfig.cs
+++ b/Examples/BookingSystem.AspNetFramework/Utils/ServiceConfig.cs
@@ -1,6 +1,7 @@
using BookingSystem.AspNetFramework.Helpers;
using BookingSystem.AspNetFramework.Controllers;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging.Abstractions;
using OpenActive.Server.NET;
using System.Configuration;
using System.Web.Http;
@@ -32,7 +33,7 @@ public static void Register(HttpConfiguration config)
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddSingleton(sp => EngineConfig.CreateStoreBookingEngine(appSettings, new FakeBookingSystem(false)));
+ services.AddSingleton(sp => EngineConfig.CreateStoreBookingEngine(appSettings, new FakeBookingSystem(false, new NullLogger())));
var resolver = new DependencyResolver(services.BuildServiceProvider(true));
config.DependencyResolver = resolver;
diff --git a/Fakes/OpenActive.FakeDatabase.NET.Tests/OpenActive.FakeDatabase.NET.Tests.csproj b/Fakes/OpenActive.FakeDatabase.NET.Tests/OpenActive.FakeDatabase.NET.Tests.csproj
index e6ac0462..c26e0e80 100644
--- a/Fakes/OpenActive.FakeDatabase.NET.Tests/OpenActive.FakeDatabase.NET.Tests.csproj
+++ b/Fakes/OpenActive.FakeDatabase.NET.Tests/OpenActive.FakeDatabase.NET.Tests.csproj
@@ -2,6 +2,7 @@
netcoreapp3.1
+ 8.0
false
diff --git a/Fakes/OpenActive.FakeDatabase.NET/OpenActive.FakeDatabase.NET.csproj b/Fakes/OpenActive.FakeDatabase.NET/OpenActive.FakeDatabase.NET.csproj
index 1e72cbb1..069c8a24 100644
--- a/Fakes/OpenActive.FakeDatabase.NET/OpenActive.FakeDatabase.NET.csproj
+++ b/Fakes/OpenActive.FakeDatabase.NET/OpenActive.FakeDatabase.NET.csproj
@@ -2,6 +2,7 @@
netstandard2.0
+ 8.0
OpenActive.FakeDatabase.NET
OpenActive.FakeDatabase.NET
OpenActive.FakeDatabase.NET
@@ -30,7 +31,7 @@
-
+
diff --git a/OpenActive.Server.NET.Tests/OpenActive.Server.NET.Tests.csproj b/OpenActive.Server.NET.Tests/OpenActive.Server.NET.Tests.csproj
index 7226907e..b07b7385 100644
--- a/OpenActive.Server.NET.Tests/OpenActive.Server.NET.Tests.csproj
+++ b/OpenActive.Server.NET.Tests/OpenActive.Server.NET.Tests.csproj
@@ -2,6 +2,7 @@
netcoreapp3.1
+ 8.0
false
diff --git a/OpenActive.Server.NET/OpenActive.Server.NET.csproj b/OpenActive.Server.NET/OpenActive.Server.NET.csproj
index 1dd2ab94..2ea7fb1d 100644
--- a/OpenActive.Server.NET/OpenActive.Server.NET.csproj
+++ b/OpenActive.Server.NET/OpenActive.Server.NET.csproj
@@ -2,6 +2,7 @@
netstandard2.0
+ 8.0
OpenActive Community
OpenActive
OpenActive