diff --git a/Directory.Packages.props b/Directory.Packages.props index 2bdd483f9..2ecf547c8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -16,18 +16,20 @@ - + + - - - + + + + - + @@ -101,13 +103,13 @@ - - + + - + diff --git a/src/DurableTask.AzureServiceFabric/DurableTask.AzureServiceFabric.csproj b/src/DurableTask.AzureServiceFabric/DurableTask.AzureServiceFabric.csproj index 770052ae9..ee457f4a5 100644 --- a/src/DurableTask.AzureServiceFabric/DurableTask.AzureServiceFabric.csproj +++ b/src/DurableTask.AzureServiceFabric/DurableTask.AzureServiceFabric.csproj @@ -2,7 +2,7 @@ - net48;net472 + net48;net472;net8.0;net10.0 true Microsoft.Azure.DurableTask.AzureServiceFabric true @@ -16,23 +16,26 @@ $(NoWarn);NU5104 - + + - - + + + - - - + + + + + - diff --git a/src/DurableTask.AzureServiceFabric/Extensions.cs b/src/DurableTask.AzureServiceFabric/Extensions.cs index ed7797cee..b73c6ca77 100644 --- a/src/DurableTask.AzureServiceFabric/Extensions.cs +++ b/src/DurableTask.AzureServiceFabric/Extensions.cs @@ -14,9 +14,12 @@ namespace DurableTask.AzureServiceFabric { using System; + using System.Net; using System.Net.Http; using System.Threading.Tasks; +#if NETFRAMEWORK using System.Web; +#endif using DurableTask.AzureServiceFabric.Exceptions; @@ -38,7 +41,7 @@ public static bool IsValidInstanceId(this string instanceId) } // InsanceId consists of valid url characters is treated as valid. - var encodedInstanceId = HttpUtility.UrlEncode(instanceId); + var encodedInstanceId = WebUtility.UrlEncode(instanceId); return instanceId.Equals(encodedInstanceId, StringComparison.OrdinalIgnoreCase); } diff --git a/src/DurableTask.AzureServiceFabric/Remote/DefaultStringPartitionHashing.cs b/src/DurableTask.AzureServiceFabric/Remote/DefaultStringPartitionHashing.cs index 619f41c95..f3e28a2b5 100644 --- a/src/DurableTask.AzureServiceFabric/Remote/DefaultStringPartitionHashing.cs +++ b/src/DurableTask.AzureServiceFabric/Remote/DefaultStringPartitionHashing.cs @@ -31,7 +31,7 @@ public Task GeneratePartitionHashCodeAsync(string value, CancellationToken long hashCode = 0; if (!string.IsNullOrEmpty(value)) { - using (var sha256 = SHA256Managed.Create()) + using (var sha256 = SHA256.Create()) { var bytes = Encoding.UTF8.GetBytes(value); var hash = sha256.ComputeHash(bytes); diff --git a/src/DurableTask.AzureServiceFabric/Remote/RemoteOrchestrationServiceClient.cs b/src/DurableTask.AzureServiceFabric/Remote/RemoteOrchestrationServiceClient.cs index 2143dd414..42ceae9d2 100644 --- a/src/DurableTask.AzureServiceFabric/Remote/RemoteOrchestrationServiceClient.cs +++ b/src/DurableTask.AzureServiceFabric/Remote/RemoteOrchestrationServiceClient.cs @@ -18,11 +18,10 @@ namespace DurableTask.AzureServiceFabric.Remote using System.Linq; using System.Net; using System.Net.Http; - using System.Net.Http.Formatting; using System.Net.Sockets; + using System.Text; using System.Threading; using System.Threading.Tasks; - using System.Web; using DurableTask.Core; using DurableTask.Core.Exceptions; @@ -31,7 +30,6 @@ namespace DurableTask.AzureServiceFabric.Remote using Newtonsoft.Json; using Newtonsoft.Json.Linq; - using System.Web.Http.Results; /// /// Allows to interact with a remote IOrchestrationServiceClient @@ -115,7 +113,7 @@ public async Task ForceTerminateTaskOrchestrationAsync(string instanceId, string { instanceId.EnsureValidInstanceId(); - var fragment = $"{this.GetOrchestrationFragment(instanceId)}?reason={HttpUtility.UrlEncode(reason)}"; + var fragment = $"{this.GetOrchestrationFragment(instanceId)}?reason={WebUtility.UrlEncode(reason)}"; using (var response = await this.ExecuteRequestWithRetriesAsync( instanceId, async (baseUri) => await this.HttpClient.DeleteAsync(new Uri(baseUri, fragment)), @@ -193,7 +191,11 @@ public async Task PurgeOrchestrationHistoryAsync(DateTime thresholdDateTimeUtc, foreach (var endpoint in await this.GetAllEndpointsAsync(CancellationToken.None)) { var uri = $"{endpoint.ToString()}/{GetHistoryFragment()}"; - var task = this.HttpClient.PostAsJsonAsync(uri, new PurgeOrchestrationHistoryParameters { ThresholdDateTimeUtc = thresholdDateTimeUtc, TimeRangeFilterType = timeRangeFilterType }); + var task = this.HttpClient.PostAsync(uri, + new StringContent( + JsonConvert.SerializeObject(new PurgeOrchestrationHistoryParameters { ThresholdDateTimeUtc = thresholdDateTimeUtc, TimeRangeFilterType = timeRangeFilterType }), + Encoding.UTF8, + "application/json")); allTasks.Add(task); } @@ -303,21 +305,26 @@ private async Task GetStringResponseAsync(string instanceId, string frag private async Task PutJsonAsync(string instanceId, string fragment, object @object, CancellationToken cancellationToken) { - var mediaFormatter = new JsonMediaTypeFormatter() - { - SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All } - }; + var jsonSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; + var jsonContent = new StringContent( + JsonConvert.SerializeObject(@object, jsonSettings), + Encoding.UTF8, + "application/json"); using (var result = await this.ExecuteRequestWithRetriesAsync( instanceId, - async (baseUri) => await this.HttpClient.PutAsync(new Uri(baseUri, fragment), @object, mediaFormatter), + async (baseUri) => await this.HttpClient.PutAsync(new Uri(baseUri, fragment), jsonContent), cancellationToken)) { // TODO: Improve exception handling if (result.StatusCode == HttpStatusCode.Conflict) { - throw await (result.Content?.ReadAsAsync() ?? Task.FromResult(new OrchestrationAlreadyExistsException())); + var errorContent = await (result.Content?.ReadAsStringAsync() ?? Task.FromResult(null)); + throw errorContent != null + ? JsonConvert.DeserializeObject(errorContent) + ?? new OrchestrationAlreadyExistsException() + : new OrchestrationAlreadyExistsException(); } if (!result.IsSuccessStatusCode) diff --git a/src/DurableTask.AzureServiceFabric/Service/ActivityLoggingMessageHandler.cs b/src/DurableTask.AzureServiceFabric/Service/ActivityLoggingMessageHandler.cs index 4f9432186..525dc072d 100644 --- a/src/DurableTask.AzureServiceFabric/Service/ActivityLoggingMessageHandler.cs +++ b/src/DurableTask.AzureServiceFabric/Service/ActivityLoggingMessageHandler.cs @@ -11,6 +11,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +#if NETFRAMEWORK namespace DurableTask.AzureServiceFabric.Service { using System; @@ -47,3 +48,4 @@ protected override async Task SendAsync(HttpRequestMessage } } } +#endif diff --git a/src/DurableTask.AzureServiceFabric/Service/ActivityLoggingMiddleware.cs b/src/DurableTask.AzureServiceFabric/Service/ActivityLoggingMiddleware.cs new file mode 100644 index 000000000..a2d0749f0 --- /dev/null +++ b/src/DurableTask.AzureServiceFabric/Service/ActivityLoggingMiddleware.cs @@ -0,0 +1,65 @@ +// ---------------------------------------------------------------------------------- +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +#if !NETFRAMEWORK +namespace DurableTask.AzureServiceFabric.Service +{ + using System; + using System.Net; + using System.Threading.Tasks; + + using DurableTask.AzureServiceFabric.Tracing; + + using Microsoft.AspNetCore.Http; + using Newtonsoft.Json; + + /// + /// ASP.NET Core middleware for activity logging of proxy service requests. + /// + internal class ActivityLoggingMiddleware + { + private readonly RequestDelegate next; + + public ActivityLoggingMiddleware(RequestDelegate next) + { + this.next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + string requestMethod = context.Request.Method; + string requestPath = context.Request.Path.ToString(); + string activityId = Guid.NewGuid().ToString("D"); + + ServiceFabricProviderEventSource.Tracing.LogProxyServiceRequestInformation( + $"{activityId} : Proxy service incoming request {requestPath} with method {requestMethod}"); + + try + { + await this.next(context); + ServiceFabricProviderEventSource.Tracing.LogProxyServiceRequestInformation( + $"{activityId} : Proxy service responding request {requestPath} with method {requestMethod} with status code {context.Response.StatusCode}"); + } + catch (Exception exception) + { + ServiceFabricProviderEventSource.Tracing.LogProxyServiceError(activityId, requestPath, requestMethod, exception); + context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(JsonConvert.SerializeObject(exception)); + } + + context.Response.Headers[Constants.ActivityIdHeaderName] = activityId; + } + } +} +#endif diff --git a/src/DurableTask.AzureServiceFabric/Service/DefaultDependencyResolver.cs b/src/DurableTask.AzureServiceFabric/Service/DefaultDependencyResolver.cs index 3361d009e..30a295ca3 100644 --- a/src/DurableTask.AzureServiceFabric/Service/DefaultDependencyResolver.cs +++ b/src/DurableTask.AzureServiceFabric/Service/DefaultDependencyResolver.cs @@ -11,6 +11,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +#if NETFRAMEWORK namespace DurableTask.AzureServiceFabric.Service { using System; @@ -71,3 +72,4 @@ public void Dispose() #endregion } } +#endif diff --git a/src/DurableTask.AzureServiceFabric/Service/FabricOrchestrationServiceController.cs b/src/DurableTask.AzureServiceFabric/Service/FabricOrchestrationServiceController.cs index dd3778dd9..282de0802 100644 --- a/src/DurableTask.AzureServiceFabric/Service/FabricOrchestrationServiceController.cs +++ b/src/DurableTask.AzureServiceFabric/Service/FabricOrchestrationServiceController.cs @@ -16,12 +16,14 @@ namespace DurableTask.AzureServiceFabric.Service using System; using System.Collections.Generic; using System.Threading.Tasks; - using System.Web.Http; - using System.Web.Http.Results; using DurableTask.AzureServiceFabric.Models; using DurableTask.Core; using DurableTask.Core.Exceptions; +#if NETFRAMEWORK + using System.Web.Http; + using System.Web.Http.Results; + /// /// A Web Api controller that provides TaskHubClient operations. /// @@ -185,4 +187,135 @@ public async Task PurgeOrchestrationHistory([FromBody]PurgeOr return new OkResult(this); } } +#else + using Microsoft.AspNetCore.Mvc; + + /// + /// An ASP.NET Core controller that provides TaskHubClient operations. + /// + [ApiController] + public class FabricOrchestrationServiceController : ControllerBase + { + private readonly IOrchestrationServiceClient orchestrationServiceClient; + + /// + /// Creates an instance of FabricOrchestrationServiceController for given OrchestrationServiceClient + /// + /// IOrchestrationServiceClient instance + public FabricOrchestrationServiceController(IOrchestrationServiceClient orchestrationServiceClient) + { + this.orchestrationServiceClient = orchestrationServiceClient; + } + + /// + /// Creates a task orchestration. + /// + [HttpPut("orchestrations/{orchestrationId}")] + public async Task CreateTaskOrchestration([FromRoute] string orchestrationId, [FromBody] CreateTaskOrchestrationParameters parameters) + { + parameters.TaskMessage.OrchestrationInstance.InstanceId.EnsureValidInstanceId(); + if (!orchestrationId.Equals(parameters.TaskMessage.OrchestrationInstance.InstanceId)) + { + return BadRequest($"OrchestrationId from Uri {orchestrationId} doesn't match with the one from body {parameters.TaskMessage.OrchestrationInstance.InstanceId}"); + } + + try + { + if (parameters.DedupeStatuses == null) + { + await this.orchestrationServiceClient.CreateTaskOrchestrationAsync(parameters.TaskMessage); + } + else + { + await this.orchestrationServiceClient.CreateTaskOrchestrationAsync(parameters.TaskMessage, parameters.DedupeStatuses); + } + + return Ok(); + } + catch (OrchestrationAlreadyExistsException orchestrationAlreadyExistsException) + { + return Conflict(orchestrationAlreadyExistsException); + } + catch (NotSupportedException notSupportedException) + { + return BadRequest(notSupportedException.Message); + } + } + + /// + /// Sends an orchestration message to TaskHubClient. + /// + [HttpPost("messages/{messageId}")] + public async Task SendTaskOrchestrationMessage([FromRoute] long messageId, [FromBody] TaskMessage message) + { + if (messageId != message.SequenceNumber) + { + return Conflict(); + } + + message.OrchestrationInstance.InstanceId.EnsureValidInstanceId(); + await this.orchestrationServiceClient.SendTaskOrchestrationMessageAsync(message); + return Ok(); + } + + /// + /// Sends an array of orchestration messages to TaskHubClient. + /// + [HttpPost("messages")] + public async Task SendTaskOrchestrationMessageBatch([FromBody] TaskMessage[] messages) + { + await this.orchestrationServiceClient.SendTaskOrchestrationMessageBatchAsync(messages); + return Ok(); + } + + /// + /// Gets the state of orchestration. + /// + [HttpGet("orchestrations/{orchestrationId}")] + public async Task GetOrchestrationState([FromRoute] string orchestrationId, [FromQuery] string executionId, [FromQuery] bool? allExecutions) + { + orchestrationId.EnsureValidInstanceId(); + if (allExecutions.HasValue) + { + var states = await this.orchestrationServiceClient.GetOrchestrationStateAsync(orchestrationId, allExecutions.Value); + return Ok(states); + } + + var state = await this.orchestrationServiceClient.GetOrchestrationStateAsync(orchestrationId, executionId); + return Ok(state); + } + + /// + /// Terminates an orchestration. + /// + [HttpDelete("orchestrations/{orchestrationId}")] + public async Task ForceTerminateTaskOrchestration([FromRoute] string orchestrationId, [FromQuery] string reason) + { + orchestrationId.EnsureValidInstanceId(); + await this.orchestrationServiceClient.ForceTerminateTaskOrchestrationAsync(orchestrationId, reason); + return Ok(); + } + + /// + /// Gets the history of orchestration. + /// + [HttpGet("history/{orchestrationId}")] + public async Task GetOrchestrationHistory([FromRoute] string orchestrationId, [FromQuery] string executionId) + { + orchestrationId.EnsureValidInstanceId(); + var result = await this.orchestrationServiceClient.GetOrchestrationHistoryAsync(orchestrationId, executionId); + return Ok(result); + } + + /// + /// Purges orchestration instance state and history for orchestrations older than the specified threshold time. + /// + [HttpPost("history")] + public async Task PurgeOrchestrationHistory([FromBody] PurgeOrchestrationHistoryParameters purgeParameters) + { + await this.orchestrationServiceClient.PurgeOrchestrationHistoryAsync(purgeParameters.ThresholdDateTimeUtc, purgeParameters.TimeRangeFilterType); + return Ok(); + } + } +#endif } diff --git a/src/DurableTask.AzureServiceFabric/Service/IOwinAppBuilder.cs b/src/DurableTask.AzureServiceFabric/Service/IOwinAppBuilder.cs index 46e36a04d..ca2bf7d14 100644 --- a/src/DurableTask.AzureServiceFabric/Service/IOwinAppBuilder.cs +++ b/src/DurableTask.AzureServiceFabric/Service/IOwinAppBuilder.cs @@ -11,6 +11,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +#if NETFRAMEWORK namespace DurableTask.AzureServiceFabric.Service { using Owin; @@ -34,3 +35,4 @@ public interface IOwinAppBuilder void Startup(IAppBuilder appBuilder); } } +#endif diff --git a/src/DurableTask.AzureServiceFabric/Service/OwinCommunicationListener.cs b/src/DurableTask.AzureServiceFabric/Service/OwinCommunicationListener.cs index 0c0af7aa9..10693c498 100644 --- a/src/DurableTask.AzureServiceFabric/Service/OwinCommunicationListener.cs +++ b/src/DurableTask.AzureServiceFabric/Service/OwinCommunicationListener.cs @@ -11,6 +11,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +#if NETFRAMEWORK namespace DurableTask.AzureServiceFabric.Service { using System; @@ -106,3 +107,4 @@ private void StopWebServer() } } } +#endif diff --git a/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionHandler.cs b/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionHandler.cs index 4ef0ad9d8..ab7029de0 100644 --- a/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionHandler.cs +++ b/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionHandler.cs @@ -11,6 +11,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +#if NETFRAMEWORK namespace DurableTask.AzureServiceFabric.Service { using System; @@ -36,3 +37,4 @@ public override void Handle(ExceptionHandlerContext context) } } } +#endif diff --git a/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionLogger.cs b/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionLogger.cs index 11f1ed776..b24224615 100644 --- a/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionLogger.cs +++ b/src/DurableTask.AzureServiceFabric/Service/ProxyServiceExceptionLogger.cs @@ -11,6 +11,7 @@ // limitations under the License. // ---------------------------------------------------------------------------------- +#if NETFRAMEWORK namespace DurableTask.AzureServiceFabric.Service { using System; @@ -34,3 +35,4 @@ public async override Task LogAsync(ExceptionLoggerContext context, Cancellation } } } +#endif diff --git a/src/DurableTask.AzureServiceFabric/Service/Startup.cs b/src/DurableTask.AzureServiceFabric/Service/Startup.cs index f9e0beac7..d796c50a3 100644 --- a/src/DurableTask.AzureServiceFabric/Service/Startup.cs +++ b/src/DurableTask.AzureServiceFabric/Service/Startup.cs @@ -14,13 +14,13 @@ namespace DurableTask.AzureServiceFabric.Service { using System; + using DurableTask.Core; + using Microsoft.Extensions.DependencyInjection; + +#if NETFRAMEWORK using System.Net; using System.Web.Http; using System.Web.Http.ExceptionHandling; - - using DurableTask.Core; - using DurableTask.AzureServiceFabric; - using Microsoft.Extensions.DependencyInjection; using Owin; class Startup : IOwinAppBuilder @@ -64,4 +64,33 @@ void IOwinAppBuilder.Startup(IAppBuilder appBuilder) appBuilder.UseWebApi(config); } } +#else + using Microsoft.AspNetCore.Builder; + using Microsoft.AspNetCore.Hosting; + using Newtonsoft.Json; + + class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(sp => + sp.GetRequiredService().OrchestrationServiceClient); + services.AddControllers() + .AddNewtonsoftJson(options => + { + options.SerializerSettings.TypeNameHandling = TypeNameHandling.All; + }); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.UseMiddleware(); + app.UseRouting(); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +#endif } diff --git a/src/DurableTask.AzureServiceFabric/Service/TaskHubProxyListener.cs b/src/DurableTask.AzureServiceFabric/Service/TaskHubProxyListener.cs index 86aba90f2..a4030acbf 100644 --- a/src/DurableTask.AzureServiceFabric/Service/TaskHubProxyListener.cs +++ b/src/DurableTask.AzureServiceFabric/Service/TaskHubProxyListener.cs @@ -29,6 +29,12 @@ namespace DurableTask.AzureServiceFabric.Service using Microsoft.ServiceFabric.Services.Communication.Runtime; using Microsoft.ServiceFabric.Services.Runtime; +#if !NETFRAMEWORK + using Microsoft.AspNetCore.Hosting; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.ServiceFabric.Services.Communication.AspNetCore; +#endif + /// /// Delegate invoked before starting the worker to register orchestrations. /// @@ -150,6 +156,9 @@ public ServiceReplicaListener CreateServiceReplicaListener() { return new ServiceReplicaListener(context => { + EnsureFabricOrchestrationProviderIsInitialized(); + +#if NETFRAMEWORK var serviceEndpoint = context.CodePackageActivationContext.GetEndpoint(Constants.TaskHubProxyListenerEndpointName); string ipAddress = context.NodeContext.IPAddressOrFQDN; #if DEBUG @@ -158,12 +167,28 @@ public ServiceReplicaListener CreateServiceReplicaListener() address => (address.AddressFamily == AddressFamily.InterNetwork) && (!IPAddress.IsLoopback(address))); ipAddress = ipv4Address.ToString(); #endif - - EnsureFabricOrchestrationProviderIsInitialized(); string protocol = this.enableHttps ? "https" : "http"; string listeningAddress = string.Format(CultureInfo.InvariantCulture, "{0}://{1}:{2}/{3}/dtfx/", protocol, ipAddress, serviceEndpoint.Port, context.PartitionId); return new OwinCommunicationListener(new Startup(listeningAddress, this.fabricOrchestrationProvider)); +#else + var provider = this.fabricOrchestrationProvider; + return new KestrelCommunicationListener(context, Constants.TaskHubProxyListenerEndpointName, (url, listener) => + { +#pragma warning disable ASPDEPR004, ASPDEPR008 // WebHostBuilder is the required pattern for SF KestrelCommunicationListener + return new WebHostBuilder() + .UseKestrel() + .ConfigureServices(services => + { + services.AddSingleton(provider); + }) + .UseStartup() + .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.UseUniqueServiceUrl) + .UseUrls(url) + .Build(); +#pragma warning restore ASPDEPR004, ASPDEPR008 + }); +#endif }, Constants.TaskHubProxyServiceName); } diff --git a/test/DurableTask.AzureServiceFabric.Integration.Tests/DeploymentUtil/DeploymentHelper.cs b/test/DurableTask.AzureServiceFabric.Integration.Tests/DeploymentUtil/DeploymentHelper.cs index 20cb25ef8..6fe4e15fa 100644 --- a/test/DurableTask.AzureServiceFabric.Integration.Tests/DeploymentUtil/DeploymentHelper.cs +++ b/test/DurableTask.AzureServiceFabric.Integration.Tests/DeploymentUtil/DeploymentHelper.cs @@ -54,7 +54,9 @@ public static async Task CleanAsync() var replicas = (await client.QueryManager.GetDeployedReplicaListAsync(node.NodeName, application.ApplicationName)).OfType(); foreach (var replica in replicas) { +#pragma warning disable CS0618 // RemoveReplicaAsync overload is deprecated in newer SF SDK await client.ServiceManager.RemoveReplicaAsync(node.NodeName, replica.Partitionid, replica.ReplicaId); +#pragma warning restore CS0618 } } } diff --git a/test/DurableTask.AzureServiceFabric.Integration.Tests/DurableTask.AzureServiceFabric.Integration.Tests.csproj b/test/DurableTask.AzureServiceFabric.Integration.Tests/DurableTask.AzureServiceFabric.Integration.Tests.csproj index 09d30327f..233f0e539 100644 --- a/test/DurableTask.AzureServiceFabric.Integration.Tests/DurableTask.AzureServiceFabric.Integration.Tests.csproj +++ b/test/DurableTask.AzureServiceFabric.Integration.Tests/DurableTask.AzureServiceFabric.Integration.Tests.csproj @@ -2,22 +2,25 @@ - net48 + net48;net10.0 true AnyCPU;x64 - - - - + + + - + + + + + @@ -25,10 +28,6 @@ - - - - diff --git a/test/DurableTask.AzureServiceFabric.Tests/DurableTask.AzureServiceFabric.Tests.csproj b/test/DurableTask.AzureServiceFabric.Tests/DurableTask.AzureServiceFabric.Tests.csproj index e409082a0..73efce7e8 100644 --- a/test/DurableTask.AzureServiceFabric.Tests/DurableTask.AzureServiceFabric.Tests.csproj +++ b/test/DurableTask.AzureServiceFabric.Tests/DurableTask.AzureServiceFabric.Tests.csproj @@ -2,15 +2,15 @@ - net48 + net48;net10.0 AnyCPU;x64 - - - - + + + + diff --git a/test/TestFabricApplication/TestApplication.Common/TestApplication.Common.csproj b/test/TestFabricApplication/TestApplication.Common/TestApplication.Common.csproj index 16bc3aea5..14d3a6b86 100644 --- a/test/TestFabricApplication/TestApplication.Common/TestApplication.Common.csproj +++ b/test/TestFabricApplication/TestApplication.Common/TestApplication.Common.csproj @@ -1,12 +1,15 @@  - net48;net472 + net48;net472;net10.0 AnyCPU;x64 - + + + +