GWT detect browser refresh in CloseHandler - gwt

I have a GWT application and I want to run some code when the user leaves the application to force a logout and remove any data etc.
To do this I am using a CloseHandler and registering it using Window.addCloseHandler.
I have noticed that when the refresh button is clicked the onClose method is run but I have been unable to differentiate this event from a close where the user has closed the browser. If it is a refresh I do not want to do the logout etc, I only want to do this when the user closes the browser/tab or navigates away from the site.
Does anybody know how I can do this?

There is no way to differentiate the 'close' from 'refresh'. But, you can set a cookie that holds the last CloseHandler call time and check, when loading the module, if this time is old enough to clean the information before showing the page.
You can do that with the folowing utility class (BrowserCloseDetector). Here is an example using it on the onModuleLoad.
The test lines:
#Override
public void onModuleLoad() {
if (BrowserCloseDetector.get().wasClosed()) {
GWT.log("Browser was closed.");
}
else {
GWT.log("Refreshing or returning from another page.");
}
}
The utility class:
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
public class BrowserCloseDetector {
private static final String COOKIE = "detector";
private static BrowserCloseDetector instance;
private BrowserCloseDetector() {
Window.addWindowClosingHandler(new Window.ClosingHandler() {
public void onWindowClosing(Window.ClosingEvent closingEvent) {
Cookies.setCookie(COOKIE, "");
}
});
}
public static BrowserCloseDetector get() {
return (instance == null) ? instance = new BrowserCloseDetector() : instance;
}
public boolean wasClosed() {
return Cookies.getCookie(COOKIE) == null;
}
}

Have you tried
<BODY onUnload = "scriptname">
in your gwt hosting/launching html file?
I am thinking that if you defined a map "hash" (i.e. a javascript pseudo hash) in the hosting file and then accessed the "hash" in GWT through Dictionary class, you could update values in that hash as the user progresses through the gwt app. Which means, your programming style would require you to log milestones on the user's progress onto this map.
When the user closes the browser page, the onunload script of the launching html page would be triggered. That script would access the map to figure out what needs to be updated to the server, or what other url to launch.

I am intereted too if someone got a solution (GWT/java side only).
Maybe we can do it with HistoryListerner ?
1-set a flag for your current viewing page.
2-when ClosingHandler event, launch a "timeout" on server-side (for example 10s)
3-if during this time your got a massage from HistoryListerner with the same last flag so it was just a refresh.
of disconnect if timer is over...
Is not a good solution but I think it is easy to do... If someone have a better one...

Related

How do schedule a task to do it after at a specific date in asp.net webforms?

Say I am desingning an exam portal page where i want To show countdown for the exam date and time and if that specific date and time is reached I want to redirect user to a login page. How can i do this? I have tried using Hangfire but it doesnt redirect me to the redirected page after the time is reached.The scheduled jobs gets updated on the database (HangFire.Job) but it doesnt redirect me to the other page. I am a total newbie in programming and i dont know much so Guiding me on how to acheive something like that would be appreciated a lot and yes, is it even possible to do something like this using Hangfire ?
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888
GlobalConfiguration.Configuration
.UseSqlServerStorage("calanders");
var option = new DashboardOptions { AppPath = VirtualPathUtility.ToAbsolute("/Default.aspx") };
app.UseHangfireDashboard("/hangfire",option);
app.UseHangfireServer();
}
This is the Startup.cs
protected void Button1_Click(object sender, EventArgs e)
{
GlobalConfiguration.Configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseColouredConsoleLogProvider()
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage("calanders", new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true
});
BackgroundJob.Schedule(() => startCountdown(),TimeSpan.FromSeconds(20));
//d.InsertDate(TextBox1.Text.ToDa);
}
public void startCountdown()
{
Response.Write("<script>alert('Time Reached')</script>");
Response.Redirect("WebForm1.aspx");
}
This is the Main Page. (Default.aspx)
In webforms there is no ongoing connection to the server in between postbacks, so a job that is activated on the server side won't be able to interact with the user at an arbitrary future time; only during the immediate time between the button click being triggered and the response being returned.
If you want to show a timer and then do something when it is done, you should look into how to do it with Javascript on the client side, if that works for your scenario. You can use Javascript to make background requests to the server if you need to, but your job won't be directly driven by the server side.

