我发布此内容是因为我无法在 Stack Overflow 上找到任何位置,通过连接服务添加服务引用来解决使用 WCF 的 .Net-Core 项目的此问题。
我的问题是,由于长时间运行的操作请求,我面临客户端超时。
那么,由于 .Net-Core 不再使用 Web 配置来存储 WCF 服务引用的配置值,如何增加 WCF 客户端对象的超时值呢? (请参阅我提供的答案)
在“解决方案资源管理器”中的“连接服务”下,添加 WCF 服务后,会为该服务生成一些文件。您应该会看到一个文件夹,其名称与您为 WCF 服务引用指定的名称相同,在该文件夹下有一个
Getting Started
、ConnectedService.json
和一个 Reference.cs
文件。
要增加任何客户端服务对象的超时值,请打开
Reference.cs
并找到方法:GetBindingForEndpoint
在这个方法中你应该看到类似这样的内容:
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IYourService))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
//Here's where you can set the timeout values
result.SendTimeout = new System.TimeSpan(0, 5, 0);
result.ReceiveTimeout = new System.TimeSpan(0, 5, 0);
return result;
}
只需使用
result.
和您想要增加的超时,如 SendTimeout
、ReceiveTimeout
等,并将其设置为具有所需超时值的新 TimeSpan。
我希望这对某人来说是一个有用的帖子。
Ryan Wilson 的回答将会起作用,但前提是您尝试更新服务。 Reference.cs 将被覆盖。 在 .NET Core 3.1 中,您可以通过语法修改绑定超时:
public MemoqTMServiceClass(string api_key)
{
client = new TMServiceClient();
var eab = new EndpointAddressBuilder(client.Endpoint.Address);
eab.Headers.Add(
AddressHeader.CreateAddressHeader("ApiKey", // Header Name
string.Empty, // Namespace
api_key)); // Header Value
client.Endpoint.Address = eab.ToEndpointAddress();
client.Endpoint.Binding.CloseTimeout = new TimeSpan(2, 0, 0);
client.Endpoint.Binding.OpenTimeout = new TimeSpan(2, 0, 0);
client.Endpoint.Binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
client.Endpoint.Binding.SendTimeout = new TimeSpan(0, 10, 0);
}
只需在生成的代理类中实现以下部分方法即可配置服务端点。将部分方法放在您自己的文件中,以确保它不会被覆盖。
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
以下是如何更轻松地在 WCF 中测试和配置超时。超时在客户端项目中配置。
首先,图像证明或它没有发生。在这里,您可以看到我在 15 秒后超时,那么我是怎么做到的?
注意,我为客户端使用以下 Nuget 包,这是一个 .NET 6 控制台应用程序:
<ItemGroup>
<PackageReference Include="System.ServiceModel.Duplex" Version="4.10.*" />
<PackageReference Include="System.ServiceModel.Federation" Version="4.10.*" />
<PackageReference Include="System.ServiceModel.Http" Version="4.10.*" />
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.10.*" />
<PackageReference Include="System.ServiceModel.Security" Version="4.10.*" />
</ItemGroup>
服务器项目使用这些 Nuget 包,我已经从 CoreWCF 模板制作了客户端和服务 WCF :
<ItemGroup>
<PackageReference Include="CoreWCF.Primitives" Version="1.*" />
<PackageReference Include="CoreWCF.Http" Version="1.*" />
</ItemGroup>
在客户端自动生成的Reference.cs文件中,我们得到了这个方法:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.1.0")]
public partial class ServiceClient : System.ServiceModel.ClientBase<MyService.IService>, MyService.IService
{
/// <summary>
/// Implement this partial method to configure the service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The endpoint to configure</param>
/// <param name="clientCredentials">The client credentials</param>
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
//more code
我们记下客户端的命名空间,并添加以下带有一组配置的超时的部分类。根据需要调整这些超时。
我在这里添加了一个名为ServiceClient的文件,类名也与Reference.cs中的ServiceClient类名相匹配。
namespace MyService
{
public partial class ServiceClient
{
/// <summary>
/// Implement this partial method to configure the service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The endpoint to configure</param>
/// <param name="clientCredentials">The client credentials</param>
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials)
{
serviceEndpoint.Binding.OpenTimeout
= serviceEndpoint.Binding.CloseTimeout
= serviceEndpoint.Binding.ReceiveTimeout
= serviceEndpoint.Binding.SendTimeout = TimeSpan.FromSeconds(15);
}
}
}
此处设置的超时设置为 15 秒。显然,您希望这些超时时间更长一些,我只输入了一个小值来快速测试它。默认值通常是 30 或 60 秒,在生产中,您可能会考虑很多分钟,以防您的服务方法应该执行长时间运行的作业 - 或者考虑使用一个框架,例如 Hangfire。
这种方法的好处是,如果您更新 Reference.cs(这在 VS 2022 中仍然有点麻烦,不像以前在 .NET Framework 中使用 WCF 那么容易),您配置的设置仍然保留。通过设置端点绑定,您还可以进行许多其他配置。
我们还可以通过将 appsettings.json 添加到我们的项目并将文件设置为复制到输出文件夹来避免硬编码超时。
如果您在控制台项目中,您可以添加这样的 json 配置文件,最好将其注册到 Program.cs 中的某些共享设置中,但我发现从静态方法中使用它有点困难,我最终得到了这个:
/// <summary>
/// Implement this partial method to configure the service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The endpoint to configure</param>
/// <param name="clientCredentials">The client credentials</param>
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials)
{
var serviceProvider = new ServiceCollection()
.AddSingleton(_ =>
new ConfigurationBuilder()
.SetBasePath(Path.Combine(AppContext.BaseDirectory))
.AddJsonFile("appsettings.json", optional: true)
.Build())
.BuildServiceProvider();
var config = serviceProvider.GetService<IConfigurationRoot>();
int timeoutInSeconds = int.Parse(config!["ServiceTimeoutInSeconds"]);
serviceEndpoint.Binding.OpenTimeout
= serviceEndpoint.Binding.CloseTimeout
= serviceEndpoint.Binding.ReceiveTimeout
= serviceEndpoint.Binding.SendTimeout = TimeSpan.FromSeconds(timeoutInSeconds);
}
我们有了 appsettings.json 文件
{
"ServiceTimeoutInSeconds" : 9
}
CoreWCF 项目有一个升级工具,可以为您完成大量迁移工作。 WCF 有很多配置设置,并且为每个设置都有一个 appsettings.json 文件将是一些工作。升级工具应该负责生成其中一些配置值并将它们添加到专用的 json 文件中。