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");
Related
I am developing on Windows application in c# and I am using web server's web service in this Windows application.
The web service should be dynamic and I need to change it in the application.
I managed to do it by this code :
CallWebService.MyWS ws = new CallWebService.MyWS();
ws.Url = "new url";
This new url will be set as per client's web server url.
I am calling this web service (I mean web service functions) 20 to 25 times in my application.
Do I need to change this path everytime when I call it or for the first time will be ok ?
Use a fixed port number for your service and configure this url in your app/web.config file and use it in your code.
Create a helper class and use that. Make it configurable by using an app setting or better store in config table in database if you are using one.
If you are using WCF client, you can pass URL in client constructor. Otherwise create a partial class for your webservice to create that constructor.
public class MyWebServiceHelper
{
private string _url = null;
public MyWebServiceHelper()
{
this._url = GetWsUrlFromDbOrAppConfig();
}
public CallWebService.MyWS GetMyWebServiceProxy()
{
return new CallWebService.MyWS("WcfBindingConfig", _url);
}
}
Need a way for one service on a well-known Endpoint to return strings which are relative addresses. The client can then connect to Endpoints using these relative addresses.
Clearly this resembles REST in some ways, but in this case running a Windows Service using NetNamedPipeBinding for IPC, so no need for HTTP.
Don't want to create the Endpoint ahead of time since there will be a potentially large number of relative addresses, only some of which the client would be interested in.
All Contracts are known in advance.
Tried to find a solution with AddressFilterMode but wasn't sure how to provision new Binding so that client connected to it, UriTemplate but don't want to use the HTTP framework. Haven't looked into RoutingService because constrained to .Net 3.5.
Pseudocode for client would be something like that below...
namespace Testing
{
class RunTest
{
static void Test()
{
NetNamedPipeBinding namedpipe = new NetNamedPipeBinding();
ChannelFactory<Contracts.IRoot> factoryRoot =
new ChannelFactory<Contracts.IRoot>(
namedpipe
, new EndpointAddress("net.pipe://localhost/root");
);
Contracts.IRoot root = factoryRoot.CreateChannel();
ICommunicationObject commsRoot = root as ICommunicationObject;
commsRoot.Open();
// Service examines address and creates Endpoint dynamically.
string address = root.SomeFunctionWhichGetsARelativeAddress();
// IBar service routes endpoint requests internally based on
// "address" variable.
ChannelFactory<Contracts.IBar> factoryBar =
new ChannelFactory<Contracts.IBar>(
namedpipe
, new EndpointAddress("net.pipe://localhost/root/IBar/" +
address)
);
Contracts.IBar bar = factoryBar.CreateChannel();
bar.DoSomething();
}
} // Ends class RunTest
} // Ends namespace Testing
Message Filters are the way to go. You can use “Prefix” or create a custom.
WCF Addressing In Depth
From the Message Filters section of the article:
...it uses message filters to determine the matching endpoint, if one
exists. You can choose which message filter to use or you can provide
your own. This flexibility allows you to break free from the
traditional dispatching model when using Windows Communication
Foundation to implement things other than traditional SOAP—for
instance, the techniques described here enable you to implement
REST/POX-style services on the Windows Communication Foundation
messaging foundation.
Nice question, by the way. I learned something trying to figure this out.
AddressFilterMode.Prefix might suffice. The actual Endpoint used can be inspected in Service methods via
OperationContext.Current.IncomingMessageHeaders.To
Helper code can parse the endpoint and do any necessary internal processing from there.
Hopefully there's some extensibility on the server side which can simplify that code.
Pseudocode for host:
namespace Services
{
[System.ServiceModel.ServiceBehavior(AddressFilterMode =
System.ServiceModel.AddressFilterMode.Prefix)]
class BarService : Contracts.IBar
{
#region IBar Members
public void DoSomething()
{
System.Uri endpoint = System.ServiceModel.OperationContext.Current.IncomingMessageHeaders.To;
Console.WriteLine("DoSomething endpoint: {0}", endpoint);
}
} // Ends class BarService
} // Ends namespace Services
class RunHost
{
static void HostIBar()
{
System.Uri uriBase = new System.Uri("net.pipe://localhost");
System.ServiceModel.ServiceHost hostBar =
new System.ServiceModel.ServiceHost(
typeof(Services.BarService),
uriBase);
hostBar.AddServiceEndpoint(
typeof(Contracts.IBar) // Type implementedContract
, namedpipeBinding // System.ServiceModel.Channels.Binding binding
, "root/IBar" //string address
);
hostBar.Open();
Console.WriteLine("Press <ENTER> to stop...");
Console.ReadLine();
}
}
Correction: I'd originally said that this wouldn't treat "net.pipe://localhost/root/IBar/1" and "net.pipe://localhost/root/IBar/2" as distinct endpoints, but it does. Each causes its own WCF Service instance to be created and called.
An additional change was to encode the data in URL style query parameters and not embed it in the path. E.g.: "net.pipe://localhost/root/IBar?something=1&somethingelse=11" and "net.pipe://localhost/root/IBar?something=2&somethingelse=22" using HttpUtility.ParseQueryString
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.
To access OData on Windows Phone you do this:
// Declare the data service objects and URIs.
NorthwindEntities context;
Uri northwindUri =
new Uri("http://services.odata.org/Northwind/Northwind.svc/");
DataServiceCollection<Customer> customers;
// Initialize the context and the binding collection
context = new NorthwindEntities(northwindUri);
customers = new DataServiceCollection<Customer>(context);
// Define a LINQ query that returns all customers.
var query = from cust in context.Customers
select cust;
// Register for the LoadCompleted event.
customers.LoadCompleted
+= new EventHandler<LoadCompletedEventArgs>(customers_LoadCompleted);
// Load the customers feed by executing the LINQ query.
customers.LoadAsync(query);
But I already know the URL from the service reference.
Can't I just pass that to the URI argument?
Is there an easy way to access it's configured URL?
Is this a good idea?
If you have a service client defined you can get the URI used by doing:
client.Endpoint.Address.Uri
In the app.config the service reference is defined:
<client>
<endpoint address="http://localhost:36294/Services/Service1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
</client>
If you have this in your application already (web.config for web app). Then you dont need to define the endpoint at all as it already exists and will be grabbed upon instantiation.
This is assuming that the service is a WCF service and a reference is added via 'Add Service Reference...'
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.