Wierd behavior while many clients generate cache - asp.net

I show you my problem by simple code snippet.
This is popular scenario. Users load our page when there is no cache so we generate one. In my code example this take 120 seconds to save cache and before this i inrement static variable.
My qustion is why static variable "i" doesn't increment when i open this page many times in the same moment and cache is null.
public partial class _Default : Page
{
static int i = 0;
protected void Page_Load(object sender, EventArgs e)
{
int i;
var cache = Cache.Get("cache") as string;
if (string.IsNullOrEmpty(cache))
{
i = GenerateCache();
}
else
{
i = Convert.ToInt32(cache);
}
Response.Write(i.ToString());
}
public int GenerateCache()
{
var sw = new Stopwatch();
sw.Start();
++i;
Response.Write(i+"<br>");
while (sw.ElapsedMilliseconds < 1000 * 120) { }
Cache.Insert("cache", i.ToString());
return i;
}
}

Because you have a bug by declaring again the i on the PageLoad
protected void Page_Load(object sender, EventArgs e)
{
int i; // <----- here, this is probably bug and you must remove this line
also you need some kind of locking to avoid multiple calls at the same moment, even tho you saved by the lock of the page session for the moment.

Related

Incrementing variables in ASP.net on every button click

I want to increment date in every click ASP.NET.
But Every time the page posts back, it is essentially starting over from scratch - anything initialized to 0.
I need to persist a value across postbacks but I don't how to do that. I would appreciate for any help.
Here is what I'am trying to do:
int myNumber = 0;
protected void Button1_Click1(object sender, EventArgs e)
{
lblDate.Text = DateTime.Now.StartOfWeek(DayOfWeek.Monday).AddDays(myNumber).ToShortDateString();
myNumber++;
}
Update:
My finaly goal is to get next weeks first day with next button and Previous week, I mean I want to forword and backword...
public int NextCount
{
get { return ViewState["Count"] != null ? (int)ViewState["Count"] : 7; }
set { ViewState["Count"] = value; }
}
protected void btnNext_Click1(object sender, EventArgs e)
{
lblsum.Text = DateTime.Now.StartOfWeek(DayOfWeek.Monday).AddDays(NextCount).ToShortDateString();
NextCount = NextCount+7;
}
protected void btnPrevious_Click(object sender, EventArgs e)
{
lblsum.Text = DateTime.Now.StartOfWeek(DayOfWeek.Monday).AddDays(NextCount).ToShortDateString();
NextCount = NextCount - 7;
}
But When I click Prev button .. there is delay with one click after two or three Click then reaction coming the same with next button when you click from prev to next. Maybe I have to store it in session?
I have updated your code below by using ViewState to handle this. Other easiest option would be storing the same in Session, Cache or Cookie.
While storing a value in ViewState, it will create a hidden field
in the page and store the value to maintain it across the postback.
public int NextCount
{
get { return ViewState["NextCount"] != null ? (int)ViewState["NextCount"] : 0; }
set { ViewState["NextCount"] = value; }
}
protected void btnNext_Click1(object sender, EventArgs e)
{
NextCount = NextCount+7;
lblsum.Text = DateTime.Now.StartOfWeek(DayOfWeek.Monday).AddDays(NextCount).ToShortDateString();
}
protected void btnPrevious_Click(object sender, EventArgs e)
{
NextCount = NextCount - 7;
lblsum.Text = DateTime.Now.StartOfWeek(DayOfWeek.Monday).AddDays(NextCount).ToShortDateString();
}

How can I use my own random captcha in ASP.NET?

For hands on experience, I am generating random numbers and compare their sums on submission, but every time, I press button, random numbers are changing, How can I stop happening this? I considered different experiments, but not able to do that.
Here is my class code for random numbers:
public class Captcha
{
int num1, num2, total;
public int N1
{
get
{
return num1;
}
}
public int N2
{
get
{
return num2;
}
}
public int Total
{
get
{
return total;
}
}
Random r = new Random();
public Captcha()
{
Random r = new Random();
num1 = r.Next(1, 11) * 10;
num2 = r.Next(1, 11);
total = num1 + num2;
}
}
Now, I am using this one on Page_Load event like this :
Captcha c = new Captcha();
protected void Page_Load(object sender, EventArgs e)
{
Label2.Text = c.N1.ToString();
Label3.Text = c.N2.ToString();
}
How can I accomplished this one?
Thanks.
Since you are creating object of Captcha outside the Page Load event, it will get re-created whenever a call to the page happens.
You might be aware that internet is state-less so whenever there is a call to the Page, a new page gets generated, and hence new Captcha object. So you need to maintain the Captcha object in some state management like view state.
Your code should be something like this.
Captcha c;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
c = new Captcha();
Label2.Text = c.N1.ToString();
Label3.Text = c.N2.ToString();
ViewState["c"] = c;
}
}
Then on button click you need to type cast the viewstate back to "c". Something like this.
//button click
c = (Captcha)ViewState["c"];
if(TextBox1.Text.Equals......)
Maybe you need to mark your Captcha class as serializable as it might throw error.
I hope this will help.
Regards,
Samar

