Count Number of Visitors in WebSite using ASP.Net and C# - asp.net

I want to keep track of the number of visitors to my site.
I tried the following code in the Global.asax class,
<script runat="server">
public static int count = 0;
void Application_Start(object sender, EventArgs e)
{
Application["myCount"] = count;
}
void Session_Start(object sender, EventArgs e)
{
count = Convert.ToInt32(Application["myCount"]);
Application["myCount"] = count + 1;
}
</script>
I am retrieving the value in the aspx page as follows:
protected void Page_Load(object sender, EventArgs e)
{
int a;
a = Convert.ToInt32((Application["myCount"]));
Label4.Text = Convert.ToString(a);
if (a < 10)
Label4.Text = "000" + Label4.Text ;
else if(a<100)
Label4.Text = "00" + Label4.Text;
else if(a<1000)
Label4.Text = "0" + Label4.Text;
}
The above coding works fine. It generates the Visitors properly but the problem is when I restart my system, the count variable again starts from 0 which logically wrong.
I want the value of count to be incremented by 1 from the last count value.
So can anyone tell me how to accomplish this task?
Please help me out!
Thanks in advance!

If you want the count to keep incrementing over application restarts, you'll need to store the value somewhere - in a database or a file somewhere, and load that value up when the application starts.
Also, you can use the following to ensure your displayed count is always at least 4 characters:
int a;
a = Convert.ToInt32(Application["myCount"]);
Label4.Text = a.ToString("0000");
See Custom Numeric Format Strings for more info.
Edit to respond to comment
Personally, I'd recommend using a database over writing to the file system, for at least the following reasons:
Depending on your host, setting up a database may well be a lot easier than enabling write access to your file system.
Using a database will allow you to store it as an int rather than a string.
Under heavy traffic, you'll have issues with multiple threads trying to open a text file for write access - which will cause a lock on the file, and cause a bottle neck you don't need.
Various resources will tell you how to connect to a database from your code, a good place to start would be this How To: Connect to SQL Server, and looking into the methods under "What are the alternatives" for details on how to query and update the database.

C# code is show below:
protected void Page_Load(object sender, EventArgs e)
{
this.countMe();
enter code here
DataSet tmpDs = new DataSet();
tmpDs.ReadXml(Server.MapPath("~/counter.xml"));
lblCounter.Text = tmpDs.Tables[0].Rows[0]["hits"].ToString();
}
private void countMe()
{
DataSet tmpDs = new DataSet();
tmpDs.ReadXml(Server.MapPath("~/counter.xml"));
int hits = Int32.Parse(tmpDs.Tables[0].Rows[0]["hits"].ToString());
hits += 1;
tmpDs.Tables[0].Rows[0]["hits"] = hits.ToString();
tmpDs.WriteXml(Server.MapPath("~/counter.xml"));
}
Then you need to have an xml file in the root directory to make the code work as well. The XML file will look like this:
<?xml version="1.0" encoding="utf-8" ?>
<counter>
<count>
<hits>0</hits>
</count>
</counter>

In First Answer U had declare count variable globally,that's why in every new session count starts with 0.for better result ,increment application[] variable inside session_start method.

Usually you use other Tools for that Task (weblog analyser).
As you store your value in Memory (Application["myCount"]) this value will not survive a server restart. So you have to store it in a
database
plain textfile
whatever

Related

How do I Redirect a new Tab with Query String in asp.net

How to open new tab window with passing ID using Query String.
I tried all the possible ways,i.e Onclientclick and others. but not.help me.
Thank you in advance
if (e.CommandName == "Items")
{
int ID = Convert.ToInt32(e.CommandArgument.ToString());
Response.Redirect("Add_Items.aspx?TestID=" + ID);
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
int id = Convert.ToInt32(Request.QueryString["TestID"]);
lblTestID.Text = id.ToString();
}
The server-side code can't instruct the browser to open a new tab, that's not how redirects work. All a redirect does is tell the browser to navigate to an address.
To open a new tab, you'd need to use client-side code. Generally this could be as simple as:
window.open(address, '_blank');
However, keep in mind that browsers make no standard guarantee to open things in tabs vs. new windows. That's entirely up to the browser's settings and capabilities. (I think that in some browsers it might make a difference whether this code is executed directly or in a click event.)

