In process web server in UWP app to receive JSON messages - c#

I have a question, I have been following this post:
IoT core background webserver
to build my background webserver. However, this post along with most that I read are just a headless background service. In my case, I do have a main app with a UI as well that the user can view and interact with. So, I am not headless, I want the app to start and show the UI when the device starts up. But, I also want a web server running in the background at all times (from within the app) to listen for JSON messages to be posted. For example, if I have text on the UI that I want to change by sending a JSON message to the device/app.
I understand that this is typically referred to as an in-process web server. So, I took most of the link above to implement the web server class and then from my MainPage.xaml.cs code behind, I did this to instantiate the web server class on another thread to listen for messages:
private async void StartServer()
{
var webServer = new WebServer();
await ThreadPool.RunAsync((workItem) =>
{
webServer.Start();
});
}
Is this the right way to start the web server in a background thread? As I read the code (and be easy on me, as I am still learning all of this stuff), it seems that the web service will start in the thread pool but then stop after it receives one message. Is that right or will it continue to run indefinitely (or as long as the app is running)?
Thanks!

Yes,it is a right way to start your web server in a background thread in headed UWP Application.In the thread pool,the web service will not stop after it receives messages,because the object of WebServer is not disposed.
Firstly, please refer to the Object Lifetime in .Net Framework.This topic is also about the life cycle of an object. The webServer object will not be disposed until the application exits.
Secondly, HTTP 1.1 implementa persistent connections.In the code you referred,each connection will be closed after web server responses to the client(web browser). So a separate TCP connection will be established to fetch each request in this web server.
var header = $"HTTP/1.1 200 OK\r\nContent-Length: {bodyStream.Length}\r\nConnection: close\r\n\r\n";

Related

Implementing a custom callback in a web service

I am using web services - not WCF - hosted in an iis web application written in C#/asp.net. I also have a C# winform Desktop application that had originally polled a web method to check for any messages on the server. I found the memory on the client shot up. So, instead of polling this web method I invoke it once, the web method goes into a loop checking for messages. As soon as it finds a message(s) for this client it breaks out of the loop and returns the message(s) to the client. The client in turn will process the message(s) and then re-invoke the same web method waiting for the next message(s).
I run this and the memory on the client desktop and the memory on the web server remain low. I really have 2 questions here.
1). Will the memory escalate on the server when more clients invoke the same web method?
2). Should I avoid this way of doing things?
I know there are callbacks available using WCF and I know I can create a hub using Signal R. what I would like to know is there anything wrong/different to how I am doing it and/or is there a better way of doing it?
Many Thanks.

communication between the website and C# winforms application

We have a Website (hosted somewhere) and C# Application (which is installed on my PC). I need to accomplish the following:
Customers fill up the form on the website, i.e. the task is "created"
C# Application immediately receives this data from the website and process it
The result is sent back to the server, i.e. "task accomplished" message
The website updates status regarding this task
How do you build this kind of link between the website and an app?
In the past I've used TCPListener to communicate between two C# apps. I'm also familiar with the UDPlistener and such.. Will this knowledge be of some use? The website is going to be build on the PHP.
Some tips and advises are appreciated. Thanks.
Your website should not be dependant on an application running on your home or office PC, so the site should publish some kind of service or feed. You can make this a webservice, which is quite easy in PHP.
You then consume this service from your C# application. Make it request the new tasks regularly, by polling the service. When you've received new tasks you process them in your application, and when you've done what you want to do you update the tasks on your server using another webservice call.
All this can be done using some sort of queue in the database that backs your website.
Make the C# application a web service may be a windows host depending on your requirement
you can the webservice from php as shown here Using PHP to call a WCF web service with multiple bindings
If you have the control over your web host and your client, you could try setting up a WCF service with duplex contracts which allows the server to callback your client. Your PHP site can call the WCF service and it can in turn notify the client. Else you will have to go with the polling method where the Desktop client has to poll the web service to get the list of pending tasks.

