使用 SOAP Web 服务而不依赖 app.config
我正在构建一个将调用外部 Web 服务的 .NET 组件。我使用“添加服务引用”对话框将 Web 服务添加到我的组件中,该组件生成使用该服务所需的代码并将设置添加到 app.config 文件中。
我通过从控制台应用程序添加对其 DLL 的引用并调用创建 Web 服务新实例的适当方法来测试该组件:... = new MyServiceSoapClient()
。但是,当我这样做时,出现以下异常:
无效操作异常
在 ServiceModel 客户端配置部分中找不到引用协定“MyServicesSoap”的默认端点元素。这可能是因为没有找到适用于您的应用程序的配置文件,或者因为在客户端元素中找不到与此协定匹配的端点元素。
这是有道理的,因为 app.config 没有与组件的 DLL 一起引入。如何在不依赖 App.Config 中的设置的情况下调用 Web 服务?
I'm building a .NET component that will call an external web service. I used the "Add Service Reference" dialog to add the web service to my component, which generates the code needed to consume the service and adds the settings to the app.config file.
I'm testing the component by adding a reference to its DLL from a Console application and calling the appropriate method that creates a new instance of the web service: ... = new MyServiceSoapClient()
. However, when I do this, I get the following exception:
InvalidOperationException
Could not find default endpoint element that references contract 'MyServicesSoap' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
This makes sense since the app.config isn't being brought over with the component's DLL. How can I call the web service without having to rely on the settings in the App.Config?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
app.config 文件中
中的设置将告诉组件如何连接到外部 Web 服务。 xml 只是与 Web 服务进行默认连接所需的必要类和枚举的文本表示。例如,这是为我添加的 Web 服务生成的代码:
这可以转换为如下代码:
通常,当您使用无参数构造函数(即
new MyServicesSoapClient()
)时,将使用 app.config 文件中的设置。但是,您可以通过在代码中显式设置binding
和endpoint
值并将这些实例传递到构造函数来绕过 app.config 文件。The settings in
<system.ServiceModel>
in the app.config file will tell the component how to connect to the external web service. The xml is simply a textual representation of the necessary classes and enumerations required to make the default connection to the web service.For example, this is the code that was generated for the web service that I added:
This can be translated to code like so:
Usually, when you use the parameterless constructor (i.e.
new MyServicesSoapClient()
), the settings in the app.config file will be used. However, you can bypass the app.config file by explicitly setting thebinding
andendpoint
values in code and passing those instances into the constructor.在代码中设置Binding和Endpoint配置是一种方法,但还有另一种方法可以使用使用者DLL并让配置保留在现有的App.config文件中。
之所以出现上述InvalidOperationException,是因为DLL中不包含配置设置。它始终依赖 App.config 来提供它,但由于您在另一个控制台应用程序中使用 DLL,因此它找不到配置设置。
当我们使用“添加服务引用”对话框将 Web 服务添加到客户端组件并创建 Web 服务的实例时,我们让 Visual Studio 处理通信通道的创建并加载配置设置。因此,如果我们能够我们自己明确创建这样的通道,然后我们就可以管理配置设置。
Microsoft 为此提供了类,
ConfigurationChannelFactory
类就是其中之一。 MSDN 指出:使用“添加服务引用”对话框将 Web 服务添加到客户端组件,因为我们需要服务通道接口实例。
首先将生成的 App.config 文件重命名为 App.dll.config,并在其文件属性中将复制更改为Output Directory 属性设置为 Copy Always
创建一个类,该类具有返回 Channel 对象以访问 Web 服务的方法,如下所示:
由于我们已设置属性 Copy Always VS 将项目 DLL 以及 App.dll.config 复制到 bin 文件夹中。
Assembly.GetExecutingAssembly().Location
返回程序集位置和ConfigurationManager.OpenExeConfiguration
PluginConfig
保存 App.Config 配置文件对象,ConfigurationChannelFactory
使用它与服务进行通信。可以通过传递服务通道接口对象来调用此方法,如下所示:
SampleService
是我的 Web 服务的命名空间。Client
保存 Web 服务的实例。如果您需要处理双工通信和回调,那么您可以查看
ConfigurationDuplexChannelFactory
类。Setting the Binding and Endpoint configuration in code is one way but there is another way to use the consumer DLL and let the configuration stay in the existing App.config file.
The reason why the mentioned InvalidOperationException occurs is because the DLL does not contain the configuration settings in it. It always rely on App.config to provide for it but since you are using the DLL in another Console application it does not find the configuration settings.
When we use the "Add Service Reference" dialog to add the web service to client component and create instance of the Web service, we let Visual Studio handle the creation of the Communication channel and load the configuration setting.So, if we are able to create such channel explicitly our self then we can manage the configuration settings.
Microsoft provides Classes for this purpose,
ConfigurationChannelFactory<TChannel>
Class is one. MSDN states:Use "Add Service Reference" dialog to add the web service to client component as we need the Service Channel Interface instance.
First rename the generated App.config file to App.dll.config and in its File properties change the Copy to Output Directory property to Copy Always
Create a class that has a method which returns the Channel object to access the web Service such as this:
Since we have set the property Copy Always VS copies the Project DLL as well as the App.dll.config into the bin folder.
Assembly.GetExecutingAssembly().Location
return the assembly location andConfigurationManager.OpenExeConfiguration
PluginConfig
holds the App.Config configuration file Object andConfigurationChannelFactory<T>
uses it to communicate with the service.This method can be called by passing your Service Channel Interface Object like this:
SampleService
is the namespace of my web service.Client
holds the instance of the web Service.If you need to handle Duplex Communication and Callbacks, then you can look at
ConfigurationDuplexChannelFactory<TChannel>
Class.如果这是一个 WCF 服务(从错误消息来看,这听起来像是),那么在大多数情况下,您将需要 app.config,因为 app.config 告诉 WCF 的其余部分: MyServiceSoapClient是一个 Web 服务(对两个 app.config 文件进行一些小的更改,它可以成为一个命名管道服务,而无需重新编译代码......)
现在,如果您真的想要在没有app.config的情况下执行此操作,那么您必须扔掉生成的
MyServiceSoapClient()
,并基于HttpWebRequest
编写您自己的。If this is a WCF service (which it sounds like, from the error messages), then, for the most part, you are going to need something is the app.config, because it's the app.config which tells the rest of WCF that MyServiceSoapClient is a web service (with a small change to the two app.config files, this could become a named pipe service, without recompiling the code....)
Now, if you really want to do this without the app.config, then you have to toss the generated
MyServiceSoapClient()
, and write your own, based onHttpWebRequest
.