Using Background Worker and process.start not able to retrieve progress status

Good evening,
I just started playing around with C# and I tried creating a GUI for a program that runs in command line. I have been able to get it running, but now I am stuck trying to implement a progress bar to it.
I have read other post but I am unable to find the exact issue or to understand how to apply the solution to my issue.
Here is my code (apologize if this is very messy):
private void MethodToProcess(Object sender, DoWorkEventArgs args)
{
// Set all the strings for passthrough
String USMTPath_Work = USMTPath + USMTArch;
String USMTPath_full = USMTPath_Work + #"\Scanstate.exe";
String USMTFlags_Capture = #"/c /v:13 /o /l:scanstate.log /localonly /efs:copyraw";
String Argument_full = SavePath + XML1 + XML2 + USMTFlags_Capture;
// Test that USMT path is correct
if (USMTPath == null)
{
MessageBox.Show("Error: There is no USMT Path defined.");
return;
}
// Test that Windows folder is correct when offline
/* if (Windows_Path == null)
{
MessageBox.Show("Error: There is no Windows Path to capture.");
return;
} */
// Runs the capture
System.Diagnostics.Process Scanstate = new System.Diagnostics.Process();
Scanstate.StartInfo.FileName = USMTPath_full;
Scanstate.StartInfo.Arguments = Argument_full;
Scanstate.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
Scanstate.StartInfo.WorkingDirectory = USMTPath_Work;
//Scanstate.StartInfo.UseShellExecute = false;
Scanstate.StartInfo.CreateNoWindow = true;
//Scanstate.StartInfo.RedirectStandardOutput = true;
Scanstate.Start();
Scanstate.WaitForExit();
String Str_ExitCode = Scanstate.ExitCode.ToString();
if (Scanstate.ExitCode == 1)
MessageBox.Show("Error: Data has not been captured. Please check the log files for details.");
if (Scanstate.ExitCode == 0)
MessageBox.Show("Success: Data has been captured. For more information, check log files.");
else
{
MessageBox.Show("Error: Unknown error has occurred. Please check the log files for details.");
MessageBox.Show("Error Code: " + Str_ExitCode);
}
Scanstate.Close();
}
Basically, I am trying to run the process scanstate.exe. Now, I am trying to run backgroundworker in order to be able to retrieve progress and pass it to the progressbar.
private void btnCapture_Click(object sender, EventArgs e)
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
progressBar1.Step = 1;
BackgroundWorker CaptureBG = new BackgroundWorker();
CaptureBG.WorkerReportsProgress = true;
CaptureBG.DoWork += new DoWorkEventHandler(MethodToProcess);
CaptureBG.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(CaptureBG_RunWorkerCompleted);
CaptureBG.ProgressChanged += new ProgressChangedEventHandler(CaptureBG_ProgressChanged);
CaptureBG.RunWorkerAsync();
}
and
private void CaptureBG_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs args)
{
progressBar1.Value = 100;
}
private void CaptureBG_ProgressChanged(object sender, ProgressChangedEventArgs args)
{
progressBar1.Value++;
}
However I am either missunderstanding the use or I am missing something, since the process runs, but I don't get any progress on the progressbar. It only fills once the process finish.
What am I doing wrong? In general, how would a process report progress if I don't know exactly how long is going to take?
Thanks in advance
The BackgroundWorker is responsible for updating the progress as it gets further complete with its task.
There is no interaction between your process that you launch and your code that would provide progress of that process back to your code.
In order for this to work, two things have to happen:
You need to define a mechanism for your process to report progress to the BackgroundWorker.
The BackgroundWorker must update its own progress by calling the ReportProgress method so that the ProgressChanged event is fired.
The first step is the tricky one and depends on how scanstate.exe works. Does it do anything to give an indication of progress, such as write to the console? If so, you can redirect the console output and parse that output to determine or at least estimate progress.
UPDATE
Scanstate.exe provides the ability to write progress to a log, e.g.:
scanstate /i:migapp.xml /i:miguser.xml \\fileserver\migration\mystore /progress:prog.log /l:scanlog.log
You could use a FileWatcher in your BackgroundWorker to look for changes to the progress log and update progress accordingly.

