I know many questions have been posted on this particular topic but I couldn't find any that fit my situation.
My test app is built with ASP.Net Web Forms. The library I use is a .Net library not compatible with .Net Core so I'm limited to .net Framework.
I'm retrieving data from a PLC Server(Modbus protocol using TCP/IP) using a third party library that supplies connection and data handling classes, handlers... I didn't need to implement "Models" or "Controllers" since everything is handled within classes. Here is an example :
//References
using AutomatedSolutions.Win.Comm;
using MB = AutomatedSolutions.Win.Comm.MB.Master;
using System;
using System.Text;
using System.Web.UI.WebControls;
protected void Page_Load(object sender, EventArgs e)
{
//Properties Instantiation
mbChannel = new MB.Net.Channel(); //Connection to the server TCP/IP
device1 = new MB.Device(); //Device sending data (temp, speed, ...)
group1 = new MB.Group(false, 500); //Abstract class with a "dataChanged event"
item1 = new MB.Item(); //Represents a specific data point (tag)
group1.Items.Add(item1);
mbChannel.Devices.Add(device1);
device1.Groups.Add(group1);
//Data changed Event Handler
item1.DataChanged = new Item.DataChangedEventHandler(Item_DataChanged);
//Polling activation
group1.Active = true;
}
Once connected to the server, the "Item.DataChangedEventHandler" is triggered every 500 ms and new data can be retrieved from the "item".
"Item.DataChangedEventHandler" code :
private void Item_DataChanged(object sender, EventArgs evArgs)
{
Item evItem = (Item)sender;
TextBox1.Text = TextBox1.Text DateTime.Now.ToString("hh:mm:ss:fff") " Item.DataChange event fired, quality is " evItem.Quality.ToString();
if (evItem.Quality == AutomatedSolutions.Win.Comm.Quality.GOOD)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < evItem.Elements; i )
{
sb.Append(evItem.Values[i].ToString() ",");
}
WriteResult(sb.ToString());
}
}
WriteResults code :
private void WriteResult(string result)
{
Result.Text = result;
}
DoRead code : This function is triggered by a button action and reads one item at a time. This works fine and read values are shown in the "TextBox"
private void DoRead(TextBox tb)
{
Result result;
try
{
device1.Read(item1, out result);
if (result.IsOK)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < item1.Elements; i )
{
sb.Append(item1.Values[i].ToString() ",");
sb.Length = sb.Length - 1;
tb.Text = sb.ToString();
TextBox1.Text = "Success";
}
}
else
{
TextBox1.Text = TextBox1.Text result.EvArgs.Message;
}
}
catch (Exception ex)
{
TextBox1.Text = TextBox1.Text ex.Message;
}
}
My issue is that while reading the item's values with "DoRead" method works fine, data collected from the "dataChanged" event are not shown. TextChanged Event is not triggered.
How can I update the page with the incoming data?
CodePudding user response:
Well, as noted, you need to grasp the life cycle of a web form or page.
That code behind ONLY exists DURING what we call a round trip.
So, the user requests a web page. the page class and variables etc. are created. The code behind runs, and the page is sent to the client side.
THEN the server side page is tossed out - does NOT exist anymore (now read this over and over!! - the server side code, varibles and page is TOSSED OUT - it does NOT exist!!!).
you MUST without ANY doubt grasp the above concpet.
So, the web page is now sent to the client side, browser replots that page. it is just sitting on the users desktop and the server page code/page/variable etc. is NOW GONE!!!!
The end user can pull the plug on their computer, maybe hit a short cut and go to google.com. The page is disconnected from the web server!
It never WAS connected. The web page just sits on the users desktop. the code behind is LONG GONE - does NOT exist anymore!!!
The web server is thus just sitting there. It is waiting for a post-back from ANY user. It does not hold or keep a copy of YOUR web page and code in memory. The web server can take ANY web page request.
So, you can NOT have and KEEP some code in a web page running during this process.
If any of the 10 users with a web page sitting on their desktop clicks a button? Then if a post-back occurs, then that WHOLE web page is sent to the ONE web server waiting for that request.
The page is then re-loaded. The page class and variables are re-initialized (starts from scratch). The code behind now runs. You can change things on the web page, and ONLY WHEN ALL code is done running is THEN the page sent back to the browser, and the browser then re-loads that WHOLE page again.
I mean, what happens if 10 users post that page? You now have 10 copies of that code and page running!!!! Which one is going to be connected to that exterinal process??
You have this setup:
Note how the page is sitting CLIENT side. On the server, THERE IS NOT a instance of that page class. (read this sentence again!!!)
NOTE VERY careful here - the web page is ON CLIENT computer - it is NOT existing at all on the web server side.
You do not have this:
And you DO NOT HAVE this either:
In above it shows the web page on the user desktop, and then the web page on the server.
you do NOT have that setup.
The page SERVER SIDE DOES NOT exist.
So, you have a web page,and you click a button:
Ok, You click the button. Now the so called round trip starts.
So you click a button the WHOLE WEB page is THEN sent up to the server. You now have this:
Now in above, the diagram I suppose COULD show that the web page is ALSO still client side. But I left it out.
NOW a instance of the page class is created, and your code behind starts running.
Your code behind can modify controls (even visible), but the page is NOT interacting with the user - ONLY code can MODIFY the web page.
web page is THEN sent back to the client side, and the server side class instance and code is TOSSED OUT - DOES NOT exist!!!
So the code behind NEVER really directly interacts with the user.
you code can ONLY modify the web page DURING that short trip up to the server. Code behind runs - modify web page, and THEN the WHOLE page is sent back to client side.
So you never interact directly with the user, but ONLY interact with the web page, ad ONLY for a VERY short time.
What this suggests?
It quite much means you probably should run a 100% seperate process outside of the web site that interacts with that one other source. It could update a table, and then say your web site could have a timer re-fresh that re-loads say ever 1 or 2 seconds.
And I doubt that machine would be happy if 10 users launched a web page, and now all 10 of them start hitting that external system. However, what is worse?
Well, the code might connect to that box, setup some code to receive some info every so often, but as noted, as soon as the code behind is done, then the whole web page is now sent back down to client side and the server side code page is TOSSED out, and does NOT exist anymore.
Only when you post back again then the code ad page starts over from scratch (no previous code values or variables exist from last post-back).
Now, having stated the above?
You could have form with a timer that fires say ever 1 or 2 seconds. And if you really need a "real time" connection from the web page to the server, then you would look into using what is called asp.net signalR. Its a bit of work to setup, so the timer idea probably is easer to start out with.
But, asp.net signalR probably the best choice.