Does an asp.net webservice have something like application start and application variables? - asp.net

I'm developing a webservice that will, when called, notify another program via a tcp connection. My problem is where to store the open tcp connection. The way I understand web services, they start and end with each HTTP Request, with no room for application wide variables, like the open tcp connection.
Please correct me if I'm wrong.
Specifically, in what part of the asmx file, or outside of it, should I place the code for listening for incoming tcp traffic?

Application events in Global.asax should fire for a web service hosted as an application in IIS. You can use these. Keep in mind that they will fire even if a web page and not the web service is accessed in the same application.

You can place the tcp connection as a static member of the service class and make a static constructor that handles the instantiation.
This will create the tcp connection before the first access of the web service is handled and then persist the connection as long as the hosting process is running. The only drawback with that approach is that the tcp connection is process wide. If you host two instances of the web service within the same process (quite unlikely) they will share the same tcp connection.

Fortunately for you, you are wrong.
Application-wide events do fire plus you have the access to all asp.net containers, the Application container for application-level variables, the Session container for session-level variables (if the client side supports cookies, the session id could even be passed in a cookie) and the Items container for request-level variables.
However, whether or not this helps you to store an additional tcp listener (if I understand correcly) is another story, not obvious one.

Related

How to get SignalR Connection to Respect Session Timeout

Using SignalR, it's designed to maintain a long-running connection to the web server. However, I have a scenario where the SignalR connection maintains an open connection to the web server, long after the ASP.Net session has expired. This happens even though neither the client nor the server is sending an data.
How can I set things up so that once the Asp.net session expires, the SignalR connection terminates, freeing up connections on the server?
This is desired because the web servers run on a load balancer, and when taking a server out of the rotation, we need the # of current connections to generally represent the number of active sessions - not SignalR connections that are still kicking just because user left browser open.
SignalR Server does not allow to disconnect a particular client connection (this would be super useful). So the client is responsible to do that.
A workaround would be to add an event listener on the client and disconnect from there, i.e:
hubProxy.On<string>("YouAreUselesLetMeAlone", _ => connection.Dispose());
Obviously, to make this work you need a relation (ConcurrentDictionary?) of asp.net sessions <-> signalr connections, so you can call this method in the correct client when the asp.net session ends.

WCF client per ASP.NET request?

I have WCF service, called by ASP.NET web application. When there is more than one call per page request, is it better to keep client open and share the instance across the whole request, or is it better to create and dispose client per each service call as shown below?
using (var client = new WcfClient())
{
var result = client.Method();
}
If you're using webHttpbinding, wshttpbinding or basicHttpbinding, the default behavior is for each client request (call) to get its own unique connection and instance of the web service object(s). This means that when Client A and B send requests to your web service, each will get it's own instance of the service, instantiated by the hosting program, then disposed of neatly (hopefully) when the response is sent back to the client. The WCF .NET infrastructure and the hosting program take care of all of the creation and destruction of the connections and objects for you, unless you hijack the process and do something fancy.
It's possible to create persistant client sessions that leave a connection open and the service in memory, but I've never tried it. Here's a link to an explanation of how to do it:
WCF sessions with a wsHttpBinding and without windows security
For the last two years, I've worked entirely on WCF client and host software on an industrial scale and there's not much reason to worry about the efficiency of continuously openning and closing connections on a WCF web service. I've benchmarked our tests services with hundreds of concurrent client connections, each uploading and downloading files, and it barely stresses the WCF server's CPU. During our tests, the majority of the stress (as usual) fell on the database side.

How does Signal-R fit in the IIS activation model?

I am learning Signal-R, and this is something that has been in my head during all time.
How does Signal-R fits in the IIS/ASP.NET life cycle?
How long does the Hubs live (I see they have re-connection semantics)?
Does IIS does prevent the shutdown of an AppDomain that has a persistent connection?
It is my understanding that IIS is designed to handle request-response scenarios. A request hits IIS, this finds the AppDomain, activate it, and then pass the request to it. And after an idle time, shutdown the AppDomain. If the request takes too long, a timeout exception is thrown.
Now let´s imagine that I have another application that broadcast information through a TCP socket. I want my javascript clients to get that information in real time, so I create a Signal-R web application. I can create a TCP client on application start, but what does guarantee that IIS is not going to shutdown the whole thing after some time with inactivity?
I could self host the Signal-R app in a window service, but then I would have to use a different port, enable cross domain, etc... Many problems for deployment. But, I am concerned about using an ASP.NET MVC application for this, since it looks to me like fitting a driving wheel in a motorbike.
Cheers.
SignalR in IIS/ASP.NET Lifecycle
SignalR uses Owin: http://owin.org/
A good article on Owin here: http://msdn.microsoft.com/en-us/magazine/dn451439.aspx
Hub object lifetime
From the SignalR docs: http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#transience:
You don't instantiate the Hub class or call its methods from your own code on the server; all that is done for you by the SignalR Hubs pipeline. SignalR creates a new instance of your Hub class each time it needs to handle a Hub operation such as when a client connects, disconnects, or makes a method call to the server.
Because instances of the Hub class are transient, you can't use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub. If you persist data in memory, using a method such as a static variable on the Hub class, the data will be lost when the app domain recycles.
Your long running TCP client
This is not a problem with SignalR. Your TCP client can be shutdown by IIS: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/
I would rather make the TCP client run in a windows service. The TCP client receives TCP broadcast messages and forwards the messages to the Hub using the SignalR .NET client.
Hubs are recreated on each SignalR request, so if you need a persistent connection you may have to look into using static vars or dictionary to hold state. But as you point ASP.NET can restart for a variety of reasons.
It depends on what persistancy you really need. If you have a connection that MUST stay alive at all times and cannot be torn down and reestablished then hosting in IIS is not the right choice. However, if you can re-establish the same connection after a shutdown, then maybe this can still work.
You can do quite a bit in making sure that ASP.NET apps don't shut down in recent versions of IIS:
http://weblog.west-wind.com/posts/2013/Oct/02/Use-IIS-Application-Initialization-for-keeping-ASPNET-Apps-alive
If that's not enough for you running as a separate service is an option. If you run as a service on the same IP address there are no cross domain concerns. Here's more info on running SignalR using a Windows Service:
http://weblog.west-wind.com/posts/2013/Sep/04/SelfHosting-SignalR-in-a-Windows-Service

