I have a winforms application that is consuming a WCF service. So far, the WCF service is a selfhosted service on the local pc. It contains several interfaces (one per program functionallity).
As an improvement I want to expose the service to the internet, so I can call it using a new mobile app. This can be easily done by configuring the router/firewall and use some kind of dynamic dns or remember the ip address (in worst case scenario).
But now, here comes the real question:
In a next step I will distribute the winforms app to several locations (call it customers), acompagnied with their local WCF service en their mobile app. In order to allow the customer to connect to their wcf service (using the mobile app), I can set up now a dynamic dns for each customer, but I don't want to do that. First of all, the best dyndns services are not free, or you have to renew periodically. Second, I want to offer the customers my own dns service so I can 'forward' their wcf call to their own local service.
The wcfdnsrouter should be located at a public webhost, where the customers ip address is provided with an ip-updater (as it is often the case for other dyndns services)
As an example, imagine this:
Customer A; IP1; endpoint: http://wcfdnsrouter.com/A
Customer B; IP2; endpoint: http://wcfdnsrouter.com/B
Where I want that
wcfdnsrouter.com/A will forward (or route?) ALL calls to IP1
and
wcfdnsrouter.com/B will forward (or route?) ALL calls to IP2
With this scenario, the customer can access his service using mobile app from every place on earth. Hardware configuration on customers site is not a problem.
The goal is to use a parameter, rather than having an other url per customer. This should reduce the configuration and avoid duplicating my service. However, it is still an open trace (in this case, I need to create a subdomain and copy the wcfdnsrouter that is nothing more than a ordinary routingservice).
So, the entry point seems to be a restfull service that routes the message to another ip address\service.
I did already some research about routingservices, but I think I'll not get where I want. Contentbased routing is not an option since I don't want to change all my interfaces to have a criteria. I do not see how to make the link between the parameter in the restfull service with the ip addres I need to call (so another service).
Security is not realy a issue at this moment.
Please note that is question is NOT about (free) dns services. The purpose is to create it myself. Activating a new customer should not be more than installing the auto-ip-updater and assigning some kind of code (like A and B) in the example.
I need some advice how to do that. Maybe I'm on the wrong track thinking about routing? Maybe there is a very easy way that I mis?
Thanks in advance!
Related
as you can see, I am relatively new on SO please don't kill me after posting this question :) I will do my best to describe the dilemma I am currently in.
I am creating something like a "Guardian Service" that is hosted on Windows Azure inside a Worker Role. This service has external ports, that can be accessed via HTTPS to allow clients to call it's service methods.
The WCF service is meant to call other services hosted in other Worker Roles that have only internal ports open, and which can be accessed only through the use of the Guardian Service. That's the main idea. Similar to a proxy or something.
I read already an excellent article from Jim O'Neil, what the caveats are when you try to access internal service points from within other WCF Services hosted in worker Roles:
His blog Troubleshooting Endpoints on a WCF Web Role
This is not the point for this question, and totally clear to me how to do that.
I have no idea at the moment, how I could do this, without implementing every contract from every single service I want to make accessible from within the Guardian Service to the outside world.
There must be a better way to decouple those things.
Any tips are appreciated.
Thank you.
I do not know the exact requirements for your project but I would say that what you are looking for is WCF Routing. I've used it in the past to redirect requests for different versions of Workflow instances.
The way it works is completely transparent to the client connecting to its endpoint. The router implementation must decide where to send the requests to, based on the request data (message headers and body).
In your case, if you are using SOAP and namespaces correctly, you might be able to base your decision on the message soap address and then send the request to the correct endpoint. You could also look at the Action property of the message.
Some links that might be useful:
http://msdn.microsoft.com/en-us/library/ee517423.aspx
http://www.codeproject.com/Articles/227699/RoutingService-on-Azure
I have two questions I hope I can get an answer for with regard to my service oriented application
I am creating a service oriented application where controls have no events, it's all done by calling services... that means the service url is written in my jQuery code, but this seems somehow not nice.... It's like what is the best option to save service urls?! I feel it's hard to maintain and not secure when it's written inside the page or inside javascript referenced file.
I am talking to a hosting company and they told me that I can host this application services on cloud server and the application on another servers.... not all in the same server, but my application services are self hosted, I mean the services are inside the application.... so to make things work as my hosting company wants, shall I host the restful services in IIS or how exactly?
Service URL must be in your page or script source file. It can be local address unless you are using cross domain calls and JSONP - cross domain calls requires absolute address. It is the same as any other web technology. If you want navigation to other page, you must provide URL. If you want some picture or css file you must provide URL. Security is up to you.
This will be the problem of cross domain calls. Normally JS calls can be done only to the same domain where the page is exposed. Once the application server is exposed on different domain name your calls will not work. To avoid that you must use JSONP (WCF 4 has support for that). Exposing rest services consumed by your application from self hosted application is strange. REST services are consumed by your clients - they are front-end services and should be part of your application hosted on front-end web server. Your back-end application server should not host anything directly accessible by your clients.
We currently have a WCF Service which is beginning to reach it's limits performance wise.
We have decided to add another server which will host another instance of the WCF Service.
We have web applications which must communicate with a specific server based on context... e.g. If the web application is dealing with objects from ServiceInstance1 then requests must be directed to ServiceInstance1's EndPoint. If the web application is dealing with objects from ServiceInstance2 then requests must be directed to ServiceInstance2's EndPoint.
I initially thought that a "Intermediate Service" or "Service Manager" could be created, the web application's Service Reference would be updated from the individual Service Instance to the "Intermediate Service" or "Service Manager" and said service would act as a "Broker" to the various Service Instances.
How is this accomplished?
I have currently added a ServiceReference to each service from the Manager however it seems that once a Service is "Referenced" it's types becomes specific to the that of the ServiceReference e.g.
ServiceInstance1's type's are all {ServiceInstance1}.
ServiceInstance2's type's are all {ServiceInstance2}.
I need the types to be the same on the web application end, so this obviously seems like the wrong way to do it.
I would also like that when methods are called on the client generated from referencing the "Intermediate Service" or "Service Manager" that the correct Service Instance is invoked, e.g.
IServiceManager.GetProjectById( {GUID} ) ->
Comes Back to ServiceManager ->
Determines which host has the project and returns the ProjectObject from the correct ServiceInstance.
Where ProjectObject is a Type Defined in ServiceInstance1 and ServiceInstance2.
I think the original service needs to have some of the DLL's pulled out so they can be referenced from the web application side and ServiceManager and a GenericWCF Client can be made.
If I am right hooray for me If someone can point me in the right direction I would appreciate it. If I am wrong can someone please scold me and show me how this is properly done!
The way to solve your problem is to create shared assembly with types used by both services. Reference this assembly on the client consuming your services (manager) and when creating proxies by Add service reference mark Reuse types from referenced assemblies.
What you are building is very simple message router. In WCF 4.0 there is additional support for routing services so you should check those features before developing your own. For WCF 3.5 MSDN magazine contains articles about building message router - part 1, part 2.
Just to Answer this and close it I wound up utilizing the Routing Strategy in .Net 4.0 and custom client class which I modeled after the generated classes from the Proxy.
Before I had the custom client ready I used the auto generated client code and I derived a class from it which allow me to change which service it was connecting to. I determined which service via a property which was made available on all service objects which were serialized.
Long story short this is working 100% as expected including the ServiceManager which can even be bypassed on certain calls which we allow.
We even have the ability to move a project from server to server during run time!
Thanks to everyone who helped! (Especially myself for actually doing the work without being spoon fed)
The easiest way to accomplish what you're trying to do is to stop generating your proxies using the server-hosted URL of the service. Instead, generate your proxies from the *.xsd and *.wsdl locally, and merely change the URL of the endpoint. Alternatively, you can use ChannelFactory<T> to generate proxies on-the-fly, and reference your interface .dll on the client side.
Once you've done that, you can use any common webserver load balancing technique to balance the load between the servers.
Not to put too fine a point on it, but Visual Studio's "Service Reference" is not useful, and should not be used, for services you develop. It's useful only for services developed externally, whose URL and contracts are likely to NEVER change. I personally have never had occasion to use it. For your own services, you should probably be using ChannelFactory<T> or a class based on ClientBase<T> to work out the proxies.
Greetings,
in our company we are developing wcf service. This is used as a server and it works quite well. Hover there is a wish from customer that after they login to application they would like to see which users are logged in too.
I read about CallbackContract (based on some wcf chat application). How can we achive this goal?
Similar question asked here
You can deffinetly manage the logged users inside the server. I have created a personal pattern for dealing with such situations, and it ussually goes like this:
create a client class inside the WCF server that will hold all the needed information about the client.
create 2 methods in the service: logIn, logOut. the login method should be able to gather all the informations about the client that you want to store. Make sure to define properties that can uniquely identify a client instance. When the client conencts to the server it calls the login method, allowing the server to gather and save the information from the client. If using callbacks, this is the place to save the CallBack context object, in the client obejt. You can now save the Client object in the WCF server instance (I use a dictioary). When the client logs out, it calls the log out method and the server removes the entry.
create a KeepAlive method in the server that regularry checks the connected clients to see if they are still connected (in case of network failure or app crash a client may not call the logout method).
I think this is the simplest way (not
saying it's the best) to manage
clients in the server. There is no
problem with having multiple clients
from the same computer (you save the
Context when a client logges in) as
long as you have a way of uniquely
identify clients.
As for your last question, having
multiple services should not be a
problem. In fact you have the same WCF
server with different contracts (and
endpoints) for the different services
you offer. ALl the contracts reside in
the same WCF server instance so they
all can access the connected client
list.
If you have further questions, I would
be happy to answer them.
You can find the code you need to actually build the WCF service you require here
I am validating users using the UserNamePasswordValidator.Validate(string username, string password) and the service is hosting itself (e.g. no IIS).
The problem I have is that if the user fails the validation I want to track the users IP address. This works fine of the user gets validated, because then the OperationContext has been initialized (it is null inside the validate method and not created until later).
Does anyone know how to get the clients IP address either in the validate method or before the validate method has been executed?
Yes, I know about how to get the IP address using RemoteEndpointMessageProperty but like I said, it never get that far if validation fails :-)
I've researched this to death all week, and I can't come up with a single blog entry or MSDN article that deals with the issue.
As far as I can tell, you cannot log IP address during the Validate stage.
The only workaround I can suggest is to host in IIS and use the weblogs there, which do log IP address. It's painful, unfortunately, but it may be the only way.
If you're hosting in IIS then this becomes much more simple. This chunk of config comes straight from my hosting web project and forces ASP.NET requests to come down the IIS pipeline rather than being dispatched straight to the ASP err bits of IIS.
aspNetCompatibilityEnabled: When this attribute is set to
true, requests to Windows Communication Foundation (WCF) services
flow through the ASP.NET HTTP pipeline, and communication over
non-HTTP protocols is prohibited.
See: http://msdn.microsoft.com/en-us/library/ms731336.aspx
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
I use the AuthenticationService and make use of the HttpContext to get at all the interesting stuff about the client, much of it is useful for things like ensuring a user isn't logging in from six different subnets as well as playing around with cookies.
Although I think this is applied to the MS AuthenticationService, any other services you have will need this attrib:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
If you want to pursue your non-IIS hosted service route, then I'd see what stuff is available inside the MS API using reflection, poking around on a WCF with the debugger while stopped, unfolding all those Non-public members.
I suppose the problem will be getting a reference to a bit of WCF which is initialized from which to start poking. You might have to register some kind of listener to one of the dispatchers when you setup the service host.
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.channeldispatcher.aspx
Edit:
Adding this link as my thoughts are that you'd need to get at stuff in WCF that's right down the stack before it gets to your code:
http://blogs.msdn.com/sonuarora/archive/2007/06/11/passing-soap-actions-to-adapter-inbound-handler-for-filtering-type-of-listeners.aspx