I'm trying to bind my WCF client using code instead of app.config as I'll need to change host IP addresses for different deployment.
This is my app.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ICX" maxReceivedMessageSize="1073741824" >
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://127.0.0.1/CX/CX.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICX" contract="CXService.ICX" name="WSHttpBinding_ICX">
<identity>
<servicePrincipalName value="host/SilverStar" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
and this is my code:
public static void StartUp()
{
XmlDictionaryReaderQuotas quota = new XmlDictionaryReaderQuotas();
quota.MaxArrayLength = 2147483647;
quota.MaxBytesPerRead = 2147483647;
quota.MaxDepth = 2147483647;
quota.MaxNameTableCharCount = 2147483647;
quota.MaxStringContentLength = 2147483647;
EndpointAddress addr = new EndpointAddress(new Uri("http://127.0.0.1/CX/CX.svc"));
WSHttpBinding binding1 = new WSHttpBinding();
binding1.Name = "WSHttpBinding_ICX";
binding1.MaxReceivedMessageSize = 1073741824;
binding1.ReaderQuotas = quota;
// Globals.CXClient is the client object
Globals.CXClient = new CXService.CXClient(binding1, addr);
// This line does not compile! Endpoint is read-only!!
Globals.CXClient.Endpoint = new ServiceEndpoint(new ContractDescription("CXService.ICX"), (Binding)binding1, addr);
}
The last line of the code does not compile as .EndPoint is read-only property.
Please help.
try this:
Globals.CXClient.Endpoint.Address = new System.ServiceModel.EndpointAddress("your url here");
This is how I did it.
Globals.CXClient.Endpoint.Contract = new ContractDescription("CXService.ICX");
Globals.CXClient.Endpoint.Binding = binding1;
Globals.CXClient.Endpoint.Address = addr;
However, I encountered another problem. I tried to replace the part:
<identity>
<servicePrincipalName value="host/SilverStar" />
</identity>
by using the following code:
addr.Identity = new SpnEndpointIdentity("host/SilverStar");
This one again fails to compile because addr.Identity is read-only.
I also tried this:
EndpointAddress addr = new EndpointAddress(new Uri("http://127.0.0.1/CX/CX.svc"), new SpnEndpointIdentity("host/SilverStar"), ???);
but the last parameter is an AddressHeaderCollection and I have no idea what should be placed in there.
Please help again. Thanks.
Related
I have a client which is a windows application called Windows.exe. I have a C# class library called ServiceFacade.dll and it has a config file called ServiceFacade.dll.config. In ServiceFacade.dll.config, I have client side bindings like below
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:5000/MyService"
binding="netTcpBinding"
contract="IMyService"
name="NetTcpBinding_MyService"/>
</client>
</system.serviceModel>
In ServiceFacade.dll, I have code like below to create proxy
NetTcpBinding binding = new NetTcpBinding("NetTcpBinding_MyService");
ChannelFactory<IMyService> chn = new ChannelFactory<IMyService>(binding);
IMyService service = chn.CreateChannel();
Windows.exe calls ServiceFacade.dll to make service calls.
But below line is looking for NetTcpBinding_MyService in Windows.exe.config instead of ServiceFacade.dll.config
How to make below line to see NetTcpBinding_MyService in ServiceFacade.dll.config but not Windows.exe.config ?
NetTcpBinding binding = new NetTcpBinding("NetTcpBinding_MyService");
You definitely can copy the configuration to the ServiceFacade.dll.config from the Windows.exe.config. I would rather create a service endpoint manually than to copy the configuration when I call the service by using ChannelFactory.
Client-side.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("https://vabqia969vm:21011/");
NetTcpBinding binding = new NetTcpBinding();
binding.OpenTimeout = new TimeSpan(0, 10, 0);
binding.MaxReceivedMessageSize = 2147483647;
binding.ReaderQuotas.MaxStringContentLength = 2147483647;
ChannelFactory<ITestService> factory = new ChannelFactory<ITestService>(binding, new EndpointAddress(uri));
ITestService service = factory.CreateChannel();
var result1 = service.GetData(34);
Console.WriteLine(result1);
}
}
//The service contract is shared between the client-side and the server-side.
[ServiceContract]
public interface ITestService
{
[OperationContract]
string GetData(int id);
}
Wish it is useful to you.
I did like below.
I added below in ServiceFacade.dll.config
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcpBindingConfiguration"
closeTimeout="00:10:00"
openTimeout="00:10:00"
receiveTimeout="00:10:00"
sendTimeout="00:10:00"
maxBufferSize="2147483647"
maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:5000/MyService"
binding="netTcpBinding"
contract="IMyService"
name="NetTcpBinding_MYService"
bindingConfiguration="netTcpBindingConfiguration" />
</client>
</system.serviceModel>
In ServiceFacade.dll, I have code like below to create proxy
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
Configuration config = ConfigurationManager.OpenExeConfiguration(path);
ConfigurationChannelFactory<IMyService> chn =
new ConfigurationChannelFactory<IMyService>(
"NetTcpBinding_MyService",
config,
new EndpointAddress("net.tcp://localhost:5000/MyService"));
IMyService iMyService = chn.CreateChannel();
I'm trying to call soap service in script task but getting this following error. I've added a serviceReference through wsdl url. I don't have idea about what this error is referring to. However i'm able to get the data in SOAPUI
"The header 'ReliableMessaging' from the namespace 'http://sap.com/xi/XI/Message/30' was not understood by the recipient of this message, causing the message to not be processed. This error typically indicates that the sender of this message has enabled a communication protocol that the receiver cannot process. Please ensure that the configuration of the client's binding is consistent with the service's binding."
below is the code i'm using
EndpointAddress endPointAddress = new EndpointAddress("https://sapnxcci.intel.com:8220/XISOAPAdapter/MessageServlet?senderParty=&senderService=MC4510&receiverParty=&receiverService=&interface=Segments&interfaceNamespace=http://intel.com/xi/Intel-MDM/Project/Segment");
SegmentsClient client = new SegmentsClient(BindingUtility.GetInitiativesBinding(), endPointAddress);
client.ClientCredentials.UserName.UserName = "sys_idwcons";
client.ClientCredentials.UserName.Password = "abdc";
SegmentResponse results = client.ListSegments(new SegmentRequest() { SegmentName = "" });
In GetInitiativesBinding contains the following.
public static BasicHttpBinding GetInitiativesBinding()
{
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.MaxReceivedMessageSize = 2147483647;
binding.MaxBufferSize = 2147483647;
binding.ReceiveTimeout = TimeSpan.FromMinutes(5);
binding.SendTimeout = TimeSpan.FromMinutes(5);
return binding;
}
and my App.Config file looks like this
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="SegmentsBinding" />
<binding name="SegmentsBinding1">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://sapnxcci.intel.com:8420/XISOAPAdapter/MessageServlet?senderParty=&senderService=MC4510&receiverParty=&receiverService=&interface=Segments&interfaceNamespace=http%3A%2F%2Fintel.com%2Fxi%2FIntel-MDM%2FProject%2FSegment"
binding="basicHttpBinding" bindingConfiguration="SegmentsBinding"
contract="ServiceReference1.Segments" name="HTTP_Port" />
<endpoint address="https://sapnxcci.intel.com:8220/XISOAPAdapter/MessageServlet?senderParty=&senderService=MC4510&receiverParty=&receiverService=&interface=Segments&interfaceNamespace=http%3A%2F%2Fintel.com%2Fxi%2FIntel-MDM%2FProject%2FSegment"
binding="basicHttpBinding" bindingConfiguration="SegmentsBinding1"
contract="ServiceReference1.Segments" name="HTTPS_Port" />
</client>
</system.serviceModel>
</configuration>
I think it's because the return message from PI contains the tags.
tags are only useful when you have a PI - PI connection.
Reference: https://archive.sap.com/discussions/thread/1839924
I have my first WCF example working. I have the host on a website which have many bindings. Because of this, I have added this to my web.config.
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
This is my default binding http://id.web, which works with the following code.
EchoServiceClient client = new EchoServiceClient();
litResponse.Text = client.SendEcho("Hello World");
client.Close();
I am now trying to set the endpoint address at runtime. Even though it is the same address of the above code.
EchoServiceClient client = new EchoServiceClient();
client.Endpoint.Address = new EndpointAddress("http://id.web/Services/EchoService.svc");
litResponse.Text = client.SendEcho("Hello World");
client.Close();
The error I get is:
The request for security token could not be satisfied because authentication failed.
Please suggest how I may change the endpoint address at runtime?
Additional here is my client config, requested by Ladislav Mrnka
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IEchoService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://id.web/Services/EchoService.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IEchoService" contract="IEchoService"
name="WSHttpBinding_IEchoService">
<identity>
<servicePrincipalName value="host/mikev-ws" />
</identity>
</endpoint>
</client>
</system.serviceModel>
So your endpoint address defined in your first example is incomplete. You must also define endpoint identity as shown in client configuration. In code you can try this:
EndpointIdentity spn = EndpointIdentity.CreateSpnIdentity("host/mikev-ws");
var address = new EndpointAddress("http://id.web/Services/EchoService.svc", spn);
var client = new EchoServiceClient(address);
litResponse.Text = client.SendEcho("Hello World");
client.Close();
Actual working final version by valamas
EndpointIdentity spn = EndpointIdentity.CreateSpnIdentity("host/mikev-ws");
Uri uri = new Uri("http://id.web/Services/EchoService.svc");
var address = new EndpointAddress(uri, spn);
var client = new EchoServiceClient("WSHttpBinding_IEchoService", address);
client.SendEcho("Hello World");
client.Close();
This is a simple example of what I used for a recent test.
You need to make sure that your security settings are the same on the server and client.
var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.None;
var myEndpointAddress = new EndpointAddress("http://servername:8732/TestService/");
client = new ClientTest(myBinding, myEndpointAddress);
client.someCall();
app.config
<client>
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="LisansSoap"
contract="Lisans.LisansSoap"
name="LisansSoap" />
</client>
program
Lisans.LisansSoapClient test = new LisansSoapClient("LisansSoap",
"http://webservis.uzmanevi.com/Lisans/Lisans.asmx");
MessageBox.Show(test.LisansKontrol("","",""));
We store our URLs in a database and load them at runtime.
public class ServiceClientFactory<TChannel> : ClientBase<TChannel> where TChannel : class
{
public TChannel Create(string url)
{
this.Endpoint.Address = new EndpointAddress(new Uri(url));
return this.Channel;
}
}
Implementation
var client = new ServiceClientFactory<yourServiceChannelInterface>().Create(newUrl);
I'm trying to move the endpoint and wshttpbinding configuration to a c# file so I can change the endpoint address at runtime (select from dropdown, process etc). However after creating a WsHttpBinding object, EndpointAddress object and passing them to my client. It will throw the following exception:
System.ServiceModel.FaultException: The caller was not authenticated
by the service
This is the same exception I get if the user credentials are incorrect. However they haven't changed from using the Web.config file to creating these config options programmatically.
Web.config (works):
<binding name="myService" maxReceivedMessageSize="2147483647">
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" establishSecurityContext="false" />
</security>
</binding>
<client>
<endpoint
address="https://address/myservice.svc"
binding="wsHttpBinding"
bindingConfiguration="myService"
contract="MyService.IMyService"
name="myService"
/>
</client>
MyService service = new MyService();
service.username = "user";
service.password = "pass";
//Success
Programmatically (does not work):
WSHttpBinding wsHttp = new WSHttpBinding();
wsHttp.MaxReceivedMessageSize = 2147483647;
wsHttp.ReaderQuotas.MaxDepth = 2147483647;
wsHttp.ReaderQuotas.MaxStringContentLength = 2147483647;
wsHttp.ReaderQuotas.MaxArrayLength = 2147483647;
wsHttp.ReaderQuotas.MaxBytesPerRead = 2147483647;
wsHttp.ReaderQuotas.MaxNameTableCharCount = 2147483647;
wsHttp.Security.Mode = SecurityMode.TransportWithMessageCredential;
wsHttp.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
wsHttp.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
wsHttp.Security.Message.EstablishSecurityContext = false;
EndpointAddress endpoint = new EndpointAddress("https://address/myservice.svc");
MyService service = new MyService(wsHttp, endpoint);
service.username = "user";
service.password = "pass";
//System.ServiceModel.FaultException: The caller was not authenticated by the service
I've tried following tutorials / looking at answers but I can't figure it out.
My solution
Keep the binding the same.
Change the endpoint so there is no address
<client>
<endpoint
binding="wsHttpBinding" bindingConfiguration="myService"
contract="MyService.IMyService" name="myService" />
</client>
Change endpoint at run time by changing the Uri object and pass the endpoint name your service as the first argument
Uri uri = new Uri("https://address/myservice.svc");
var address = new EndpointAddress(uri);
service= new MyService("myService", address);
service.username = "user";
service.password = "pass";
You can remove EVERYTHING in your app.config - so there is no binding or interface info.
Your runtime code is this:
//create an endpoint address
var address = new EndpointAddress("http://localhost:51353/EmployeeService.svc");
//create a WSHttpBinding
WSHttpBinding binding = new WSHttpBinding();
//create a channel factory from the Interface with binding and address
var channelFactory = new ChannelFactory<IEmployeeService>(binding, address);
//create a channel
IEmployeeService channel = channelFactory.CreateChannel();
//Call the service method on the channel
DataSet dataSet = channel.SelectEmployees();
Just for reference, here is my app.config:
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
/************ You can dumb this down to this: ********************************/
var factory = new ChannelFactory<IEmployeeService>(new WSHttpBinding());
var channel = factory.CreateChannel(new EndpointAddress("http://localhost:51353/EmployeeService.svc"));
When I am trying to read a meta data I got this error any Idea here is My code
WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
binding.MaxReceivedMessageSize = Int32.MaxValue; // DPNote: This may actually be too big. see how it performs.
binding.ReaderQuotas.MaxNameTableCharCount = 99999999;
MetadataExchangeClientMode exchangeMode = MetadataExchangeClientMode.HttpGet; // Default to a HttpGET
metaClient = new MetadataExchangeClient(binding);
metaClient.MaximumResolvedReferences = 10 * 100; //DPNote: Some arbitrary number. Default is 10, so this is bigger.
if (address.Scheme == "http")
exchangeMode = MetadataExchangeClientMode.HttpGet;
else if (address.Scheme == "https")
exchangeMode = MetadataExchangeClientMode.HttpGet;
else
exchangeMode = MetadataExchangeClientMode.MetadataExchange;
MetadataSet metadata = metaClient.GetMetadata(address, exchangeMode);
MetadataImporter importer = new WsdlImporter(metadata);
and this is the line which throws the error
MetadataSet metadata = metaClient.GetMetadata(address, exchangeMode);
If you are doing 'Update Reference' through visual studio, add these lines to devenv.exe.config
<system.serviceModel>
<client>
<endpoint binding="netTcpBinding" bindingConfiguration="GenericBinding" contract="IMetadataExchange" name="net.tcp" />
</client>
<bindings>
<netTcpBinding>
<binding name="GenericBinding"
maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
This is a error in Microsoft code,Http-Get not support Reader Quotas, so we can do this
var smAsm = AppDomain.CurrentDomain.GetAssemblies().First(a => a.FullName.StartsWith("System.ServiceModel,"));
var defTy = smAsm.GetType("System.ServiceModel.Channels.EncoderDefaults");
var rq = (System.Xml.XmlDictionaryReaderQuotas)defTy.GetField("ReaderQuotas", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
rq.MaxArrayLength = int.MaxValue;
rq.MaxDepth = int.MaxValue;
rq.MaxNameTableCharCount = int.MaxValue;
rq.MaxStringContentLength = int.MaxValue;
Have you tried incrementing any of these other values inside of binding.ReaderQuotas beyond their default values:
maxDepth, maxStringContentLength, maxArrayLength, maxBytesPerRead?
It could also be the maxBufferPoolSize of the binding
The problem seems to be fixed in .NET 4.0. According to Reflector, MetadataExchangeClient now reads the quotas from the supplied binding, and if it doesn't have those, it falls back to EncoderDefaults. Previously, I think it only used EncoderDefaults, that's why #BreakHead's solution seems to be the only solution (to change EncoderDefaults with reflection).