Im having trouble converting wpf to asp.net using mqtt. My code did not show any error but when i launch and input some text and a button click,it will show me an error
"An exception of type 'System.NullReferenceException' occurred in WebApplication4.dll but was not handled in user code"
public partial class Testing : System.Web.UI.Page
{
MqttClient client;
string clientId;
protected void Page_Load(object sender, EventArgs e)
{
}
public void MainWindow()
{
string BrokerAddress = "test.mosquitto.org";
client = new MqttClient(BrokerAddress);
// register a callback-function (we have to implement, see below) which is called by the library when a message was received
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
// use a unique id as client id, each time we start the application
clientId = Guid.NewGuid().ToString();
client.Connect(clientId);
}
void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
string ReceivedMessage = Encoding.UTF8.GetString(e.Message);
txtReceived.Text = ReceivedMessage;
}
protected void btnPublish_Click(object sender, EventArgs e)
{
if (txtTopicPublish.Text != "")
{
// whole topic
string Topic = "" + txtTopicPublish.Text + "";
// publish a message with QoS 2
client.Publish(Topic, Encoding.UTF8.GetBytes(txtPublish.Text), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, true);
}
else
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "Scripts", "<script>alert('You have to enter a topic to publish!')</script>");
}
}
It seems to be a lack of understanding of the ASP.NET page lifecycle.
In WPF, the lifecycle spans from when you run the program til when it is closed; it is statefull. ASP.NET is not; whatever you do in a Page_Load (and the other lifecycle events) will be disposed with the completion of rendering the page.
You have a few ways of solving your problem.
You can keep the MqttClient instance in the Application object. This keeps the instance alive from when the AppPool starts (instantiate the client in the Application_Start event in Global.asax. It is fired when the AppPool starts) and until it shuts down (Application_End, where you get the opportunity to shut your MqttClient down gracefully if you want/need to). It is shared between all users and can be accessed anywhere with Application[key] where key is any string, "MqttClient" for example.
You can keep it in the Session object the same way you would in the Application object. You can use Sesson_Start and Session_End in the same way. The Session object is unique to each user, in terms of it staying alive until the user stops browsing your website.
You can instantiate MqttClient every time you need it or with every Page_Load.
Related
In the documentation of the Siemens TIA-Portal Openness API you can read the following:
There is an event, when a confirmation box opens, and an event when the confirmation is given by the user.
//Register event handler for Notification-Event
....
tiaPortal.Notification += TiaPortal_Notification;
....
private static void TiaPortal_Notification(object sender, NotificationEventArgs e)
{
....
}
//Register event handler for Confirmation-Event
....
tiaPortal.Confirmation += TiaPortal_Confirmation;
....
private static void TiaPortal_Confirmation(object sender, ConfirmationEventArgs e)
{
....
}
The documentation gives this much information on reacting to the events
I want to react on the notification event. But the NotificationEventArgs Class does not contain an result attribute which i can write on, and does not contain any method of some kind to send a confirmation. There is only one writeable attribute, called IsHandled. But nothing happens if i write to that, so i suggest this is only an internal confirmation
My understanding of the api documentation ist, that it is something native of c#/.net? maybe a function of some kind, to raise reactions on events?
This answer is valid for TIA 16 with Openness API V16.
Confirmations: If a prompt is triggered in TIA Portal that requires a user decision (i.e. has more than one button), ConfirmationEvent is raised, and it definitely happens prior to any decision being made by the user.
Set IsHandled, then set the Result value. That's all you need to do.
private static void Tiap_Confirmation(object sender, ConfirmationEventArgs e)
{
//signal to TIA Portal that the event is handled
e.IsHandled = true;
//handle the various events
if (CONDITIONS_FOR_CHOOSING_YES)
e.Result = ConfirmationResult.Yes;
if (CONDITIONS_FOR_CHOOSING_CANCEL)
e.Result = ConfirmationResult.Cancel;
...
}
Notifications: NotificationEvent is only raised for prompts that have one button. The example below is for a .NET Framework console application.
using Siemens.Engineering;
using System;
using System.Linq;
using System.Threading;
namespace OpennessConsoleTests
{
class Program
{
static void Main(string[] args)
{
//attach to the first tia portal process found
TiaPortal tiap = TiaPortal.GetProcesses().First().Attach();
//subscribe to confirmation event
tiap.Notification += Tiap_Notification;
//pause
Console.WriteLine("Waiting for events. Press Ctrl+C to quit");
//sleep indefinitely. User must ctrl+C out of this
Thread.Sleep(Timeout.Infinite);
}
private static void Tiap_Notification(object sender, NotificationEventArgs e)
{
e.IsHandled = true;
Console.WriteLine("*****Notification*****");
Console.WriteLine("Caption: " + e.Caption);
Console.WriteLine("Text: " + e.Text);
Console.WriteLine("DetailText: " + e.DetailText);
}
}
}
An important note: According to my testing, some prompts do not raise an event even if subscribed, for example "Subfolder already exists" when extracting an archive. This puts TIA Portal into a locked state until you stop your application.
I think it's just a (not optimal) translation into German. What they mean is you need to set a field in the event args you got. This is a normal pattern in .NET.
Something like this (don't have the library for syntax check but you should get what I mean):
private static void TiaPortal_Confirmation(object sender, ConfirmationEventArgs e)
{
// do your thing, open a confirmation dialog or something, then:
e.Result = Choices.OK;
}
I am trying to send an email every day in specific time,
but seems like the function(void SomeMethodRunsAtSpecificTime(object o)) in System.Threading.TimerCallback is not working.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
double TimeOfExecution = 14;
DateTime now = DateTime.Now;
DateTime today7am = now.Date.AddHours(TimeOfExecution);
DateTime next7am = now <= today7am ? today7am : today7am.AddDays(1);
System.Threading.TimerCallback callback = new
System.Threading.TimerCallback(SomeMethodRunsAtSpecificTime);
var timer1 = new System.Threading.Timer(callback, null, next7am - DateTime.Now, TimeSpan.FromHours(24));
}
void SomeMethodRunsAtSpecificTime(object o)
{
//Sending email from someone to someone(this function has no problem)
}
As soon as Page_Load is done executing the Timer goes out of scope. It's the same as if you declared an int in that method. Once the method is done executing, where does the int go? Nowhere. It's gone.
Even if you made the Timer a property of the page (the _Default class) the same is true. The whole class is created just to generate a response (HTML page) and then it also goes out of scope, taking its member variables with it.
A web application isn't really a good tool for doing something at regular intervals. Its purpose is to respond to requests when they come in. When there are no requests the application isn't doing anything except waiting for requests. If no one sends a request to the site for a while the whole application can even shut down, and IIS just starts it up later when a request comes in.
To do something at regular intervals you may want a Windows Service or even a scheduled task.
I get the link in "https://www.youtube.com/watch?v=SIs7ZsMCUWA&t=327s"
I want to change from aspx to winform
the problem:
in aspx
protected void Page_Load(object sender, EventArgs e)
{
if (Session["TokenQueue"] == null)
{
Queue<int> queueTokens = new Queue<int>();
Session["TokenQueue"] = queueTokens;
}
}
protected void btnPrinToken_Click(object sender, EventArgs e)
{
Queue<int> tokenQueue = (Queue<int>)Session["TokenQueue"];
lblStatus.Text = " Terdapat " + tokenQueue.Count.ToString() + " Antrian ";
if (Session["LastTokenNumberIssued"] == null)
{
Session["LastTokenNumberIssued"] = 0;
}
int nextTokenNumberTobeIssued = (int)Session["LastTokenNumberIssued"] + 1;
Session["LastTokenNumberIssued"] = nextTokenNumberTobeIssued;
tokenQueue.Enqueue(nextTokenNumberTobeIssued);
AddTokensToListBox(tokenQueue);
}
in c# can't read session?
Session["TokenQueue"] = queueTokens;
how to use session in c# winform?
Session normally helps us to maintain information for a user across multiple pages in a web application. When you are converting any web application to windows application you need to know the certain aspects of web application. As session is pretty common in most of web application frameworks. You can achieve same behavior by static variables in any language. In C# you can make a class to hold such information in static variables like this
internal static class SESSIONWINFORM
{
public static string TokenQueue = string.Empty;
public static DateTime LastLogin = DateTime.MinValue;
// more variables as you needed
}
Then you assign these variables values at particular events of your windows application for example in login method to save logged in time like this
protected bool login(string username, string password) {
if (succesfullLogic)
{
SESSIONWINFORM.LastLogin = DateTime.Now;
....
}
}
And to show in a Label1 to user his last login in a WinForm. You can set it text like this
Label1.Text = SESSIONWINFORM.LastLogin;
You don't need sessions since Windows apps run within the user context. There is always a single user.
I would advice to make the variable a static variable, since then it really is shared for the lifetime of the session, as it would in ASP.NET. What if you make a Session class in your Winforms project and mimic the session behavior? That would make it easier to exchange code between your projects.
I have a webpage with a button that does postback, connects to an external database to download some data and perform some database updates. The issue I have is the possibility that two or more people runs this download simultaneously or while the function is still running, which may cause problems.
How do I create some form of semaphore so that if the second person clicks the button, he'll get a message saying it's currently being updated?
Use a proper transaction on your external database and apply row locking there as needed; the DB system should handle the concurrency just fine.
At the first sight, I would use an ASP.NET Application variable enclosed in a lock statement to check and update it if needed.
protected void Page_Load(object sender, EventArgs e)
{
if (!GetSem_SomeoneIsDownloading())
{
PerformDownload();
ClearSem_SomeoneIsDownloading();
}
else
{
DisplayMessageSomeoneIsDownloadingAlready();
}
}
bool GetSem_SomeoneIsDownloading()
{
bool isSomeoneDownloading;
Application.Lock();
isSomeoneDownloading = (bool)(Application["SomeoneIsDownloading"] ?? false);
if (!isSomeoneDownloading)
Application["SomeoneIsDownloading"] = true;
Application.UnLock();
return isSomeoneDownloading;
}
void ClearSem_SomeoneIsDownloading()
{
Application.Lock();
Application["SomeoneIsDownloading"] = false;
Application.UnLock();
}
We are having problems with Safari(and Opera) and from what I have read the FedAuth cookies are just too big.
There is an "neat trick" to fix this:
"WIF RTM added a property to the SessionAuthenticationModule, IsSessionMode. When flipped to true, IsSessionMode has the effect of ensuring that the SessionSecurityToken remains in the cache for the whole duration of the session and generating a cookie which contains just a session identifier rather than the content of the session itself."
I have this code in global.asax:
void WSFederationAuthenticationModule_SessionSecurityTokenCreated(object sender, Microsoft.IdentityModel.Web.SessionSecurityTokenCreatedEventArgs e)
{
FederatedAuthentication.SessionAuthenticationModule.IsSessionMode = true;
}
The Problem , "FederatedAuthentication.SessionAuthenticationModule.IsSessionMode = true" never runs ... why?
Is it related to the "PassiveSignInControl" to set IsSessionMode to true?
MSDN Post
your-fedauth-cookies-on-a-diet-issessionmode-true.aspx
From the book "Programming Windows® Identity Foundation":
"An interesting property of the SAM is IsSessionMode. When set to
true, IsSessionMode has the effect of storing the bulk of the session
on a server-side token cache instead of writing everything in the
cookie. The cookie itself will just contain a small context
identifier, which will be used for retrieving the session on the
server. Unfortunately, in this version of the92 Part II Windows
Identity Foundation for Identity Developers product there is no way to
set IsSessionMode from the configuration file. You can set it via a
property of the PassiveSignInControl, or in the global.asax file as
follows(same code as above)"
Old thread, but I believe SessionSecurityTokenCreated is the proper event to handle this--tested it and it works under "old WIF" and NET 4.5 with the appropriate namespace variations.
void WSFederationAuthenticationModule_SessionSecurityTokenCreated(object sender, System.IdentityModel.Services.SessionSecurityTokenCreatedEventArgs e)
{
e.SessionToken.IsReferenceMode = true;
}
Have you registered your event handler for the SessionSecurityTokenCreated event?
FederatedAuthentication.WSFederationAuthenticationModule.SessionSecurityTokenCreated
+= this.WSFederationAuthenticationModule_SessionSecurityTokenCreated;
This line needs to be added to the Application_Start medthod in your Global.asax file.
The FederatedAuthentication class in in the namespace Microsoft.IdentityModel.Web.
Hi try this: instead of the SessionSecurityTokenCreated event use the SecurityTokenValidated
In the global.ascx
void WSFederationAuthenticationModule_SecurityTokenValidated(object sender, SecurityTokenValidatedEventArgs e)
{
FederatedAuthentication.SessionAuthenticationModule.IsSessionMode = true;
}
Check the comment from Dominick Baier blog
One important thing to note is how to handle SecurityTokenValidated and SessionSecurityTokenCreated events of WSFederationAuthenticationModule class.
Alternative 1 — auto event wire up in global.asax (explicit method names without manual wiring to events):
void WSFederationAuthenticationModule_SecurityTokenValidated(object sender, SecurityTokenValidatedEventArgs e)
{
FederatedAuthentication.SessionAuthenticationModule.IsReferenceMode = true;
}
// or
void WSFederationAuthenticationModule_SessionSecurityTokenCreated(object sender, SessionSecurityTokenCreatedEventArgs e)
{
e.SessionToken.IsReferenceMode = true;
}
Alternative 2 — manual method wiring to events in global.asax. The point is that it must not be in Application_Start but in overriden Init:
void Application_Start(object sender, EventArgs e)
{
// Called only once on application start
// This is not the right place to wire events for all HttpApplication instances
}
public override void Init()
{
// Called for each HttpApplication instance
FederatedAuthentication.WSFederationAuthenticationModule.SecurityTokenValidated += STV;
FederatedAuthentication.WSFederationAuthenticationModule.SessionSecurityTokenCreated += SSTC;
}
void STV(object sender, SecurityTokenValidatedEventArgs e)
{
FederatedAuthentication.SessionAuthenticationModule.IsReferenceMode = true;
}
// or
void SSTC(object sender, SessionSecurityTokenCreatedEventArgs e)
{
e.SessionToken.IsReferenceMode = true;
}