I wanna to track the user activity (log data). i have several links on the page which submit form through specific way .the problem is :
I can't find a suitable way to handle the click event and insert the log in the database in a simple way.
My code :
HtmlGenericControl a = new HtmlGenericControl("a");
a.Attributes["onclick"] = "$('#" + frm.ClientID + "').submit();";
a.InnerText = "site " + dt_list.ElementAtOrDefault(0).Field<string>("pro_name").TrimEnd();
inner_li_1.Controls.Add(a);
Now i wanna to handle the click event of the link which make the submission ?!!
This is too much, how ever its works, and I use it in some case that I can not do other way.
The javascript call, I call the log first, then continue with submit. I have also show a wait message when I make the click, how ever the events happends too fast and the user did not understand that is wait for anything. I also take care to avoid double log of the action with simple javascript. I call this function on the onclick event.
var confirmSubmited = false;
function SubmitWithLog(me)
{
// to avoid many clicks...
if(confirmSubmited)
return false;
confirmSubmited=true;
jQuery.ajax({
url: "/LogAction.ashx",
type: "GET",
timeout: 3000,
async: true, // you can try and async:false - maybe is better for you
data: action=4, // here you send the log informations
cache: false,
success: function(html) {
jQuery("#FormID").submit();
},
error: function(responseText, textStatus, XMLHttpRequest) {
jQuery("#FormID").submit();
}
});
return false;
}
The handler is as
public class LogAction : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// log here what you wish
// end up with no content
context.Response.TrySkipIisCustomErrors = true;
context.Response.Status = "204 No Content";
context.Response.StatusCode = 204;
}
}
I like to clear that this is not a good way to log the user action, but its a way when you can not do otherwise. I use it only ones, when the user make submit and leave my site and go to one other site, and I use it to write this action.
In all other cases I use ether a reference in the url, ether make log on code behind, ether I include an empty image in the html page that make the log like that: ASP server stats for html pages
I have try to call ajax, and right way make the submit, but its fails, the ajax is stop by submit. The next way was to use timeout, to call ajax, and set timeout 500ms to make the submit, but I avoid the timeout because the ajax call takes less than 100ms as I have made it.
#Aristos -- Why in the world would you negatively impact the user experience by waiting for the Ajax call that does the logging to return before moving on with the event (click, submit, whatever...)?!? Logging is a non-critical part of the application, where the user experience does not change based on its results. It's a "send and forget" type routine. Fire off the Ajax request, leave the success and failure routines empty, and execute the submit on the line immediately following the $.ajax(); call.
So, some pseudo code for you...
function handleClick(e) {
handleLoggingOnClick("something happened here");
myForm.submit();
}
function handleLoggingOnClick(message) {
$.ajax({url:"logging.do", data:"message="+message});
}
Related
Disclaimer - I should note that my JavaScript is pretty weak.
I'm in the process of inserting code into my website so it can cover a scenario when a user exits his browser, he gets prompted with a proverbial 'Are you sure you want to quit?' sort of confirmation messsage.
I'm in the process of trying to implement this piece of JavaScript on my website:
<script language="JavaScript" type0"text/javascript">
var foo = true;
window.onbeforeunload = askBeforeExiting;
function askBeforeExiting() {
if (foo)
return "Are you sure you want to leave this page?";
}
</script>
The code not only throws a confirmation message when attempts to exit a browser are made. However, it also throws the confirmation when a link to another portion of the site is clicked and other related events.
Is there a way to modify this code to just capture the browser closing scenarios only? I get that scenario like killing the browser from the Task Manager or from a powershell command can't be captured. I just want the scenarios in the current user session where they may exit the browser.
I've been looking over various samples across the web and through code references and can't seem to track down exactly what I want to do. Is this even possible?
I've done this before where a page has a form, and I only want to ask the user for confirmation when a change has been made to the form. You could do something similar, where you attach a click event to all links, for example, that would set foo to false. Something like:
var links = document.getElementsByTagName('a');
for(var i = 0, l = links.length; i < l; i++) {
links[i].onclick = function () {
foo = false;
}
}
Edit: There are many other actions you might have to account for, depending upon your site, however with the information given, this should be a good start for you as there is no direct way to accomplish what you are after.
I'm doing a high-level spec on an ASP.Net page which may have some delayed data presented.
When the page loads, the initial data presented will originate from a local database (which will be fast in presenting). What I want is a separate process to go out and look for updated data (from whatever other services I have). This is more time consuming, but the idea is to present data, then if newer data is found, append this, on the fly to the top of the existing page.
I would like some recommendations on how to accomplish this.
The tech scope for this is ASP.Net 4.0, C# MVC3 and HTML5.
Thanks.
AJAX with jQuery is a good way to achieve this. So for example you could put a content placeholder div on your markup:
<div id="result" data-remote-url="#Url.Action("Load", "SomeController")"></div>
and then once the DOM is loaded:
$(function() {
$.ajax({
url: $('#result').data('remote-url'),
type: 'POST',
beforeSend: function() {
// TODO: you could show an AJAX loading spinner
// to indicate to the user that there is an ongoing
// operation so that he doesn't run out of patience
},
complete: function() {
// this will be executed no matter whether the AJAX request
// succeeds or fails => you could hide the spinner here
},
success: function(result) {
// In case of success update the corresponding div with
// the results returned by the controller action
$('#result').html(result);
},
error: function() {
// something went wrong => inform the user
// in the gentler possible manner and remember
// that he spent some of his precious time waiting
// for those results
}
});
});
where the Load controller action will take care of communicating with the remote services and return a partial view containing the data:
public ActionResult Load()
{
var model = ... go ahead and fetch the model from the remote service
return PartialView(model);
}
Now if this fetching of data is I/O intensive you could take advantage of asynchronous controllers an I/O Completion Ports which will avoid you jeopardizing worker threads during the lengthy operation of fetching data from a remote source.
There are various ways to handle session timeouts, like "meta refreshes" javascript on load functions etc.
I would like something neat like: 5 minutes before timeout, warn the user...
I am also contemplating keeping the session open for as long as the browser is open(still need to figure out how to do it though... probably some iframe with refreshing).
How do you handle session timeouts, and what direction do you think i should go in?
The best approach to handle sessions timeouts.
I say that there is 2 basic cases.
One is when the users enter little or no data, and just read reports, or do small thinks with his mouse. In this case there is not easy way to inform him that the session is going to expire. If you going to check the time left for the session calling the code behind, then automatically you update the session. Then if you have a timer to count down the session, then maybe the user have open a new tab of your web and the session is going to expired but not the time you have note with javascript and the user receive wrong message.
So for me, when the user enter little or no data, just let the session expired, if he lose one click, it will do it again later.
Second is when the user need to enter many data, that some time can take time, a long text for example, to write it and fix it. In this case I use the below technique and I am not let the session go out.
How to keep the session open as long as the browser.
Here is a very nice and simple technique, I use an image that I make an reload of it before the session is timeout using JavaScript.
<img id="keepAliveIMG" width="1" height="1" src="/img/ui/spacer.gif?" />
<script language="javascript" type="text/javascript">
var myImg = document.getElementById("keepAliveIMG");
if (myImg){
window.setInterval(function(){
myImg.src = myImg.src.replace(/\?.*$/, '?' + Math.random());
}, 6000);
}
</script>
In a third case, you can do this. We care if the session is expired only on post back. When the user have enter some data and on the post back the application is redirect him on the login page and the post lost.
In this third case you can capture the post data and saved them until the user re-login. You capture the post data on global.asax on the
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
This is the function that called before the redirect to the login page, and there you see if you have post data and the use required to login, you save that post data, ether to a new redirect page, ether to the server (maybe on session, maybe on your temporary database).
Now after the user is login again, you redirect him again to the last page with the saved post data, and the user is continue as it is.
The only trick here is to make a middle page, that render the form with the last posted data and an automatically redirect javascript call.
The only thing I can think of is to generate some script on the page that creates a client timer, so that when the page is received and rendered, it can show an alert X-minutes later (that is 5mins before expire).
If you'd rather have the session just keep itself alive, you can do this with a generic handler (ASHX) that you periodically call via AJAX. This will help refresh the session and it should stay alive for as long as the AJAX calls continue.
Example "keepalive.ASHX":
<%# WebHandler Language="C#" Class="keepalive" %>
using System;
public class keepalive : System.Web.IHttpHandler
{
public void ProcessRequest (System.Web.HttpContext context)
{
context.Response.ContentType = "text/json";
var thisUser = System.Web.Security.Membership.GetUser();
if (thisUser != null)
context.Response.Write("[{\"User\": \"" + thisUser.UserName + "\"}]");
}
public bool IsReusable
{
get { return false; }
}
}
And here's the script on the page to call it (with jQuery for simplicity):
<script type='text/javascript'>
function keepAliveInterval()
{
$.ajax(
{
url: "keepalive.ashx",
context: document.body,
error: function () {
alert("AJAX keepalive.ashx error :(");
}
});
}
$(document).ready(function () {
window.setInterval('keepAliveInterval()', 60000);
});
</script>
Use some jquery that keys off of your session timeout variable in the web.config. You can use this Jquery delay trick that when a specific time occurs (x number of minutes after load of the page), it pops up a div stating session timeout in x minutes. Nice, clean and pretty simple.
Regarding session timeout, Codesleuth's ajax call would be perfect.
When the user clicks on a link to generate report I make an AJAX call which generates a pdf file in the background.Now the files are huge running upto 10mb or more.So it takes some time.In the mean time the user should be able to navigate other links as if nothing has happened.So I need to implement in such a way that the pdf generation process gets started & user doesn't have to wait for the process to finish.Is this possible?I am using AJAX Pro with c# with dot net framework 2.0
The problem here is that as soon as the AJAX activity begins the browser enters into a hung stage & the user has to wait although he clicks on a different link.
I would probably create a 'queue' or an 'inbox' for the user ...
start your pdf generation routine with a ThreadPool.QueueUserWorkItem (you would also need to modify your generation method to output to their inbox)
then on each http request check that inbox and notify the user of the item ... you can always poll the server on an interval or somthing
Sure, but once the user navigates to another page, the Javascript that is waiting for the Ajax response is no longer running, so that request is lost. You'd have to either find a way to keep that page open (using frames or exclusively Ajaxified navigiation), or find a way to store the response and notify the user of its completion on the next page view. For instance, storing a session variable that indicates that the operation is completed, or storing it in a database with (perhaps) an "unread" boolean value.
You can have asynchronous Ajax call with which you can do other tasks while response objects returns from the Ajax page.
Here is some example, testAjax.aspx is the Ajax page here :
http_request.onreadystatechange = function() { alertContents(http_request); };
http_request.open('GET', 'testAjax.aspx?', true);
http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
http_request.send(null);
function alertContents(http_request)
{//debugger;
if (http_request.readyState == 4)
{
if (http_request.status == 200)
{
var vResult;
vResult=http_request.responseText;
//Write your logic after successful Ajax call here.
}
else
{
alert('There was a problem with the request.');
}
}
}
So I'm trying to load some returned html from an .aspx page but a click event needs to fire before it doing some stuff that the AJAX request depends upon. More specifically, I'm doing this. When a user types in a text field this function is run...
function KeyPress() {
$("#" + HiddenButtonId).click();
$("#test").load("TempJumpToAJAX.aspx");
}
then $("#" + HiddenButtonId).click(); does sets some session data in a code behind file. Specifically...
Session["SearchText"] = Search.Text;
then, $("#test").load("TempJumpToAJAX.aspx"); calls that .aspx page that returns a newly built select box...
Response.Expires = -1;
StringBuilder builder = new StringBuilder();
builder.Append("<select id=\"testListId\" name=\"testList\" size=\"4\" style=\"width:200px;\">");
builder.Append("<option>");
builder.Append(Session["SearchText"]);
builder.Append("</option>");
builder.Append("</select>");
Response.ContentType = "text/HTML";
Response.Write(builder.ToString());
Response.End();
The problem is, the order seems to be screwed up it tries to append the Session["SearchText"] first, then runs the code that the click event runs. So it functions more like this...
function KeyPress() {
$("#test").load("TempJumpToAJAX.aspx");
$("#" + HiddenButtonId).click();
}
Where the commands are reversed. So what in effect happens is the session variable has an empty string as opposed to what the user typed in the text box. What's odd to me is that it doesn't seem like it should have an empty string, it seems like it should have nothing since the session variable has not been initialized to anything at this point. I really have no idea what's happening. Chalk it up to inexperience I guess. Any ideas?
You are mixing technologies here. The hiddenButtonID click event is trying to do a full postback for the page, whereas the AJAX call will not do a postback. There is no reason to do a post back and then follow it up with an AJAX call. The point of AJAX is to eliminate the need to postback the page and instead just reload a small amount of the HTML on the page using a small callback to the server. Instead of accessing the Search Textbox text in the HiddenButtonID click event handler you should be passing that data to the Server in the AJAX call parameters.
The following client side script should do this.
function KeyPress() {
$("#test").load("TempJumpToAJAX.aspx", {searchText: $("#").val()});
}
In this code you are getting the ID of the search textbox and then using jQuery to retrieve the value of that text box. This will get passed to the TempJumpToAJAX.aspx page as POST variable called 'searchText'. You should be able access this data by accessing the Request['searchText'] variable in the 'TempJumpToAJAX.aspx' page.
Another smart extension to what you are doing, is not to do the ajax call as soon as a key is pressed. If the user types in a long word quickly, you'll get multiple ajax http requests triggered faster than they can return and update your UI.
This adds to your server load, and might make the client's UI sluggish.
Instead, onkeypress, store all the appropriate details and then call
var timeout = setTimeout('some_method()',100);
Which says call the some_method() in 100 milliseconds. The first thing you should do within your keypress method is cancel/clear the Timeout call with clearTimeout.
http://www.w3schools.com/js/js_timing.asp
The some_method() should also clear any timeout, then make the http ajax request.
The net effect here is that your ajax request is delayed slightly, but never happens if the user presses another key. Or put another way, don't try and fire an ajx request until the user has stopped/paused typing. 100 milliseconds might be too high or too low, but you hopefully get the idea!
You should also take care to deal with a "slow server" situation. Consider this:
User types "hello", pauses for 1 second, you fire an ajax request with "hello" as the parameter
User continues to type " world", so the textfield now contains "hello world", and stops typing.
You fire a second ajax request with "hello world" as the parameter.
The second request (for "hello world") returns first, you update your UI
The first request (for "hello") returns, you update your UI again.
Ooops! Have the server include the original query string in the (json) data it returns to the client. When the client gets the ajax data back, check that the result/data is for the query ("hello" / "hello world") that matches what is currently in the text field.
There is a JQuery plugin that encapsulates what the previous answer is talking about. Its called TypeWatch. It allows a function to fire once the user has stopped typing in a text field for a specified number of milliseconds. I've used it before and it works quite well.
Awesome! Thanks to everyone all your answers were quite insightful. The real issue I learned was that I did not know how to send variables with that ajax request. This here.
$("#test").load("TempJumpToAJAX.aspx", {searchText: $("#").val()});
Also mintywalker, thanks for the insight. It was all good.