How to make your Service-Reference proxy URL dynamic? - c#

I have a web reference to web-service:
using (var client = new GetTemplateParamSoapClient("GetTemplateParamSoap"))
{
TemplateParamsKeyValue[] responsArray = client.GetTemplatesParamsPerId(
CtId, tempalteIds.ToArray());
foreach (var pair in responsArray)
{
string value = FetchTemplateValue(pair.Key, pair.Value);
TemplateComponentsData.Add(pair.Key, value);
}
}
Tried to change a web-reference url from c# code: as advice here:
1) http://www.codeproject.com/KB/XML/wsdldynamicurl.aspx
2) How to call a web service with a configurable URL
3) http://aspalliance.com/283_Setting_Web_Service_References_Dynamically
But I get symbol is missing when trying to do:
client.Url
In addition I couldn't find a property of "Url_behavior"

It sounds like you've already added the service reference, but here's a walkthrough on adding, updating and removing service references.
Once you've got one of those in your project, you can alter the endpoint URI with one of the constructor overloads, as John Saunders said above. To do this, you'll need to know the name of the endpoint in your config file. For instance, after you add your service you might have elements like this in your config file:
<endpoint address="http://bleh.com/services/servicename.asmx"
binding="basicHttpBinding" bindingConfiguration="ServiceNameSoap"
contract="ServiceReference1.ServiceNameSoap" name="ServiceNameSoap" />
Given that endpoint, you can change the address at runtime by using the following overload:
var proxy = new ServiceReference1.ServiceNameSoapClient("ServiceNameSoap",
"http://new-address.com/services/servicename.asmx");
You can also do it after construction, but that becomes a little bit harder. If you need to do so, see the documentation on the Endpoint property and the associated type ServiceEndpoint.

Related

Pass a valid endpoint name to the service client constructor

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");

Dynamically Change WCF Service URL in ASP.NET MVC

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");

ServiceModel.Discovery.DiscoveryClient(string endpointConfigurationName) throws ArgumentNullException

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.

Could not find endpoint element with name and contract

I have added reference to a WCF service that has two end points. On adding the service the following get added to the Config file:
<client>
<endpoint name="ABCServiceV1" address="http://staging.ABCwebservices.com/ABC/Service.svc"
binding="basicHttpBinding" bindingConfiguration="ABCServiceV1"
contract="ABCService.IService" />
<endpoint name="ABCServiceV2" address="http://staging.ABCwebservices.com/ABC/Service.svc/20"
binding="basicHttpBinding" bindingConfiguration="ABCServiceV2"
contract="ABCService.IService1" />
</client>
The code to create the client is as as below:
ABCService.ServiceClient ABCClient = new ServiceClient("ABCServiceV2");
However, I am getting an runtime error - "Could not find endpoint element with name 'ABCServiceV2' and contract 'ABCService.IService' 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 name could be found in the client element."
if i used ABCService.ServiceClient ABCClient = new ServiceClient("ABCServiceV1"); then everything works fine. But when using ABCServiceV2 it is trying to look for Contract - ABCService.IService - when it should be looking for - ABCService.IService1.
How do i make it look for the correct contract?
If you added a second reference to a different service (ABCServiceV2) then I believe this will have generated a second service class for ABCServiceV2. The two classes will implement separate contracts (ABCService.IService and ABCService.IService1) so you won't be able to interchange the endpoints.
I believe you should be able to initialise your two service endpoints like so:
ABCService.ServiceClient ABCClient = new ServiceClient("ABCServiceV1");
ABCService.Service1Client ABCClient1 = new Service1Client("ABCServiceV2");
Even though this post is old and answered, the answer didn't help in my case.
My problem was I generated the service client with the svcutil.exe tool, but didn't specify any namespace at all; and so the contract namespace name was generated as the target namespace of the schema document by default, yes total mess.
On the other hand I was trying to use the config file generated when a service reference is added to the project. The contract namespace in this file is ServiceReference1 (by default) or any other name you want, perfect storm! But all I had to do was to remove the namespace part from the FQN from the <endpoint>'s contract attribute, and the contract became visible to the CLR.
Hope this help others

WCF does not generate the properties

I have a .NET 1.1 ASMX and want to use it in a client WinForms app.
If i go wit the old way and add it as a "WebRefrence" method then I will have access to two of its properties which are "url" and "UseDefaultCredentials" and it works fine.
But if I go with the new WCF way and add it as a ServiceReference I still have access to the methods of that ASMX but those two properties are missing.
what is the reason for that?
so for example in the old way ( adding WebReference) these codes are valid:
TransferService transferService= new TransferService();
transferService.Url = "http://something.asmx";
transferService.Credentials = System.Net.CredentialCache.DefaultCredentials;
string[] machines = transferService.GetMachines();
But in the new way ( adding Service Reference )
using(TransferServiceSoapClient transferServiceSoapClient = new TransferServiceSoapClient("TransferServiceSoap"))
{
transferServiceSoapClient.Url = "someUrl.asmx"; //Cannot resolve URL
transferServiceSoapClient.GetMachines(new GetMachinesRequest());
transferServiceSoapClient.Credentials = .... // //Cannot resolve Credentials
}
Because those are configured in the endpoint in your app/web.config or programatically if you prefer. More on configuring a WCF client here.

Categories

Resources