How to call wcf using Reflection and app.config? - c#

I create a class library project[MyLibrary] in vs2010 and add Service Reference[http://127.0.0.1/MyService.svc].so it includes such node in app.config.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://127.0.0.1/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyService.IMyService" name="BasicHttpBinding_IMyService" />
</client>
</system.serviceModel>
I compile MyLibrary project ,it generate MyLibrary.dll and MyLibrary.dll.config.
Generally,I can call wcf method such as:
MyService.MyServiceClient client = new MyServiceClient();
int result = client.Add(3,6);
I haven't operate app.config through programe.it works well.
Now,I write another programe to load MyLibrary.dll and call wcf method using refelection.it generate error:
Could not find default endpoint element that references contract 'MyService.IMyService' 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.
I think it hasn't read the Configuration in app.config using reflection at runtime.I try to use such method,it still does not work.
string assemblyPath = Assembly.GetExecutingAssembly().Location;
string configPath = assemblyPath + ".config";
currentDomain.SetData("APP_CONFIG_FILE", configPath);
typeof(ConfigurationManager)
.GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, 0);
typeof(ConfigurationManager)
.GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, null);
typeof(ConfigurationManager)
.Assembly.GetTypes()
.Where(x => x.FullName == "System.Configuration.ClientConfigPaths").First()
.GetField("s_current", BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, null);
If I don't want to change calling wcf code above, What can I do? How to let programe to load and recognize app.config using reflection at runtime. Seems useless reflection as.Thanks!

You should copy <system.servicemodel> section from MyLibrary.dll.config to app.config of your application references MyLibrary.dll. It should be enough. Anyway, you are asking how to load app.config. In this post described how to load WCF client configuration from any file. But again, it should be enough to copy servicemodel section.

It has nothing to do with calling via reflection. There error message is indicating that the configuration in Mylibrary.dll.config cannot be found. You would get the same error if you were calling the client code directly referencing Mylibrary.dll without the configuration added to the new program's app.config (or web.config).
MyService.MyServiceClient client = new MyServiceClient();
By default, the above code will look in the currently running process's config file and look for <system.servicemodel>. Your new program's configuration needs the information in the Mylibrary.dll.config file to be added to it's configuration file. Otherwise, you must configure the client in code directly.

Related

C# WCF - net.tcp cannot find endpoint

I'm getting the following error message when trying to implement net.tcp WCF in C#:
"Could not find default endpoint element that references contract 'EventInterfaceService.IEventInterface'
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."
On my client side I have the following code:
private void Initialize(string sInterfaceUrl, string sUserParticipantName)
{
EventInterfaceCallbackSink _callbackSink;
InstanceContext _instanceContext;
EndpointAddressBuilder _endpointAddressBuilder;
_callbackSink = new EventInterfaceCallbackSink();
_instanceContext = new InstanceContext(_callbackSink);
eventInterfaceClient = new EventInterfaceClient(_instanceContext); //Exception gets thrown here
EndpointIdentity edi = EndpointIdentity.CreateUpnIdentity(sUserParticipantName);
var endpointAddress = eventInterfaceClient.Endpoint.Address;
EndpointAddressBuilder newEndpointAddress = new EndpointAddressBuilder(endpointAddress);
newEndpointAddress.Uri = new Uri(sInterfaceUrl);
newEndpointAddress.Identity = edi;
eventInterfaceClient.Endpoint.Address = newEndpointAddress.ToEndpointAddress();
}
As you can see I get the EndPointAddress as sInterfaceUrl and the UserParticipantName as sUserParticipantName.
For the app.config I have the following:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding_Interface" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="Infinite" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
textEncoding="utf-8" useDefaultWebProxy="true" messageEncoding="Text">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</basicHttpBinding>
<netTcpBinding>
<binding name="NetTcpBinding_IEventInterface"/>
</netTcpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8732/HTTPWCF/" binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding_Interface" contract="InterfaceService.IInterface"
name="basicHttpBinding_Interface" />
<endpoint address="net.tcp://localhost:8733/NETTCPWCF/"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEventInterface"
contract="EventInterfaceService.IEventInterface" name="NetTcpBinding_IEventInterface">
</endpoint>
</client>
</system.serviceModel>
When running this code in a stand-alone client (not the actual application) it works. I can't seem to find out what's wrong. Any tips would be great!
Thanks.
Edit: Is there any way configuring this purely at runtime, so I won't need the app.config? Regarding the comments below, config file may not be found or wrong one is being used.
Your comment mentioned that you are putting your app.config stuff into a class library. This won't be read. The app.config of the executing assembly gets read instead (or the web.config since this is ASP). You will need to add your relevant config info to the config file of the executing assembly (your ASP project).
Alternatively, you could use the static ConfigurationManager class to read in your specific app.config settings:
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx

