在 C# 中访问多端点 Web 服务 (ASMX) 最佳实践
accessing multi endpoints web services (ASMX) best practices in c#
我有一个干净的架构项目,提供微服务,其中之一是访问 Agresso ERP 网络服务。
https://***************/service.svc
它提供许多服务
- https://**/service.svc?FooService/Foo
- https://**/service.svc?BooService/Boo
每个都有自己的服务引用(连接服务),每个都有很多方法。
每次调用您需要传递凭据的任何端点。
var fooSoapClient = new FooSoapClient();
var credentials = new WSCredentials
{
Username = "fakeuser",
Password = "fakepassword",
Client = "fakeclient",
};
var result = fooSoapClient.GetFoosAsync(Foo filter,true,
credentials );
(P.S) 凭据 class 存在于所有实体
namespace Foo1NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
namespace Foo2NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
我可以毫无问题地访问所有端点。
我有以下问题:
- 有没有我可以遵循的通用解决方案,以免陷入 DRY?
- 有没有最适合这个问题的设计模式?
这是我过去所做的,如果您也使用它,它非常适合 Dependency Injection/containers。这里的关键是定义所有服务都将实现的单一接口。使用它的代码应该只使用接口。
每个 class 都应该实现您定义的接口,例如IWebServiceOperations
public interface IWebServiceOperations
{
WebServiceOperationResult GetFooAsync(WebServiceOperationRequest request);
}
我会留给你弄清楚 classes WebServiceOperationResult/Request,它们只是保存你的 request/response 变量,包括凭据。
然后您需要实现的每个 Web 服务都在单独的 class 中完成。您还可以在构造函数中指定这是什么类型的实现(FooSoap1 vs FooSoap2)例如
public class FooSoapClient : BaseClient, IWebServiceOperations
{
public FooSoapClient() : base(Clients.FooSoap1)
public GetFooAsync(...)
{
...
}
}
public class BaseClient
{
private readonly eFooServiceType _serviceType;
public eFooServiceType ServiceType {
get{
return _serviceType;
}
}
protected BaseClient(eFooServiceType service)
{
_serviceType = service;
}
}
现在您应该有一堆 class 参考资料。您的 DI 容器可以根据您想要的服务类型为您解决这些问题,或者您可以将它们添加到字典中,因此如果您想要针对 FooSoap1 进行操作,您可以...
var fooSoapClient1 = myServices[Clients.FooSoap1];
await fooSoapClient1.GetFooAsync(...)
我有一个干净的架构项目,提供微服务,其中之一是访问 Agresso ERP 网络服务。
https://***************/service.svc
它提供许多服务
- https://**/service.svc?FooService/Foo
- https://**/service.svc?BooService/Boo
每个都有自己的服务引用(连接服务),每个都有很多方法。
每次调用您需要传递凭据的任何端点。
var fooSoapClient = new FooSoapClient();
var credentials = new WSCredentials
{
Username = "fakeuser",
Password = "fakepassword",
Client = "fakeclient",
};
var result = fooSoapClient.GetFoosAsync(Foo filter,true,
credentials );
(P.S) 凭据 class 存在于所有实体
namespace Foo1NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
namespace Foo2NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
我可以毫无问题地访问所有端点。
我有以下问题:
- 有没有我可以遵循的通用解决方案,以免陷入 DRY?
- 有没有最适合这个问题的设计模式?
这是我过去所做的,如果您也使用它,它非常适合 Dependency Injection/containers。这里的关键是定义所有服务都将实现的单一接口。使用它的代码应该只使用接口。
每个 class 都应该实现您定义的接口,例如IWebServiceOperations
public interface IWebServiceOperations
{
WebServiceOperationResult GetFooAsync(WebServiceOperationRequest request);
}
我会留给你弄清楚 classes WebServiceOperationResult/Request,它们只是保存你的 request/response 变量,包括凭据。
然后您需要实现的每个 Web 服务都在单独的 class 中完成。您还可以在构造函数中指定这是什么类型的实现(FooSoap1 vs FooSoap2)例如
public class FooSoapClient : BaseClient, IWebServiceOperations
{
public FooSoapClient() : base(Clients.FooSoap1)
public GetFooAsync(...)
{
...
}
}
public class BaseClient
{
private readonly eFooServiceType _serviceType;
public eFooServiceType ServiceType {
get{
return _serviceType;
}
}
protected BaseClient(eFooServiceType service)
{
_serviceType = service;
}
}
现在您应该有一堆 class 参考资料。您的 DI 容器可以根据您想要的服务类型为您解决这些问题,或者您可以将它们添加到字典中,因此如果您想要针对 FooSoap1 进行操作,您可以...
var fooSoapClient1 = myServices[Clients.FooSoap1];
await fooSoapClient1.GetFooAsync(...)