I am relatively green with C# and WCF. I have landed on a project where I am creating self hosted WCF services running as Windows services but am starting to wonder if I should use IIS instead (which we don't currently use) as managing all of these services could eventually get cumbersome.
Despite my best efforts, I have yet to find any definitive information about why I might favor one approach over the other. The services are primarily used for utility stuff like resizing images, retrieving files, etc. and are called by both C# and Java clients.
Thanks
The shortest answer would be 'it depends'. On your requirements. You can self host without problems, but IIS will manage resources more effectively and enable you to fine tune stuff more easily than self-hosted.
For instance, in IIS would be more simple to deploy a new version or remove and old one.
Either way is fine.
Generally, using the builtin IIS hosting capabilities can make deployment and configuration simpler for you. Also you have the activation model of http.sys - which means IIS will start the necessary process for you when an appropriate message arrives.
Clients of any platform can connect to the WCF services regardless whether they are self-hosted or IIS hosted.
ps: how to allow IIS-hosted WCF services to store their configuration data in distinct xxx.config files
Related
I am trying to run a background service which just writes to a file on a specified interval.
There are two methods that I tried
1) Created the project with the Console application template
2) Created the project with Web Application as template
When I run the app from visual Studio, both of them run fine. But when I deploy them to IIS, only the web application version works. It must be noted that there is absolutely no difference between the code of the two projects. I have used the WebHost as a hosting strategy in both the projects as well as well as installed all the dependencies in case of Console application as there are in the Web Application version.
I must also inform that I have used the preloadEnabled="true" option in IIS as IIS needs a web request to start the application.
I am wondering what is the difference between both the project types as the code is the same? I don't want the Web Application template.
Edit 1: I forgot to mention that the service will also need to expose an api endpoint for healthcheck purposes. Will the windows service approach listen for http requests?
I used the following article for implementing my background service.
https://learn.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice
After years of building background services, I learned that Windows services are the best tools to implement these applications. While there are different techniques to keep an IIS application up and running in the background and prevent it from getting recycled, in practice, the applications on IIS are not meant to be executed forever.
If you had an intention to build your app in the cloud, I would have suggested using something like Azure WebJobs or Azure Functions Timer-Triggered functions, but for on-premise, even using something like Hangfire in the web is not sustainable. The worst happens when you need backward compatibility on Windows servers that don't have the "Application Initialization" module.
My suggestion is to move your application to a simple Windows Service if you control your environment. Windows services consume less memory, are easier to manage, and can run forever without getting recycled.
WebApplications are plain the wrong tools for this.
Being always on and always reachable, WebServers are primary targets for hacking. To compensate for that, they are usually run under the most restrictive user rights you can imagine: Read rights to their programm and this instances content directory. While I do not know why it worked at all, it propably will stop working in Production.
What you wanted to write was eitehr a Service or something executed by the Windows Task Sheduler. Personally I advise for the Task Sheduler as Services have their own set of restrictions. Unless of coruse there is some detail of the requirements that you did not told us.
This article could be helpful. It's a step by step tutorial on how to convert a console application to a web application.
I have a client where I'm trying to port their code to my machine for development purposes. They built their wcf services using classes and interfaces only - thus no svc files. Almost like you would find with self hosting.
When I run the application, these services are hosted by WcfSvcClient (for debugging purposes) and I can see them starting up. I can however not access these services by pointing my browser to the given urls, nor can I step into that code.
I know this should work, because it works on a client machine - but I cannot tell why it isn't working on my machine other than suspecting it needs a computer which runs on their domain?
The strange thing I've noticed is they declared a host url in the wcf services config file for each service. This url is used when starting WcfSvcClient - but it is not configured anywhere else I can see i.e. not IIS. It just mysteriously exists and I have no idea how to call it, debug it or even under which account it runs. Is this configurable somewhere?
Could someone perhaps point me in the right direction? My knowledge with wcf is very limited. Thanks
Ok so it seems wsHttpBinding does support authentication where the domain the service is running on is relevant. This is it's default behavior. You have to explicitly tell it to not do so, by including:
securityMode=None
in your binding configuration. Not suggested for production.
For more information see this post: WCF slow ServiceHost.Open() call
Context: My company has been developing a WebAPI application to be hosted by IIS and the request latencies for a single static content file are about ~60ms. We investigated benchmarking the same app using WebAPI Self host and the latencies for the same content file were ~15ms, which really blew us away.
From a deployment process, we love IIS as it provides us extreme flexibility in doing hot deployments by copying DLLs directly to our web servers, which doesn't require us to do any sort of drain-stopping.
Question: Is it feasible to do similar hot deployments (just copying over dll's) with self hosted applications?
Nope, while self-host is executing, the DLLs will be locked so you'll have to stop the self-host first. You can do other tricks like deploying to another folder and then re-routing requests etc. but it's not the same as IIS deployment.
Self host allows you to do some neat things like have a secondary service running on the same address that will respond while the primary service is down. e.g. It could return a 503 with a retry-after header. Stopping and starting a service to enable copying files should only cost a few seconds.
On the other hand, you are doing something wrong if IIS is taking longer than self-host to deliver static content. IIS can use kernel mode functions of http.sys to deliver static content. One of the Owin based hosts has enabled this for self-host but the default self host does not allow it. In my experience IIS should definitely be faster than 60ms for small files.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
My application is currently made up of 2 different solutions.
1) The Shell which contains all the WPF and front end logic
2) The BackEnd which contains all the WCF service implementations and NHibernate related data access. At the moment, there are 6 different WCF service contracts defined.
I currently have this working quite well in Visual Studio but need to consider the deployment options for when the application is installed on to a users PC. As far as I am aware there are numerous different ways of hosting WCF services -- in-process, as a Windows Service, in IIS. I am intrigued to know how people go about configuring this type of setup in a Prism application.
The nearest info I have found so far is from http://wcfguidanceforwpf.codeplex.com/releases/view/27987 but I don't think it is quite what I am looking for.
I would like to know :-
a) How and if you can allow the users the choice of different hosting strategies for WCF services?
b) All the examples I have seen show the ServiceHost opening and starting one service. Is this the recommended practice and I would have to create 6 Service hosts or could I start six WCF services in one ServiceHost?
c) If the WCF services are run in process for testing locally for example - do you use the bootstrapper in the Shell and open all 6 WCF services or is there some other place that this happens?
d) What strategies you use for configuring the endpoints or is it simply a case of modifying the app.config files?
e) If there are any decent references online or book that I have not managed to find that cover Prism desktop / WCF configuration?
Apologies for the amount of questions but usually I can piece together an idea of what I need to do from extensive Googling but on this occasion I cannot find anything other than the link above that seems to match what I need to know.
Any help with this on any question would be most appreciated.
Alex
Let me begin by saying that Prism and WCF are mutually exclusive frameworks, and the use of one does not preclude the use of the other in any way.
a) Why would you let them decide how to host their WCF service? The easiest configuration is IIS hosting, which requires minimal setup. One IIS web could host all of your six services, unless you needed a memory barrier by putting each one in a separate application pool. Running the services in a Service Host is tantamount to writing an EXE (e.g. Windows Service) to serve the client. A lot more work and configuration (from the Windows Service side, WCF configuration is the same, unless it conflicts with IIS by running on HTTP:80). You have many options for the how, but you're using WCF, so I assume you have a client/server scenario. If you have a Windows server, use IIS, imho.
b) You can run as many WCF services inside the same Service Host as you want, but if one fails, the whole EXE crashes. That is why I suggest IIS application pools, which auto-restart on failure, and can be configured to run each service in a different application pool.
c) There are different strategies for where to put service integration code, depending on how your application is structured. I would suggest writing a "Service" class for each of your WCF services and register each with your container, so you can use an ImportingConstructor on your view models that need any particular one. You would initialize and register these classes in the bootloader. At this point you may be asking yourself if you really needed 6 and maybe should consider consolidating into 1 WCF service.
d) I disagree with Sebastian here. WCF configuration is simple if your service is simple. The more complicated you need it to be, the more complex the configuration. By default, you need very little configuration, and I would look at the WCF Service Configuration Editor tool included with Visual Studio to modify both your app.config and web.config, but don't get confused which one you are working on! The simplest way to configure the client is to use the "Add Web Reference" and point to the URL on the server machine. Remember that WCF allows you to configure multiple end points for the same service (an end point is a URL with a port and service name), and each endpoint can have one of many different protocols (I use basicHttpBinding, wsHttpBinding, or netTcpBinding, depending on my needs). I suggest starting with wsHttpBinding, which is one of the easiest to debug. Modifying the app.config or web.config by hand is going to get you in trouble, because one mistype and you're debugging for hours. Stick to the editor.
e) You will not find a good reference on both Prism and WCF, because one does not affect the implementation of the other. By encapsulating your WCF service code inside of a service class served up in Prism by the container, you remove any dependencies between Prism itself and the services, and don't cause yourself headaches later on by inadvertently coupling them together. Later, you can inject your view models with a Moq service class that doesn't make calls to the actual service for testing purposes. Prism has a very good CHM file that has all you need to know about Prism, WCF has great documentation on Microsoft's web site (no book required, unless you want to get fancy, like with that Windows Service).
Feel free to follow up.
Follow up #1:
As I use IIS to host my services, I haven't the experience to guide you on implementing a ServiceHost for multiple services. However, IIS allows putting multiple services into the same application pool (which is basically a single instance of W3WP.exe running on your machine), so I am pretty sure it can be done.
Edit: After reading the WCF Guidance for WPF you provided, I can see that you create one ServiceHost instance inside your EXE for each service you want to host. So you'll need 6 ServiceHost instances, and manage them separately in the EXE code.
Factoring your services is a matter of design. You chose to have one service per domain class. If I did that in my application, there'd be over 100 services. Instead, I chose a to implement a command pattern which allow me to make requests for the objects I want, regardless of type, and it returns them to me in one, clean interface.
I am confident you will not find guidance on accomplishing your design between Prism and WCF in any book. You may find some in blogs, however, here is what I suggest:
Encapsulate your WCF service creation and operations inside of a class (e.g. DataAccessService) that can be injected into your view models through dependency injection (see ImportingConstructor attribute). Use the eventaggregator service to publish events from your DataAccessService if errors (or other notifiable events) occur, and handle them in your view model. Don't create cohesion between your view models or views and the WCF services by calling between them directly, as that will violate both SRP as well as prevent the ability to test the view models without touching your web services (an external dependency).
a) For the "if": sure, why not? For the "how": Write different modules that deploy your services to IIS or Windows Services or Console Hosts and let the user choose which one to run.
b) One Service per host but multiple endpoints with different bindings are possible.
c) In process means that they start when you start your application? Then I would go for the bootstrapper.
d) There is nothing simple about configuring WCF via app.config. The tooling in Visual Studio is puny and the number of knobs and dials is legion. Using code for configuration at least gives you Intellisense support.
e) I don't think that this is a very common combination so I would not bet that there is any literature out there. But for any questions regarding WCF I would recommend reading Programming WCF Services by Juval Lowy. I think the code samples also contain a WinFormsHost for WCF service which might be another option for your "where do I host services" problem.
I need to change some configuration settings on-the-fly in a Windows Azure project - and they need to be changed via a web service call (updating the application's configuration either via the platform api or the Azure Management site isn't an option here).
The project has multiple web and worker roles - all of which will need to know about the new configuration when it is changed.
The configuration is persisted to durable storage, and it's also cached during runtime in a static variable.
My solution was to create an internal (tcp) endpoint on my roles, and use that to loop through all of the roles and instances within those roles, create a client on the fly, and tell the instance about the new setting. (pretty much identical to: http://msdn.microsoft.com/en-us/gg457891)
At first I started a ServiceHost in the WebRole's RoleEntryPoint... and I was confused why everything seemed to be working fine when I stepped through the communications (the static variables where getting set correctly) - yet when I'd make other webservice calls, the static variable seemed to have "forgotten" what I set it to.
This was the case both locally, and in the Azure staging environment.
At this point I realized that because we're using full-IIS mode, the RoleEntryPoint and the Web Services were running in two separate processes - one in Azure's stub, and one in IIS.
"Not a problem" I said, I'll simply move the line of code which starts the ServiceHost from my RoleEntryPoint into the global.asax - at which point the ServiceHost will have been started in the same process as the rest of the site - and the static variables would be the same ones.
Here's where I'm having a problem; This works great on my local machine running in the dev environment. As soon as I deploy to staging I start getting error emails saying the channel used to connect to the service can't be closed because it's in a "faulted state".
Question:
What's different about Azure vs. Dev environment that is causing this?
How can I fix or workaround the problem?
Does anyone have any general advice on how I should go about obtaining a more descriptive error... do I have to enable full wcf diagnostics in Azure to get this, or is there some other way I can get at the exception details?
Follow-Up:
Via remote desktop i've learned several interesting things:
Non-HTTP Activation isn't installed by default on Azure WebRoles. I believe this can be overcome via a startup script:
start /w pkgmgr /iu:WCF-NonHTTP-Activation;
The website created in IIS by the web role doesn't have the net.tcp protocol enabled by default. I also believe this can be overcome with a startup script:
%systemroot%\system32\inetsrv\appcmd.exe set app "Website Name Here" /enabledProtocols:https,http,net.tcp
I haven't had time to take this all the way, as deadlines have forced me to implement some workarounds temporarily.
Some useful links related to this topic:
http://msdn.microsoft.com/en-us/magazine/cc163357.aspx
http://forums.iis.net/t/1160443.aspx
http://msdn.microsoft.com/en-us/library/ms731053.aspx
http://labs.episerver.com/en/Blogs/Paul-Smith/Dates/2008/6/Hosting-non-HTTP-based-WCF-applications-in-IIS7/
UPDATE (6/27/2011):
Amazingly, someone at Microsoft (whose blog I commented on) actually got me an answer on this.
The Azure & WCF teams updated this post:
http://blogs.msdn.com/b/windowsazure/archive/2011/06/27/hosting-services-with-was-and-iis-on-windows-azure.aspx
The link contains all of the information you need to get going with this.
And a HUGE thanks goes to Yavor Georgiev, the MSFT PM with the win.
It's been quite a while since I've asked the question, and no answers, so let me leave this:
Per my follow-ups in the post, there are ways of making this work... but they are complicated and difficult to implement.
For WORKER ROLES, netTcpBinding works perfectly. No issues here. Go ahead and use it.
For WEB ROLES, you've got problems.But netTcpBinding is what you need to use for exposing internal endpoints. What to do?
Well, here's what I did:
Start netTcpBinding service in your RoleEntryPoint using ServiceHost.
Create standard WCF service in your web role using SOAP / JSON / Whatever you want.
When you receive requests through your netTcpBinding, proxy them along to the WCF service on the loopback adapter.
Properly secure your "internal" WCF service with SSL client certs.
It's not perfect... but it works, and it's not terrible.
I suspect that needing to do this kind of thing isn't super common, and I really can't think of any reason why you'd need to other than to dynamically modify settings at runtime... which means you're not slamming these services like crazy.
Obviously, YMMV.
I had a miserable time getting HTTP working between instances in staging, and gave up when it looked like I needed to mess around with netsh to give my processes permission to listen via an HttpListener (sheesh!). So I switched to TCP via sockets. HTTP just adds overhead in a point-to-point communication scenario like this.