Where to host SignalR when long-running service via WCF is backend

I'm sure that was a confusing enough title.
I have a long running Windows service dealing with things happening in the world. This service is my canonical source of truth for the rest of my system. Now I want to slap a web interface onto this so the clients can see what is actually going on. At first this would simply be a MVC5 application with some Web API stuff. Then I plan to use SignalR 2.0 and Ember.js to make this application more interactive and "realtime".
The client communicates with the Windows Service over named pipes using WCF. A client (such as a web app) could request an instance of for example IEventService, would be given a WCF proxy client, and could read about events through this interface. Simple enough.
However, a web application basically just exists in the sense that it responds to requests from the user. The way I understand it, this is not the optimal environment for a long lived WCF client proxy to raise events in, and thus I wonder how to host my SignalR stuff. Keep in mind that a user would log in to the MVC5 site, but through the magic of SignalR, they will keep interacting with the service without necessarily making further requests to the website.
The way I see it, there are two options:
1) Host SignalR stuff as part of the web app. Find a way to keep it "long-running" while it has active clients, so that it can react to events on the WCF client proxy by passing information out to the connected web users.
2) Host SignalR stuff as part of my Windows service. This is already long-running, but I know nada about OWIN and what this would mean for my project. Also the SignalR client will have to connect to a different port than where the web app was served from, I assume.
Any advice on which is the right direction to go in? Keep in mind that in extreme cases, a web user would log in when they get to work in the morning, and only have signalr traffic going back and forth (i.e. no web requests) for a full work day, before logging out. I need them to keep up with realtime events all that time.
Any takers? :)
The benefit of self-hosting as part of your Windows service is that you can integrate the calls to clients directly with your existing code and events. If you host the SignalR server separately, you'd have another layer of communication between your service and the SignalR server.
If you've already decided on using WCF named pipes for that, then it probably won't make a difference whether you self-host or host in IIS (as long as it's on the same machine). The SignalR server itself is always "long-running" in the sense that as long as a client is connected, it will receive updates. It doesn't require manual requests from the user.
In any case, you'll probably need a web server to serve the HTML, scripts and images.
Having clients connected for a day shouldn't be a problem either way, as far as I can see.

Is it possible to start WCF UDP Listener in IIS on a shared host without requiring a user to access HTTP first?

I have created a sweet ASP.NET 4.0 UDP listener via WCF that starts on Application_Start. As usual, everything is hunky dory on my local machine. On my local machine using the VS Dev Environment and setting it to not open any page upon debug, the listener starts without browsing to anything yet. However, whenever I deploy to my shared host, I must access the site via a web browser before the listener will start. I do not have access to the IIS control panel but I do have some limited setting changes I can make to IIS via "Website Panel" software. I believe the shared host uses IIS 7.5.
Is there a better way to solve this rather than creating a polling service from my home PC to send an HTTP request to the shared host every so often to kick off the listener?
Requirements
The client sends UDP packets over a configurable port. I cannot change anything other than the IP and port that the client uses to connect
The solution must work with my shared host since I cannot afford a VPS at this time - otherwise I would've created a Windows Service. I got around creating a window service before by creating a polling service via WCF Application_Start but that only works because the info the users would see have to be on a webpage therefore application_start would always be called. In this case, the users/clients are not necessarily accessing the webpage.
Ideas:
Somehow pull this into a .svc. That way when the .svc is accessed by the client, it kicks off the listener for everyone else. But how can a .svc running on port 80 accept UDP calls? I'm also not sure if the client will be able to connect to more than an IP:PORT (I don't think it'd accept a .svc path like URL.com/awesomeListener.svc).
Any suggestions? Thank you so much.
If you are running ASP.NET 4.0 you can set it to auto-start for you which will fire Application_Start:
http://weblogs.asp.net/scottgu/archive/2009/09/15/auto-start-asp-net-applications-vs-2010-and-net-4-0-series.aspx

Resources