I'm writing a program which has both an ASP.NET configuration system and a Silverlight application. Most users will remain on the Silverlight page and not visit the ASP.NET site except for logging in, etc.
The problem is, I need the session to remain active for authentication purposes, but the session will timeout even if the user is using the features of the silverlight app.
Any ideas?
On the page hosting the silverlight control, you could setup a javascript timer and do an ajax call to an Http Handler (.ashx) every 5 minutes to keep the session alive. Be sure to have your Handler class implement IRequiresSessionState.
I recommend the Handler because it is easier to control the response text that is returned, and it is more lightweight then an aspx page.
You will also need to set the response cache properly to make sure that the browser makes the ajax call each time.
UPDATE
Here is the sample code for an HttpHandler
public class Ping : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.ContentType = "text/plain";
context.Response.Write("OK");
}
public bool IsReusable
{
get { return true; }
}
}
Then if you use jQuery, you can put this on your host aspx page
setInterval(ping, 5000);
function ping() {
$.get('/Ping.ashx');
}
The interval is in milliseconds, so my sample will ping every 5 seconds, you probably want that to be a larger number. Fiddler is a great tool for debugging ajax calls, if you don't use it, start.
I've actually found a pretty cool hack which essentially embeds an iframe on the same page as the silverlight application. The iframe contains an aspx webpage which refreshes itself every (Session.Timeout - 1) minutes. This keeps the session alive for however long the silverlight app is open.
To do this:
Create an asp.net page called "KeepAlive.aspx". In the head section of that page, add this:
<meta id="MetaRefresh" http-equiv="refresh" content="18000;url=KeepAlive.aspx" runat="server" />
<script language="javascript" type="text/javascript">
window.status = "<%= WindowStatusText%>";
</script>
In the code behind file, add this:
protected string WindowStatusText = "";
protected void Page_Load(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated)
{
// Refresh this page 60 seconds before session timeout, effectively resetting the session timeout counter.
MetaRefresh.Attributes["content"] = Convert.ToString((Session.Timeout * 60) - 60) + ";url=KeepAlive.aspx?q=" + DateTime.Now.Ticks;
WindowStatusText = "Last refresh " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
}
}
Now, on the same page as the silverlight app, add this:
<iframe id="KeepAliveFrame" src="KeepAlive.aspx" frameborder="0" width="0" height="0" runat="server" />
Now the asp.net session will remain active while the silverlight app is being used!
The ajax ping / HttpHandler approach is good, but the JQuery $.get function is expecting a json result and throws a javascript parse error.
I modified the Ping HttpHandler to return "{}" instead of "OK" and this worked better.
Related
I've created a socket listener, and I need to display a div (keep it hidden, then make it visible), when the server detects a certain socket data.
I've tried to use a thread, but it doesn't update the UI in realtime, only if the page is reloaded or if you do a post back.
Here is an example of what I want to do, in this case I only want to update a textbox with codebehind data, I would like to do it without ajax, javascript or jQuery, if possible.
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
Thread t = new Thread(TestThread);
t.Start();
}
private void TestThread()
{
for (int i = 0; i <= 1000000000; i++)
{
myTextbox.Text += "1";
}
}
Webpage:
<asp:UpdatePanel runat="server" ID="myPanel" >
<ContentTemplate>
<asp:TextBox runat="server" ID="myTextbox" />
</ContentTemplate>
</asp:UpdatePanel>
what you are trying to do is change the UI (modify client components) from server code (code behind) in asp.net when the server already sent the data to the client.
you have to use client side scripting/coding.
As far as I know, this is not possible without using ajax or JavaScript.
ASP.NET is only responsible for generating the html that is sent from your web-server to the client. Once that html is rendered in the browser, the only way to update the html is via JavaScript.
You can do a Partial Render in WebForms using their AJAX handler without having to write jQuery by enabling a partialRenderingEnabled attribute in the ScriptManager tag. There's no way to do this without scripting or AJAX, the content has to get back to the server to run your code-behind somehow, but at least this way you don't have to write any JavaScript yourself.
For real-time web functionality check out :
SignalR
In a web enviornment, there is no way for the server side to reach out for the client except in the request-response scenario, where the client has to send a request to the server side, the server side handles the request and replies with a response.
EDIT :
SignalR uses the best available technique, websockets when available, if not, AJAX long polling technique in which the client polls(sends a request) to the server, and the server replies only when a certain change to the observed data happens, else SignalR tries repetitve AJAX requests, polling the server over and over until the server replies with the change on the observed data (Worst scenario !).
Also, HTML 5 contains web-sockets, i don't have enough information about it, but it maybe interesting to check out.
With minimal JavaScript you could utilise Server Sent Events for simplex data (from server to client) It doesn't have the overhead of Websockets which has a bit of cost in terms of establishing a connection. However I don't think all browsers are supported but there might be polyfill available for it (library to provide functionality in absence of native support)
Checkout:
http://www.html5rocks.com/en/tutorials/eventsource/basics/
In ASP.NET Threads gets aborted as soon as the page unloads, so this is not possibler you way, sorry.
Your approach could be using AJAX to poll the status from the server on regular intervals. Server on the other hand, will reply according to change in data.
in your ASP.NET Page, add the following script
<head>
<script type="text/javascript" language="javascript">
function poll()
{
var ajax;
if(window.XMLHttpRequest)
ajax = new XMLHttpRequest();
else
ajax = new ActiveXObject("Microsoft.XMLHTTP");
url = "yourPageOrHandler.aspx";
ajax.onreadystatechange = function()
{
if (ajax.readyState == 4 && ajax.status == 200)
{
// success
var receivedText = ajax.responseText;
}
else
{
// error, do the needful
}
}
ajax.open("GET", url, true);
ajax.send();
setTimeout("poll()", 1000); //polls every 1 second, you can change the duration here.
}
</script>
</head>
Start the polling before page finishes
<body>
.
.
.
.
<script type="text/javascript" language="javascript">
poll();
</script>
</body>
Alternatively, you can use the ASP.NET AJAX controls, but that will be heavier compared to JavaScript AJAX.
Glad to help! Please remember to accept the answer if you found it helpful.
The scenario
I have an ASP.NET project which uses a custom authorization/authentication method (vs. using forms/windows authentication, etc.). On each secure page load, the following code is executed:
protected void Page_Load(Object sender, EventArgs e)
{
if (!IsLoggedIn)
{
HttpContext.Current.Response.Redirect("~/Login/", true);
}
}
This code basically checks whether the user is still logged in (no expired ASP.NET session, not logged out, etc.); if the user is not logged in, a Response.Redirect() happens, sending them to the login page.
This scenario works perfectly fine when the user requests a full page (through a link, or direct URL). The issue arises when using an async postback!
I have a button nested inside of an <asp:UpdatePanel>, which cause async postbacks when clicked. This button updates an <asp:Label />. For example:
<!-- the button -->
<asp:LinkButton ID="MyButton" CausesValidation="false" Text="My Button" OnClick="MyButton_Click" runat="server" />
<!-- the label -->
<asp:Label ID="MyLabel" runat="server" />
protected void MyButton_Click(Object sender, EventArgs e)
{
MyLabel.Text = DateTime.Now.ToString();
}
The issue
When an async postback is executing, and IsLoggedIn is false, the request is redirected to the login page. Now, the ASP.NET Framework expects a specific response (rather than an HTML page); thus, throwing the following error:
The question
How can I solve this issue? How can I force the whole page redirect to a specific address from the code-behind during an async postback?
While Kenneth's answer is the appropriate method of redirecting, I needed something a little more custom.
During an async postback, I needed to simulate Response.Redirect("path", true) - the true parameter (Indicates whether execution of the current page should terminate) is the important thing I needed to replicate! Simply using Response.End() after ScriptManager.RegisterClientScriptBlock() would not work because then there would be no response sent back to the browser.
By analyzing the server response to an async postback, I resorted to using the following hack (simulating a response by using Response.Write):
String jsRedirect = String.Format("window.location.pathname = '{0}';", VirtualPathUtility.ToAbsolute(url));
Response.Write(
// required parameters!
"0|asyncPostBackControlIDs|||" +
"0|postBackControlIDs|||" +
"0|updatePanelIDs|||" +
"0|childUpdatePanelIDs|||" +
"0|panelsToRefreshIDs|||" +
// your custom JavaScript
String.Format("{0}|scriptBlock|ScriptContentNoTags|{1}|", jsRedirect.Length, jsRedirect)
);
Response.Flush();
Response.End();
If you want to trigger from the code-behind you can do this:
if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack) {
ScriptManager.RegisterStartupScript(updatepanelid, typeof(string), "redirect", "window.location = 'http://www.google.com';", true);
} else {
Response.Redirect("http://www.google.com");
}
Also note that if you use window.open(), a popup window will be opened (which may or may not be blocked). If you use window.location = "someurl"; it will just do a client-side redirect.
There is some terminology misunderstanding here. "Async postback" is not technically a postback at all; it is an xmlHttpRequest. If you want to do a redirect here, it must be done in javascript in an ajax callback function using window.open().
I'm not sure how you would implement this using asp.net AJAX. During the execution of your xmlHttpRequest code on the server, it is impossible to redirect a client (clarification - you may redirect, but the html you respond with will be (as in your case) incorrectly parsed by asp.NET's javascript ajax code.
With jQuery, this would be a pseudo-solution.
$.ajax({
success: function(data) {
if (data == 'redirect') {
window.open('yourRedirectUrl');
}
}
});
I have an ASP.NET page where an iframe src is being dynamically set:
<iframe id="specialframe" src="<%= IframeSrc %>"></iframe>
And the codebehind:
internal string IframeSrc { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
IframeSrc = SpecialService.GetNewUrl();
}
SpecialService is a third-party service that, when called, returns a one-time use URL that looks something like:
http://www.specialservice.com/oneTimeUseId=fh8396123lkjufgh49
For security purposes, this ID can only be used once before expiring. However, this leads to a problem.
The first time I display the page in a browser, it loads the iframe correctly. However, if I hit refresh, I will receive an error message in the iframe because it's trying to use the same one-time use ID. It works properly if I Ctrl+F5 refresh to force a cache clear, but I can't tell my users to do that every time.
My question is, is it possible to force the browser to never use the cache and always request a fresh copy from the server?
You need to set expiration and caching one your page correctly so browser always will have to request page from the server.
This question maybe a good start http://msdn.microsoft.com/en-us/library/y18he7cw.aspx.
You need cacheability to none (and maybe to set expiration in the past, maybe SetMaxAge too):
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.SetExpires(DateTime.Now.AddMinutes(-30));
How do I redirect from one ASP.NET page to another ("Webform2.aspx") by means of a button?
You can redirect from one page to another using Response.Redirect()
set PostBackUrl property of button, like this :
button1.PostBackUrl= "Webform2.aspx";
You can redirect to another ASP.NET page using the code below :
Response.Redirect("Webform.aspx");
This is the simplest way
Personally, if all you're wanting to do is load a new page when a button is clicked, I would do this with client-side script.
You could use a JS library for this (eg: jQuery), like so:
jQuery
$(function() {
$('#<%= button1.ClientID %>').click(function() {
window.location.href = "Webform2.aspx";
});
});
ASP.NET
<asp:Button id="button1" runat="server"/>
Or, for a specifically ASP.NETesque way to do it, you can use Button.PostBackUrl as Antonio suggests, which still uses client-side script but means you don't have to write it yourself. The HTML for the button renders as:
<input type="submit" name="button1" value="Button" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("button1", "", true, "", "webform2.aspx", false, false))" id="button1" />
If you've got other processing to do server-side and you need to redirect afterwards, use
Response.Redirect("Webform2.aspx"); in your click handler.
If that's not working for you, please add some more detail to your question to explain what's happening.
Well there are lot of ways. Response.Redirect, Server.Transfer, Javascript call to the page.
Javascript call is required when u have no server side actions for the button.
onclick="javascript:window.location.href = Webform2.aspx?id='<%=Request.QueryString["id"]%>'"
Server.Transfer will do a re-direct at server side. i.e, The browser will still show after the response from webform2. Webform1.aspx will re-direct the request to webform2 and webform2 will give the req. (Req = 1, Res = 1)
Response.Redirect: webform1 will send a response asking the browser to make a new request to webform2. In this case, the browser will change the url as it is making a new req to webform2.(Req = 1 + 1, Res = 1+1)
There is one more way, form.submit() if you are interested. The traditional html form submit.
Forgot to mention the best of all, the cross-page postback with PostBack url..
http://aspdotnetcode.source-of-humor.com/TipsAndTricks/General/CrossPagePostbackAspNetCrossPagePostback.aspx
You can use below code :
protected void Button1_Click(object sender, EventArgs e) {
Response.Redirect("default2.aspx");
}
Notice that default2.aspx is your second web page name and you
Response.Redirect(string url) issues a 302 HTTP status code instructing the client to redirect to url. The browser will issue a new request for url and the URL will change in the address bar.
Server.Transfer(string path) terminates execution of the current page and starts execution of a new page on the specified path i.e. internally within IIS. Therefore the URL in the browser address bar will not be changed. The page you transfer to must be an aspx page in the same web site.
The differences are subtle but important. A simple way to think about this is to ask yourself "should the user bookmark/favorite this URL?". Use Response.Redirect if the URL has changed and future visits to the content should be on the new URL. Use Server.Transfer if the URL is correct and current but you need to display different content this one time - maybe you are displaying an error message or you need the user to enter their credentials to continue or there is some other reason why the content should change but the URL should not.
Either of the above can be used within the Click event handler of an ASP.NET Button control in your code-behind:
protected void Button1_Click(object sender, EventArgs e)
{
Response.Redirect("Webform2.aspx");
// OR
Server.Transfer("Webform2.aspx");
}
Both Response.Redirect and Server.Transfer methods are used to transfer a user from one web page to another web page. Both methods are used for the same purpose but still there are some differences as follows.
The Response.Redirect method redirects a request to a new URL and specifies the new URL while the Server.Transfer method for the current request, terminates execution of the current page and starts execution of a new page using the specified URL path of the page.
Both Response.Redirect and Server.Transfer has same syntax like:
Response.Redirect("UserDetail.aspx");
Server.Transfer("UserDetail.aspx");
Before touching on more points I want to explain some HTTP status codes, these are important for the understanding of the basic differences between these two. The HTTP status codes are the codes that the Web server uses to communicate with the Web browser or user agent.
Response.Redirect sends an HTTP request to the browser, then the browser sends that request to the web server, then the web server delivers a response to the web browser. For example, suppose you are on the web page "UserRegister.aspx" page and it has a button that redirects you to the "UserDetail.aspx" web page.
I have a .Net 3.5 website which uses windows authentication and expires the session using a meta tag on the prerender of my base masterpage class.
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (Response.ContentType == "text/html")
this.Page.Header.Controls.Add(new LiteralControl(
String.Format("<meta http-equiv='refresh' content='{0};url={1}'>",
SessionLengthMinutes * 60, SessionExpireDestinationUrl)));
}
This works well for pages that do full post backs. However there are a few pages in my application where the user does a lot of work that is inside of an update panel. My company's policy is a timeout of 15 minutes. Which means, after 15 minutes of working inside of an update panel page, the user gets redirected to the application splash page.
Is there a way to reset or extend the meta tag on an async postback? Or perhaps a better way to accomplish this entirely?
A better way to accomplish this entirely would be to use javascript. This will prevent meta refresh related issues if your page is bookmarked.
In place of the page META REFRESH use this javascript:
<script type="text/javascript">
var _timerID = setTimeout("window.location='splash-url'", 900000); //15 mins
</script>
When you make a request from the update panel use this javascript:
<script type="text/javascript">
clearTimeout(_timerID);
_timerID = setTimeout("window.location='splash-url'", 900000); //15 mins
</script>
In the past I have used the WebMethod(EnableSession = true) attribute on the methods that respond to AJAX calls
You could use an AJAX request to keep the session alive as well. This will work as long as the user has opened your page in the browser.
See http://808.dk/?code-ajax-session-keepalive