Sharing web service methods

I am writing web service client in .Net c# which consumes stage and production web services.Functionality of web methods is same in both stage and production.
Client wants capability of using web methods from both production and stage web services for some data validation. I can do this generating two separate proxy classes also two
separate code bases. Is there a better way so that I can eliminate redundant code by doing something like below
if (clintRequest=="production")
produtionTypeSoapClient client= new produtionTypeSoapClient()
else
stageSoapClient client= new stagetypeSoapClient()
//Instantiate object. Now call web methods
client.authenticate
client.getUsers
client.getCities
You should be able to get away with just one client. If the contract is the same, you can specify the endpoint configuration and the remote address programmatically.
Let us say you have something like this:
1) Staging - http://staging/Remote.svc
2) Production - http://production/Remote.svc
If you are using Visual Studio you should be able to generate a client from either endpoint.
You should, then, be able to do something like this:
C# Code:
OurServiceClient client;
if (clientRequest == "Staging")
client = new OurServiceClient("OurServiceClientImplPort", "http://staging/Remote.svc");
else
client = new OurServiceClient("OurServiceClientImplPort", "http://production/Remote.svc");
This should allow you to use one set of objects to pass around. The 'OurServiceClientImplPort' section above is referencing the config file for the endpoint:
Config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="OurServiceClientSoapBinding" openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:02:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="128" maxStringContentLength="9830400" maxArrayLength="9830400" maxBytesPerRead="40960" maxNameTableCharCount="32768"/>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" realm=""/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<!-- This can be either of the addresses, as you'll override it in code -->
<endpoint address="http://production/Remote.svc" binding="basicHttpBinding" bindingConfiguration="OurServiceClientSoapBinding" contract="OurServiceClient.OurServiceClient" name="OurServiceClientImplPort"/>
</client>
</system.serviceModel>

Java WebService with .NET issue. Results different with scvutil /wrapped and not

I'm using a well known vendor's API with a WSDL link1, link2 (click wait to download):
The above mentioned documentation wants me to create an Authentication request packet like this:
<soapenv:Envelope xmlns:soapenv=‖http://schemas.xmlsoap.org/soap/envelope/‖
xmlns:web=‖http://UltraWebServiceLocation/‖>
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand=‖1‖ xmlns:wsse=‖http://docs.oasisopen.
org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd‖>
<wsse:UsernameToken wsu:Id=‖UsernameToken-16318950‖ xmlns:wsu=‖http://docs.oasisopen.
org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd‖>
<wsse:Username>bwooster</wsse:Username>
<wsse:Password Type=‖http://docs.oasis-open.org/wss/2004/01/oasis-200401-wssusername-
token-profile-1.0#PasswordText‖>**********</wsse:Password>
<wsse:Nonce>QTvkiqEFK7uJuOssMndagA==</wsse:Nonce>
<wsu:Created>2009-04-14T21:20:57.108Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
My client binding looks like this; and am using a service reference instead of a web reference.
UltraDNS.UltraDNS1Client client = new UltraDNS.UltraDNS1Client();
client.ClientCredentials.UserName.UserName = "user";
client.ClientCredentials.UserName.Password = "pass";
var results = client.getResourceRecordsOfZone("domain.com",1);
// Throws InvalidOperationException: There was an error reflecting 'UltraWSException'.
// Detail:
//{"Namespace='http://webservice.api.ultra.neustar.com/v01/' is not supported with rpc\\literal SOAP. The wrapper element has to be unqualified."}
The web config looks like this
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="UltraDNS1Binding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://ultra-api.ultradns.com:80/UltraDNS_WS/v01"
binding="basicHttpBinding" bindingConfiguration="UltraDNS1Binding"
contract="UltraDNSService.UltraDNS1" name="UltraWebServiceV01Port" />
</client>
</system.serviceModel>
When I use SVCUtil to generate the proxy class with the /wrap parameter I get the following error:
{"The top XML element 'result' from namespace '' references distinct types System.String and ZoneInfoData[]. Use XML attributes to specify another XML name or namespace for the element or types."}
You appear to have used "Add Web Reference". Please use "Add Service Reference" instead.
Then see Programming WCF Security.
The service is sending you a fault of some kind (UltraWSException). WCF is having trouble deserializing it, but if you turn on message tracing, you may be able to see what the error is, and fix it.