Umbraco - when editor create content send email notification to admin

Is it possible?
I am an admin. I want to be notified by email when editor (or writer or whom ever with the access) creates some content (e.g. enters some News in News document type).
And how?
I use Umbraco 7.5
You need to code into Umbraco ContentService events.
The following should get you started. It will be triggered whenever an item is published.
Be careful what you wish for though. You may get a barrage of useless emails if somebody publishes a parent node along with all of its child nodes.
There are other events that you can hook into so please refer to documentation at https://our.umbraco.com/Documentation/Reference/Events/ContentService-Events-v7.
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
namespace My.Namespace
{
public class MyEventHandler : ApplicationEventHandler
{
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ContentService.Published += ContentServicePublished;
}
private void ContentServicePublished(IPublishingStrategy sender, PublishEventArgs<IContent> args)
{
foreach (var node in args.PublishedEntities)
{
// Your code to send email here
}
}
}
}
You can either write your own custom code by creating some event handlers, which is what #wingyip has recommended, or you can use built-in Umbraco notification functionality.
For the second built-in option, please see all the steps here on this post.

GWT Session timeout with Timer

I am trying to implement session timeout with help of a GWT Timer which will make a RPC call to server to check whether the session is valid or expired by using lastaccessedtime. but every time i make a RPC call it updates the lastaccessedtime (understandable as i am making a RPC call), any way i can prevent my Timer RPC call from updating the lastaccessedtime?
wrote some server side logic to get the lastaccessedtime and try to find out session is valid or not
com.google.gwt.user.client.Timer elapsedTimer;
public void onModuleLoad() {
elapsedTimer = new Timer () {
public void run() {
validateSession();
}};
//giving time delay of 1sec to call the batches
elapsedTimer.scheduleRepeating(60000);
}
public void validateSession(){
//Problem code every time i make this call it updates the last accessed time
viewService.validateSessionGWT(new AsyncCallback<ModuleData>() {
#Override
public void onFailure(Throwable e) {
//do something
}
#Override
public void onSuccess(ModuleData data) {
if(data.getSessionExpired()){
//redirect to login page
}
}
});
}
any idea how to overcome this problem or any other idea to implement Session management in GWT
NOTE: already gone through this which is similar to my approach
https://itsecrets.wordpress.com/2011/07/20/session-timeouts-with-gwt-rpc-calls/
Your GWT servlets extend the RemoteServiceServlet. So you can override processPost and add a custom last call timestamp in you http session. Every request updates this field.
I suggest to implement an abstract servlet that is extended by all your gwt servlets. Additionally you should not only set the custom last access field, but check it just before and only call the super method if everything is fine.
Then your timer and the servlet request you already have should only check this Session field.
Perhaps not the best solution but this should work.

MVC CORE 2.0.0 run c# code on every page

I need to run some c# code each time any page based on _layout.cshtml is viewed. I don't want to put something in every controller.cs file, just something central like you used to have in ASP.NET's MasterPage.cs
Can't get this
Run a method in each request in MVC, C#?
or this
#Html.Action in Asp.Net Core
to run, not sure if it's because they're not CORE 2.0.0, I just get a lot of compilation errors. All I want to do is be able to run some code like this
public class myClass {
public static bool returnTrue() {
return true;
}
}
every time each page is loaded.
You can accomplish this with an action filter
public class GlobalFilter : IActionFilter{
public void OnActionExecuting(ActionExecutingContext context) {
//code here runs before the action method executes
}
public void OnActionExecuted(ActionExecutedContext context) {
//code here runs after the action method executes
}
}
Then in the Startup.cs file in the ConfigureServices method you wire up the ActionFilter like so:
services.AddScoped<GlobalFilter>(); //add it to IoC container.
services.AddMvc().AddMvcOptions(options => {
options.Filters.AddService(typeof(GlobalFilter)); //Tell MVC about it
});
Then you can place code in this ActionFilter which can run before every action method and you can place code in it to run after every action method. See code comments.
Through the context parameter you have access to the Controller, Controller Name, Action Descriptor, Action Name, Request object (Including the path) and so on, so there is lots of info available for you to determine which page you want to execute the code for. I'm not aware of a specific property that will tell you if the page is using _layout.cshtml but you could probably deduce that based on the other properties I mentioned.
Enjoy.
Filter would also work, but the correct way to go in .Net Core is Middleware. You can read more about it here.
If it's something simple as your example, you can go with the first examples on the link like:
app.Use(async (context, next) =>
{
returnTrue();
await next.Invoke();
});
Let me know if it helped!