Wants to call a function after time interval in ASP.net

My problem is that I have a function implemented on my website which searches for Particular Tweets when I press the button. I want it to make it automatic such that, that function is called again and again after every two minutes, regardless some one uses the website or not..
I have a only a space piece of idea. Such as using a web service. Can any one help?
What you can do is add a System.Timers.Timer in Global.asax.
System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(TimerElapsed), null, new Timespan(0), new Timespan(24, 0, 0));
// This will run every 24 hours.
private void TimerElapsed(object o)
{
// Do stuff.
}
You could use a timer, declared in global.asax, like this:
void Application_Start(object sender, EventArgs e)
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 2000 * 60;
timer.Elapsed += Myhandler;
timer.Start();
Application.Add("timer", timer);
}
static void Myhandler(object sender, System.Timers.ElapsedEventArgs e)
{
}

Textbox value null when trying to access it

namespace Dynamic_Controls.Dropdowndynamic
{
public partial class DropdowndynamicUserControl : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (ControlCount != 0)
{
Recreatecontrols();
}
}
private void Recreatecontrols()
{
// createtextboxes(ControlCount);
createtextboxes(2);
}
protected void createtextboxes(int ControlCount)
{
DynPanel.Visible = true;
for (int i = 0; i <= ControlCount; i++)
{
TextBox tb = new TextBox();
tb.Width = 150;
tb.Height = 18;
tb.TextMode = TextBoxMode.SingleLine;
tb.ID = "TextBoxID" + this.DynPanel.Controls.Count;
tb.Text = "EnterTitle" + this.DynPanel.Controls.Count;
tb.Load+=new EventHandler(tb_Load);
tb.Visible = true;
tb.EnableViewState = true;
DynPanel.Controls.Add(tb);
DynPanel.Controls.Add(new LiteralControl("<br/>"));
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
Int32 newControlCount = Int32.Parse(DropDownList1.SelectedValue);
//createtextboxes(newControlCount);
//ControlCount+=newControlCount;
createtextboxes(2);
}
protected void Button1_Click(object sender, EventArgs e)
{
readtextboxes();
}
public void readtextboxes()
{
string x = string.Empty;
for (int a = 0; a < DynPanel.Controls.Count; a++)
{
foreach (Control ctrl in DynPanel.Controls)
{
if (ctrl is TextBox)
{
x = ((TextBox)ctrl).Text;
}
x+=x+("\n");
}
Result.Text = x;
}
}
private Int32 ControlCount
{
get
{
if (ViewState["ControlCount"] == null)
{
ViewState["ControlCount"] = 0;
}
return (Int32)ViewState["ControlCount"];
}
set
{
// ViewState["ControlCount"] = value;
ViewState["ControlCount"] = 2;
}
}
private void tb_Load(object sender, EventArgs e)
{
LblInfo.Text = ((TextBox)sender).ID + "entered";
}
}
}
Are you adding these controls dynamically in Page_Load (by, I'm assuming, calling your AddRequiredControl() method)? If so, is it wrapped in a conditional which checks for IsPostBack? The likely culprit is that you're destructively re-populating the page with controls before you get to the button click handler, so all the controls would be present but empty (as in an initial load of the page).
Also, just a note, if you're storing each control in _txt in your loop, why not refer to that variable instead of re-casting on each line. The code in your loop seems to be doing a lot of work for little return.
You need to recreate any dynamically created controls on or before Page_Load or they won't contain postback data.
I'm not entirely clear what happens on DropdownList changed - are you trying to preserve anything that has been entered already based on the textboxes previously generated?
In any event (no pun intended) you need to recreate exactly the same textboxes in or before Page_Load that were there present on the postback, or there won't be data.
A typical way to do this is save something in ViewState that your code can use to figure out what to recreate - e.g. the previous value of the DropDownList. Override LoadViewState and call the creation code there in order to capture the needed value, create the textboxes, then in the DropDownList change event, remove any controls that may have been created in LoadViewState (after of course dealing with their data) and recreate them based on the new value.
edit - i can't figure out how your code works now, you have AddRequiredControl with parameters but you call it with none. Let's assume you have a function AddRequiredControls that creates all textboxes for a given DropDownList1 value, and has this signature:
void AddRequiredControls(int index)
Let's also assume you have a PlaceHolder called ControlsPlaceholder that will contain the textboxes. Here's some pseudocode:
override void LoadViewState(..) {
base.LoadViewState(..);
if (ViewState["oldDropDownIndex"]!=null) {
AddRequiredControls((int)ViewState["oldDropDownIndex"]);
}
}
override OnLoad(EventArgs e)
{
// process data from textboxes
}
void DropDownList1_SelectedIndexChanged(..) {
ControlsPlaceholder.Controls.Clear();
AddRequiredControls(DropDownList1.SelectedIndex);
ViewState["oldDropDownIndex"]=DropDownList1.SelectedIndex;
}

How to log POSTed forms submissions?

Back in the ASP classic days when i needed to write out the name/value pairs of forms submitted by POST i thru this loop into the page:
on error resume next
for each x in Request.Form
Response.AppendToLog x & "=" & Request(x)
next
It threw all the form fields and values into the log just as GETs are. Does IIS7 .net give me any better method? (this is for the dev/testing portion of the project i don't have any concern about the space or cycles used to accomplish this).
thx
You can create an http module to log all posts. It allows you to log outside of the pages, a single point of logging instead of having to add the logic to all pages where you want to log activity.
Here you have some of the code. You would have to avoid logging viewstate since is tons of useless information. So you have to add some logic to achieve this.
public class ActivityLogModule: IHttpModule
{
public void Init(HttpApplication application)
{
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if (RecordActivity(context))
{
ActivityLogger.Instance.Log(application.Context.User.Identity.Name,
application.Context.Request.Url.AbsoluteUri,
application.Context.Request.Form.ToString());
}
}
public void Dispose(){}
protected bool RecordActivity(HttpContext context)
{
if (!context.Request.RequestType.Equals("POST"))
{
return false;
}
return true;
}
}
You could have something like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
LogPostValues();
}
private void LogPostValues()
{
string logPath = #"C:\PostedValuesLog.txt";
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Logging: {0}", Request.Path);
sb.Append("Form Values");
foreach (string key in Request.Form)
{
string val = Request.Form[key];
sb.AppendFormat("{0} = {1}<br/>", key, val);
}
sb.Append(Environment.NewLine);
sb.Append("QueryString Values");
foreach (string key in Request.QueryString)
{
string val = Request.QueryString[key];
sb.AppendFormat("{0} = {1}<br/>", key, val);
}
sb.Append(Environment.NewLine);
sb.Append(Environment.NewLine);
sb.Append(Environment.NewLine);
File.AppendAllText(logPath, sb.ToString());
}
This is a crude method though and shouldn't really be used in production code. However, as this is just for development & testing, it should suffice to track what data is being posted to your page via the querystring and form.

Resources