Is there any way to speed up crystal reports generation?

We are running a reporting web application that allows the user to select a few fields and a crystal report is generated based off of the fields selected. The SQL that is generated for the most complex report will return the data in < 5 seconds, however it takes the report and average of 3 minutes to run, sometimes longer causing a time out. We are running VS2010. The reports are basically set up out of the box with no real manipulations or computations being done, just displaying the data in a nice format. Is there anything we can try to speed it up, pre-loading a dummy report to load the dlls, some hack to make crystal run faster, anything?
EDIT: Code Added to show the databinding
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string strFile = Server.MapPath(#"AwardStatus.rpt");
CrystalReportSource1.Report.FileName = strFile;
DataTable main = Main();
CrystalReportSource1.ReportDocument.SetDataSource(main);
CrystalReportViewer1.HasCrystalLogo = false;
CrystalReportSource1.ReportDocument.ExportToHttpResponse(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, Response, false, "pmperformance");
}
}
private DataTable Main()
{
Guid guidOffice = Office;
CMS.Model.ReportsTableAdapters.ViewACTableAdapter rptAdapter = new CMS.Model.ReportsTableAdapters.ViewACTableAdapter();
Reports.ViewAwardedContractsDataTable main = new Reports.ViewAwardedContractsDataTable();
if (Office == new Guid())
{
IEnumerable<DataRow> data = rptAdapter.GetData().Where(d => UserPermissions.HasAccessToOrg(d.guidFromId, AuthenticatedUser.PersonID)).Select(d => d);
foreach (var row in data)
{
main.ImportRow(row);
}
}
else if (guidOffice != new Guid())
{
main = rptAdapter.GetDataByOffice(guidOffice);
}
else
{
main = new Reports.ViewACDataTable();
}
return main;
}
private Guid Office
{
get
{
string strOffice = Request.QueryString["Office"];
Guid guidOffice = BaseControl.ParseGuid(strOffice);
if (!UserPermissions.HasAccessToOrg(guidOffice, AuthenticatedUser.PersonID))
{
return Guid.Empty;
}
else
{
return guidOffice;
}
}
}
protected void CrystalReportSource1_DataBinding(object sender, EventArgs e)
{
//TODO
}
This may be a bit flippant, but possibly consider not using crystal reports... We had a fair bit of trouble with them recently (out of memory errors being one), and we've moved off to other options and are quite happy...
Here's what I would do:
Put clocks from the time you get the field choices from the user, all the way to when you display the report. See where your processing time is going up.
When you look at the clocks, there can be various situations:
If Crystal Reports is taking time to fill the report, check how you're filling it. If you're linking the report fields directly to your data table, CR is probably taking time looking up the data. I suggest creating a new table (t_rpt) with dynamic columns (Field1, Field2,..FieldN) and pointing your report template to that table. I don't know if you're already doing this.
If it's taking time for you to lookup the data itself, I suggest creating a view of your table. Even though a memory hog, this will make your lookup quick and you can delete the view once you're done.
If it's none of the above, let us know what your clocks show.
In terms of loading any large amount of data, you'll always want to use a stored procedure.
Outside of that, you WILL see a delay in the report running the first time the Crystal DLLs load. Yes, you can preload them as you mentioned and that will help some.

Linq 2 SQL - Manual Databinding not working