IIS Background thread and SignalR

I need to have a background thread that does some work and sends data to the users connected to the service through SignalR.
I thought of hosting this thread inside IIS, and to spawn it when Application_Start is first hit, or in a separate worker process.
If I host it in IIS and create it at the start of the application
- The thread starts only when the app is first hit. I need it running as soon as I start the service.
- I do not have control over this thread via a desktop GUI, I can't stop or pause it in a simple way.
If I host it in a separate process, such as a Windows Service
- I don't have access to the SignalR service instance
- I don't want to connect to the SignalR service as a user to send data to other users. I wanr a different approach to this, one that doesn't imply the worker being a client to SignalR itself.
What is your opinnion on this ? Do you see any other solution ?
The way we have approached this is to create a separate endpoint on the web application that your Windows service can call.
Imagine the following URI exists in an ASP.NET MVC controller: http://[myserver]/api/TellUsers/[msg]. Inside of this method, you can get the connected hub clients and make the call.
[HttpPut]
public void TellUsers(string msg)
{
var connectionManager = AspNetHost.DependencyResolver.Resolve<IConnectionManager>();
var demoClients = connectionManager.GetClients<MyHubDerivedClass>();
demoClients.TellUsers(msg);
}
[Insert caveat about proper error checking here.]
Of course, you don't have to use MVC. Any publicly accessible URI would work. As for securing it, you can use any valid technique for securing ASP.NET endpoints.
I know the question is rather old but:
In truth i rather like the "client itself" example you have. This gives you control from many different points rather than just one. Example - multiple services can call over to control the service. I can't see any reason you can't have an admin user which is able to invoke "special" commands that others users can't.
That's a tried and tested design for many systems. I'd stick with it.

How does the WCF service interact with my winform app?

I am currently developing a C# Windows Form Application that I intend to let it interact with a server. The server will receive posting from a mobile application that I have developed and whenever a posting is received, my Windows Form Application should be notified and give me a notification. In order to do this, I intend to use WCF duplex service for it.
E.g. My mobile application sends an posting over to my server. Once my server reads and receives the new posting, the service should send a message over to my winform app to alert me that a posting is received. And the UI of the winform app should update accordingly to what I want to updated. (e.g. adding new panels)
This is basically how I wish for it to work
They way this would work is
WCF Service in running on my server
Windows Form connects to my server's WCF service using Duplex Contract
Mobile app posts to a webpage
Once the webpage receives the posting, the asp.net will invoke the WCF service
WCF duplex service receives the posting and sends the information to the winform app
My winform Application aka WCF Client updates UI with this new message received
My question is, how does step 4 proceed to step 5? To be specific, how does the service sends the information over to the winform app upon receiving the posting.
To be even more specific, once the posting is received from the webpage, the service contract is invoked and the information is sent and received by the service, how does the service make use of the call back channel to send the information over to the winform app and update the UI accordingly?
The answer to this question depends on how your WCF service is hosted and how "big" the service will eventually be (in terms of number of simultaneous clients).
The simplest scenario is a self-hosted WCF service (meaning hosted in a Windows Service or as a desktop application--not in IIS). In this case, you can use InstancePerSession mode and make your service use sessions. In this case, you'll have a 1:1 correspondence between clients and instances of your service class. When a client connects, retrieve the callback reference and store it in a static list outside of the service class. When you need to send a message to one or more clients, simply iterate over (or find the desired client in) your list and call the appropriate function on the callback contract
If you need to host your service in IIS, then the situation is trickier because you have the possibility of multiple processes hosting your service, so your list can potentially get fragmented (or blown away in the event of an app pool recycle). In this case, you'll have to use something external to your service (MSMQ, perhaps) to notify other application pool processes that a message needs to be sent.
In terms of a duplex connection, you are really just able to communicate two way over that one connection, not with all connections of the service without doing some tricky thread stuff and shutting the door on any scalability (or using something outside the service to handle to pub/sub).
One solution though that may work a lot more along the lines of what you want to do would be SignalR. It allows a single client to make a request and then you can broadcast data from that request to other clients (or target it). Take a look at its info, its sole purpose is real time communication in .NET with multiple clients.
Also another note, is that you will want to use some sort of BackgroundWorker or something for your listening thread in WinForms so that the UI is not locked while the background operations are running.