Getting started with Paypal Adaptive Payments in C# SOAP

I'm trying to start with Adaptive Payments by Paypal using SOAP interface.
When adding service reference to https://svcs.sandbox.paypal.com/AdaptivePayments?WSDL the following warning is shown by Visual Studio:
Custom tool warning: Cannot import wsdl:binding
Detail: The WSDL binding named AdaptivePaymentsSOAP11Binding is not valid because no match for operation CancelPreapproval was found in the corresponding portType definition.
XPath to Error Source: //wsdl:definitions[#targetNamespace='http://svcs.paypal.com/services']/wsdl:binding[#name='AdaptivePaymentsSOAP11Binding'] C:\cproj\daemon\Service References\PaypalSandboxApi\Reference.svcmap 1 1 daemon
Discarding this message, the reference added successfully.
In order to perform a transaction, I try to create the client:
var client = new PaypalSandboxApi.AdaptivePaymentsPortTypeClient()
This throws InvalidOperationException:
Could not find default endpoint element that references contract 'PaypalSandboxApi.AdaptivePaymentsPortType' 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.
Am I missing something?
Should I use missing AdaptivePaymentsSOAP11Binding and not AdaptivePaymentsPortTypeClient?
It looks like importing this WSDL doesn't generate the servicemodel config. I kludged one together like this (and updated the relevant classname to match yours, so you can copy/paste):
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="PaypalAdaptivePayBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="1048576" maxBufferPoolSize="1048576" maxReceivedMessageSize="1048576" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="65536" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://svcs.sandbox.paypal.com/AdaptivePayments"
binding="basicHttpBinding" bindingConfiguration="PaypalAdaptivePayBinding"
contract="PaypalSandboxApi.AdaptivePaymentsPortType"
name="PaypalAdaptivePay" />
</client>

InvalidOperationException when using soap client

I've added as wsdl file using the add servece reference dialog in vs2008.
MyService serviceproxy = new MyService();
When I instantiate the service proxy, I get an InvalidOperationException with the following text (translated from german):
Could not find default endpoint
element to the contract
"ServiceName.ServiceInterface" in the
service model refers client
configuration section. This may be
because: The application configuration
file was not found or not an endpoint
in the client element item is found,
which corresponded to this contract.
Where servicename is the name I give the service when I add it in vs2008 and ServiceInterface the interface which is automatically generated for it.
EDIT
here is what's in my app.config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="MyServiceBinding" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
You need something like this in your config:
<client>
<endpoint binding="basicHttpBinding"
bindingConfiguration="MyServiceBinding" contract="ServiceName.ServiceInterface"
name="MyServiceEndpoint">
</endpoint>
</client>
inside your tag
I just read your comment.
So Removed the address from the endpoint config.
You can choose to specify the endpoint completely in your code or just the address like this:
MyServiceClient proxy = new MyServiceClient();
proxy.Endpoint.Address = new EndpointAddress ("http://addressto your service"); //<-- address
Check your config file - web.config if you're in a ASP.NET web app or web site, app.config if it's a Winforms or console app.
There ought to be some config for your WCF service in there - anything below <system.serviceModel> would be fine. If not - add the necessary info to your config!
OK, so if you want to specify your endpoint URL in code, you need to do this when you instantiate your client proxy class - otherwise, it'll go look in config. Using this code snippet, you'll be using the http binding configuration settings from app.config, and specify the URL separately, in code:
BasicHttpBinding binding = new BasicHttpBinding("MyServiceBinding");
EndpointAddress address = new EndpointAddress(new Uri("http://localhost:8888/YourService"));
MyService serviceproxy = new MyService(binding, address);
That way, the basicHttpBinding object will read the settings from the config under the bindings with a name=MyServiceBinding.
Edit:
Sorry, my first answer was wrong. For the client you need:
ChannelFactory<Interface> factory = new ChannelFactory< YourServiceInterface >(new basicHttpBinding(), new EndpointAddress(new Uri("http://localhost:8888/YourService")));
YourServiceInterface proxy = factory.CreateChannel();

Categories