I have a container running in SF. A WCF service is running inside the container on port 7777 and is bind to the host on the same port.
I have written a second SF service and deployed it on the cluster.
I have used the WCFComuunicationClientFactory to talk to the WCF service running inside the container.
However, I am getting an exception of type: EndPointNotFoundException on uri:
net.tcp://MyPc.XXX.com:7777/.
This makes sense since the contracts are exposed this way: net.tcp://MyPc.XXX.com:7777/ContractType.
How can I make it work?
I am attaching the code of the service trying to contact the container:
var wcfClientFactory = new WcfCommunicationClientFactory<MyContractService>(
clientBinding: binding,
servicePartitionResolver: partitionResolver
);
var newClient = wcfClientFactory.GetClientAsync(
new Uri("fabric:/MyContainerService"),
ServicePartitionKey.Singleton,
TargetReplicaSelector.Default,
null,
new OperationRetrySettings(),
CancellationToken.None
).Result;
var x = newClient.Channel.GetX();
when Accessing 'GetX' I get the endpoint exception.
The solution is inside the container endpoint definition in the service fabric serviceManifest.xml file.
It is possible to add a pathSuffix, like this:
<Endpoint Name="MyEndPoint" UriScheme="net.tcp" Port="3000" Protocol="tcp" PathSuffix="YourService" />
This will result in the following end point:
net.tcp://<host>:3000/YourService
Notice you can have as many as endpoints as you like, and in order to choose one from the client contacting the service inside the container, you should specify the parameter: 'listenerName' when creating 'ServicePartitionClient', which represents your EndPoint name.
Related
I try to use web service for weather
http://www.webservicex.com/globalweather.asmx?WSDL
I make console application and try to use this service. First of all I add reference and name the reference WeatherService and write below code
Console.WriteLine("Now we get weather, please wait .......");
WeatherService.GlobalWeatherSoapClient w = new WeatherService.GlobalWeatherSoapClient();
Console.WriteLine(w.GetWeather("Lahore","Pakistan"));
But it gives me a exception
Additional information: An endpoint configuration section for contract 'WeatherService.GlobalWeatherSoap' could not be loaded because more than one endpoint configuration for that contract was found. Please indicate the preferred endpoint configuration section by name.
I am learning web services and don't know why this happens. Any one help me on this is great favor. Advance thanks.
Open your app.config, find needed then pass it's name to GlobalWeatherSoapClient(here):
in your app.config should be setting like this:
<endpoint address="http://www.webservicex.com/globalweather.asmx"
binding="basicHttpBinding" bindingConfiguration="GlobalWeatherSoap"
contract="WeatherService.GlobalWeatherSoap" name="GlobalWeatherSoap" />
get name and pass it to client:
WeatherService.GlobalWeatherSoapClient w = new WeatherService.GlobalWeatherSoapClient("GlobalWeatherSoap");
I have one solution in which I have 2 projects with:
ASP.NET MVC Application to consume wcf services.
5 WCF services.
I have added one web service reference in the project 1. Now, I need to use different services based on the user e.g.
User Type 1: Only allow to consume Service 1.
User Type 2: Only allow to consume Service 2.
etc.
I have Service URL's like localhost:6227/Service1.svc, localhost:6227/Service2.svc etc.
I have stored all service URL's in the db and I need to change URL for each user type to consume his allowed service only without adding more end points and only change URL from the backend based on user type. I need relevant link or code to solve this problem.
Edit
In Web Config
I have added just this endpoint in the mvc application and I don't want to use web config to change address in here but I want to change address in the code for each user type while application is running.
<client>
<endpoint address="http://localhost:6227/Service1.svc"
binding="customBinding" bindingConfiguration="CustomBinding_IService1"
contract="Service1.IService1" name="CustomBinding_IService1" />
</client>
if i completely realize your question you need dynamic soap service calling. maybe something like this:
private void CallService()
{
var myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.None;
var myEndpointAddress = new EndpointAddress("your url depend on user type");
var client = new ClientService1(myBinding, myEndpointAddress);
var outpiut = client.someCall();
client.close();
}
Not sure if I understand you correctly but you could use below snippet, if it suits.
//assuming you get string URL. Change type as per need.
string reqdURL = GetServiceURL(typeof(userObject));
private string GetServiceURL(Type userType)
{
if (userType == typeof(UserType1))
{
// currently hardcoded but you can replace your own fetch logic
return "localhost:6227/Service1.svc";
}
if (userType == typeof(UserType2))
{
return "localhost:6227/Service2.svc";
}
//and so on
}
You can modify directly your EndPoint Address doing this:
ClientService1 ws = new ClientService1();
ws.Endpoint.Address = new EndpointAddress("Your new URL svc service");
I have a WCF Service in which I want to maintain session for my Authentication method.
I have gone through from various articles and applied some of the below changes which are required to maintain session in WCF Service, as WCF not supported Session by default.
1- [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] in svc file.
2- [ServiceContract(SessionMode = SessionMode.Allowed)] in ServiceContract
3- Use the wsHttpBinding as basicHttpBinding not supported Session.
I am using WCFTestClient to call my service. I have checked the config of my TestClient and it is using basicHttpBinding, here is the cause of issue.
I am unable to implement the 3 point in my Service webconfig and also unable to change the config of my TestClient. Can anyone please guide me. Thanks
To solve this I implemented my own SessionHandler within the service.
a thread safe singleton class containing a Dictionary<Guid, SessionData>
Service Method: Guid RegisterClient(ClientName clientName) { /* add client to session */ }
Service Method: bool UnregisterClient(Guid clientGuid) { /* remove client from session */ }
Service Method: void DoThisOnServer(Guid clientGuid) { /* the service functionality */}
void CheckTimeout() { /* iterate over dictionary and remove out timed sessions */ }
Hints:
SessionData contains ClientName, TimeOfConnection, YourUsefulData
ClientName is a placeholder for IP-Adresse or some other initial identificator
Client has to register and all following operations are done only if the provided Guid exists in SessionHandler.
I have a WCF RESTful service that I want to integration test so need to create an instance of the service locally within the test with a reference to a client channel that I can call. I can do this, however the code I'm using will only call the Services default parameterless constructor as below
_serviceHost = new WebServiceHost(typeof(UserService), baseAddress);
var binding = new WebHttpBinding();
_serviceHost.AddServiceEndpoint(typeof(Interface.IUserService), binding, address.Uri);
_serviceHost.Open();
In my UserService class, I want to inject a dependency into it for the data repository, as so
public UserService(IUserDataRepository userRepository)
{
_userRepository = userRepository;
}
How can I adapt the first lot of code so that I can create and self host my WCF REST service with an IDataRepository object that I create (Mock) in the test class?
Well, I think you can use the same approach as you have for production environment. I might be wrong but you must already have your custom ServiceHost and ServiceHostFactory. If not please take a look at this article Using Instance Provider and ServiceHostFactory to Construct the Service. You want to read through steps steps 1-3. You will need to derive from WebServiceHost to implement your own one. Then your code will look like that:
_serviceHost = new YourCustomServiceHost(typeof(UserService), baseAddress);
Hope it helps!
I have a small WCF Client which I'm trying to configure for service discovery via the application configuration file - however whenever I do this:
// Create a new DiscoveryClient instance from the 'DiscoveryEndpoint'
// configuration in App.config
DiscoveryClient discoveryClient = new DiscoveryClient("DiscoveryEndpoint");
I get an ArgumentNullException, Value cannot be null. Parameter name: contract. There is no contract parameter for this overload of the DiscoveryClient constructor, and the contract is correctly specified in the App.config (see below).
Here are the relevant sections of the App.config:
<system.serviceModel>
<client>
<endpoint name="DiscoveryEndpoint"
contract="IExampleContract"
kind="dynamicEndpoint"
endpointConfiguration="DynamicEndpointConfiguration"/>
</client>
<standardEndpoints>
<dynamicEndpoint>
<standardEndpoint name="DynamicEndpointConfiguration">
<discoveryClientSettings>
<endpoint kind="udpDiscoveryEndpoint"/>
<findCriteria duration="00:00:02">
<types>
<add name="IExampleContract"/>
</types>
<scopes>
<add scope="urn://wcf.test.com/examples/exampleContract/development"/>
</scopes>
</findCriteria>
</discoveryClientSettings>
</standardEndpoint>
</dynamicEndpoint>
</standardEndpoints>
</system.serviceModel>
This is targetted at .NET Framework 4.0, using Visual Studio 2010 SP1.
The documentation for this overload of the DiscoveryClient(string) constructor indicates that this should create a new DiscoveryClient instance with the configuration identified in App.config.
Has anyone else encountered this behaviour, and if so how did you resolve it?
The "DiscoveryEndpoint" that you defined in the config file is actually a service client end point, not the DiscoveryClient end point.
The following should work:
var exampleContractChannelFactory = new ChannelFactory<IExampleContract>("DiscoveryEndpoint");
var exampleContractClient = exampleContractChannelFactory.CreateChannel();
// You can now invoke methods on the exampleContractClient
// The actual service endpoint used by the client will be looked up dynamically
// by the proxy using the DiscoveryClient class internally.
OK, I've spent a lot of time in the debugger with the Enable .NET Framework source stepping option enabled, and I've found that the cause of this exception being thrown is (probably) a bug in the implementation of the way that the DiscoveryClient is instantiated from the configuration file - there is a call way down the call stack which passes a hard-coded value of null into a contract parameter, which is where the originating exception is thrown.
So, after much head-scratching, and lots of searching, I've come up with the following workaround (well, more like a total HACK:!) - which I'm posting here to help out anyone else who might encounter the same issue.
// HACK: The following is a workaround for a bug in .NET Framework 4.0
// Discovery should be possible when setup from the App.config with the
// following three lines of code:
//
// discoveryClient = new DiscoveryClient("DiscoveryEndpoint");
// Collection<EndpointDiscoveryMetadata> serviceCollection = discoveryClient.Find(new FindCriteria(typeof(IExampleContract))).Endpoints;
// discoveryClient.Close();
//
// However, a bug in the Discovery Client implementation results in an
// ArgumentNullException when running discovery in this way.
//
// The following code overcomes this limitation by manually parsing the
// standard WCF configuration sections of App.config, and then configuring
// the appropriate FindCriteria for a programmatically configured discovery
// cycle. This code can be replaced by the above three lines when either
// 1. The bug in .NET Framework 4.0 is resolved (unlikely), or
// 2. The application is retargeted to .NET Framework 4.5 / 4.5.1
//
// To aid future developers, this HACK will be extensively documented
// Load the App.config file into a ConfigurationManager instance and load the configuration
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Get the ServiceModel configuration group
ServiceModelSectionGroup serviceModelGroup = ServiceModelSectionGroup.GetSectionGroup(configuration);
// Get the StandardEndpoints configuration node
StandardEndpointsSection section = serviceModelGroup.StandardEndpoints;
// Get the DynamicEndpoint configuration node
Configuration dynamicEndpointConfiguration = section["dynamicEndpoint"].CurrentConfiguration;
// Get the first DynamicEndpoint configuration
// HACK: This assumes only one DynamicEndpoint configuration exists
// No additional configurations will be interpreted. This should
// not pose a problem as typically a client will only access a
// single service instance. This can be extended if necessary
// at a later time.
DynamicEndpointElement element = ((DynamicEndpointElement)serviceModelGroup.StandardEndpoints["dynamicEndpoint"].ConfiguredEndpoints[0]);
// Set the required Contract Type
// HACK: This is currently hard-coded to prevent the need to specify
// an AssemblyQualifiedName in the App.config file. This will
// not typically pose a problem as each client will typically
// only open a single service exposing a single, well-known,
// Contract Type
FindCriteria criteria = new FindCriteria(typeof(IExampleContract));
// Add all required Scopes to the FindCriteria instance
foreach (ScopeElement scopeElement in element.DiscoveryClientSettings.FindCriteria.Scopes)
{
criteria.Scopes.Add(scopeElement.Scope);
}
// Get the Discovery Duration
criteria.Duration = element.DiscoveryClientSettings.FindCriteria.Duration;
// Create a new Discovery Client instance
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
// Retrieve the matching Service Endpoints via Dynamic Search
Collection<EndpointDiscoveryMetadata> serviceCollection = discoveryClient.Find(criteria).Endpoints;
// Close the Discovery Client
discoveryClient.Close();
// HACK: END -- Process the results of Discovery
Note that I'm assuming that this issue is resolved in .NET Framework 4.5 / 4.5.1 - it may not be, but I cannot test that at the moment.
If anyone else has an alternative solution, more elegant or efficient than this, please post it to help others.