How to use SignalR to notify web clients from ASP.NET MVC 3 that MSMQ tasks were completed

How would one use SignalR to implement notifications in an .NET 4.0 system that consists of an ASP.NET MVC 3 application (which uses forms authentication), SQL Server 2008 database and an MSMQ WCF service (hosted in WAS) to process data? The runtime environment consists of IIS 7.5 running on Windows Server 2008 R2 Standard Edition.
I have only played with the samples and do not have extensive knowledge of SignalR.
Here is some background
The web application accepts data from the user and adds it to a table. It then calls an one way operation (with the database key) of the WCF service to process the data (a task). The web application returns to a page telling the user the data was submitted and they will be notified when processing is done. The user can look at an "index" page an see which tasks are completed, failed or are in progress. They can continue to submit more tasks (which is independent of previous data). They can close their browser and come back later.
The MSMQ based WCF service reads the record from the database and processes the data. This may take anything from milliseconds to several minutes. When its done processing the data, the record is updated with the corresponding status (error or fail) and results.
Most of the time, the WCF service is not performing any processing, however when it does, users generally want to know when its done as soon as possible. The user will still use other parts of the web application even if they don't have data to be processed by the WCF Service.
This is what I have done
In the primary navigation bar, I have an indicator (similar to Facebook or Google+) for the user to notify them when the status of tasks has changed. When they click on it, they get a summary of what was done and can then view the results if they wish to.
Using jQuery, I poll the server for changes. The controller action checks to see if there is any processes that were modified (completed or failed) and return them otherwise waits a couple of seconds and check again without returning to the client. In order to avoid a time out on the client, it will return after 30 seconds if there was no changes. The jQuery script waits a while and tries again.
The problems
Performance degrades with every user that views a page. There is no need for them to do anything in particular. We've noticed that memory usage of Firefox 7+ and Safari increases over time.
Using SignalR
I'm hoping that switching to SignalR can reduce polling and thus reduce resource requirements especially if nothing has changed task wise in the database. I have trouble getting the WCF service to notify clients that its done with processing a task given the fact that it uses forms based authentication.
By asking this question, I hope someone will give me better insight how they will redesign my notification scheme using SignalR, if at all.
If I understand correctly, you need a way of associating a task to a given user/client so that you can tell the client when their task has completed.
SignalR API documentation tells me you can call JS methods for specific clients based on the client id (https://github.com/SignalR/SignalR/wiki/SignalR-Client). In theory you could do something like:
Store the client id used by SignalR as part of the task metadata:
Queue the task as normal.
When the task is processed and de-queued:
Update your database with the status.
Using the client id stored as part of that task, use SignalR to send that client a notification:
You should be able to retrieve the connection that your client is using and send them a message:
string clientId = processedMessage.ClientId //Stored when you originally queued it.
IConnection connection = Connection.GetConnection<ProcessNotificationsConnection>();
connection.Send(clientId, "Your data was processed");
This assumes you mapped this connection and the client used that connection to start the data processing request in the first place. Your "primary navigation bar" has the JS that started the connection to the ProcessNotificationsConnection endpoint you mapped earlier.
EDIT: From https://github.com/SignalR/SignalR/wiki/Hubs
public class MyHub : Hub
{
public void Send(string data)
{
// Invoke a method on the calling client
Caller.addMessage(data);
// Similar to above, the more verbose way
Clients[Context.ClientId].addMessage(data);
// Invoke addMessage on all clients in group foo
Clients["foo"].addMessage(data);
}
}

Categories

Resources