I'm using linq2sql in my asp.net app. When using it with linq2sqldatasource object everything works, i mean i bind it without no code to a detailsview control.
My idea is when i click a row in the detailscontrol e will load/add to the same page a customwebcontrol that will permit edit the data.
For that i need to load some items to fill the dropdowns in that customcontrol, and in its load event i have the follwoing code that doesn't work and i can't see why. It raises a object null reference exception.
example:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//loads combobox with organizations
using (MyDataContext cdc = new MyDataContext())
{
var queryOrgs = from p in cdc.orgUnits
select p;
//Organizations
dropDownOrgs.DataSource = queryOrgs.ToList();
dropDownOrgs.DataValueField = "orgUnitID";
dropDownOrgs.DataTextField = "orgUnitName";
dropDownOrgs.DataBind();
}
}
}
Anyone know what is happenning? Looks like when i want to bind all by myself manually something do not work :(
Hope you can help me.
Thanks.
Teixeira
#Chalkey is correct. I have run into this error myself, where due to the fact that LINQ to SQL does "lazy" querying, it waits till the last minute to actually perform the query.
This means that it may wait until after the page_load function to do the query (and therefore outside of the using statement).
Therefore, return the data as a list with .ToList() to force it to run the query immediately.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//loads combobox with organizations
using (MyDataContext cdc = new MyDataContext())
{
List<orgUnit> queryOrgs = (
from p in cdc.orgUnits
select p
).ToList();
//Organizations
dropDownOrgs.DataSource = queryOrgs.ToList();
dropDownOrgs.DataValueField = "orgUnitID";
dropDownOrgs.DataTextField = "orgUnitName";
dropDownOrgs.DataBind();
}
}
}

javascript timer

I am developing an online exam application using asp.net. In the start exam page I have created a javascript countdown timer.
How can I move to the next page automatically after the timer reaches 00?
Here is my code:
long timerStartValue = 1000 ;
private int TimerInterval
{
get
{
int o =(int) ViewState["timerInterval"];
if(o==0)
{
return (o);
}
return 50 ;
}
set
{
ViewState["timerInterval"] = value;
}
}
protected void Page_PreInit(object sender,EventArgs e)
{
string timerVal = Request.Form["timerData"];
if(! String.IsNullOrEmpty(timerVal))
{
timerVal = timerVal.Replace(",", String.Empty) ;
this.timerStartValue = long.Parse(timerVal);
}
}
protected void Page_Load(object sender, EventArgs e)
{
if(! IsPostBack)
{
this.timerStartValue = 10000; //3599000;//14400000;
this.TimerInterval = 500;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
this.timerStartValue = 3599000;
}
protected void Page_PreRender(object sender, EventArgs e)
{
System.Text.StringBuilder bldr=new System.Text.StringBuilder();
bldr.AppendFormat("var Timer = new myTimer({0},{1},'{2}','timerData');", this.timerStartValue, this.TimerInterval, this.lblTimerCount.ClientID);
bldr.Append("Timer.go()");
ClientScript.RegisterStartupScript(this.GetType(), "TimerScript", bldr.ToString(), true);
ClientScript.RegisterHiddenField("timerData", timerStartValue.ToString());
}
Thanks in advance,
sangita
It sounds like when you click the "Next" button, you are loading an entirely new page. This of course changes all the content and resets all the javascript. You can't maintain state across pages without a bit of work.
The solution to this could be to save the timer state when the next button is pressed, and pass it to the next stage. You could do this by saving the timer state to a hidden form input and submitting it along with the Next button.
The other option would be to load your questions via AJAX. Instead of moving to a new page every time the next button is clicked, you could simply replace the question portion of the page with a new question, and leave the timer intact. This is probably the solution I would use.
Are u reloading the entire page when clicking on the next button ? That may leads to realod the java script file also.So the variable values will reset.May be you can think about showing the questions /answers via Ajax.You need not reload the entire page when showing the next question.the part when you show the quiz will only be updated.so you can maintain the global variables in your java script too. Check the below link to know about partial page updating using jQuery.
http://www.west-wind.com/presentations/jquery/jquerypart2.aspx
Hope this helps.
You can put the timer in an iframe if you can't get rid of the postback.
You need a way to persist information between pages, and there's really only one possibility: To make it part of the next page request.
Now, this could be subdivided into 2 categories:
1) As part of the url: http://www.example.com/page?timer=123;
2) As part of the headers;
And number 2 opens new possibilities:
a) As part of POST data;
b) As a client-side cookie only;
c) As a cookie tied to information on the server;
Number 1, 2a and 2b can be manipulated by the user. So what you can do is store some value in a cookie, a hash for example or a database row ID, that you'll use to fetch information on the server.
tl;dr? Use a asp "Session object". It lets you keep things on the server-side and users will have no idea what they are.

Resources