How to create a kentico form that does not store the response

Is there any way in Kentico to have a user submit a form and then email the response but not actually save the answer to the related table?
As mentioned the emails from Kentico rely on the record being written to the DB before they trigger. Furthermore (unless I'm just unlucky) the only values you have access to are those stored in the table. I had thought that maybe you could mark the offending fields as Field without database representation, but sadly, the fields you may want will all be null - so best not to go down that route.
I took a slightly different approach to #trevor-j-fayas in that I used the BizFormItemEvents.Insert.Before event so that there is no trace of any log. It's a short hop from there to make use of an email template to make things look good. So my code looked as follows:
using CMS;
using CMS.DataEngine;
using CMS.EmailEngine;
using System;
[assembly: RegisterModule(typeof(FormGlobalEvents))]
public class FormGlobalEvents : Module
{
public FormGlobalEvents() : base("FormGlobalEvents")
{
}
protected override void OnInit()
{
CMS.OnlineForms.BizFormItemEvents.Insert.Before += Insert_Before;
}
private void Insert_Before(object sender, CMS.OnlineForms.BizFormItemEventArgs e)
{
var email = new EmailMessage();
email.From = e.Item.GetStringValue("ContactEmail", "null#foo.com");
email.Recipients = "no-reply#foo.com";
email.Subject = "Test from event handler (before save)";
email.PlainTextBody = "test" + DateTime.Now.ToLongTimeString();
EmailSender.SendEmail(email);
e.Cancel();
}
}
To me, it seems cleaner to not insert the record in the first place than delete it, but obviously that autoresponder etc. will only kick in automatically if you do save the record, so the choice is yours and ultimately depends on your preference.
Well, there's a couple different options, but the easiest is to simply delete the record after it's inserted. Use the Global Event Hooks to capture the BizFormItemEvent insert after, if it's your form, then delete it. Below is for Kentico 10:
using CMS;
using CMS.DataEngine;
using CMS.Forums;
using CMS.Helpers;
using CMS.IO;
using System.Net;
using System.Web;
// Registers the custom module into the system
[assembly: RegisterModule(typeof(CustomLoaderModule))]
public class CustomLoaderModule : Module
{
// Module class constructor, the system registers the module under the name "CustomForums"
public CustomLoaderModule()
: base("CustomLoaderModule")
{
}
// Contains initialization code that is executed when the application starts
protected override void OnInit()
{
base.OnInit();
CMS.OnlineForms.BizFormItemEvents.Insert.After += BizFormItem_Insert_After;
}
private void BizFormItem_Insert_After(object sender, CMS.OnlineForms.BizFormItemEventArgs e)
{
switch(e.Item.BizFormInfo.FormName)
{
case "YourFormNameHere":
e.Item.Delete();
break;
}
}
}
The other option would be to clone and modify the Online Form Web part to take the information, manually call the email and cancel the insert, but that's a lot of work when this is quicker.
Yes and no. The record is stored before the email notifications and autoresponders are sent out. Your best bet for this is to create a custom global event handler for the form submission(s) using the BizFormItemEvents.Insert.Before. This will call the event before the actual record is stored in the database. You can then cancel out of the event (which will not store the record) and send your email manually.
Handling global events
BizFormItemEvents Events