maintain pageViews in global.asax (asp.net) - asp.net

I need a function in global.asax file which gets called only once when user enter a page url. application_beginrequest gets called 50-60 times in a single page( as to render a page several requests go to server.)
I thought of a solution - I can write my function in global.asax and call it on page load of other pages but in that solution I need to call it in every page. I would prefer something which is to be done only in global.asax

You could test the request url in the Begin_Request function:
protected void Application_BeginRequest(object sender, EventArgs e)
{
// Perform some test on the request url that suits your case:
if (Request.Url.ToString().EndsWith(".aspx"))
{
// ...
}
}

Another variation on your approach would be create a subclass of Page which called your global method, or did the work itself and then have all your pages extend your class not Page directly.
public class AcmePage : Page{
// override/subscribe to one of the page events
}
...
public class HomePage : AcmePage
If you are just trying to count page views it may be worth looking at the pre built analytics services available, like the free google analytics. There are others around like CoreMetrics etc.

Related

Checking user authentication in Page_Load()... anywhere else?

For each page in my ASP.Net WebForms app I check the user's access like this:
protected void Page_Load(object sender, EventArgs e) {
if (!UserCanAccessPage())
RedirectToAccessNotPermitted();
// < if user has access, set up the page >
}
My question is, is that single check enough or should I check at all other handlers:
protected void seriousDeleteButton_Click(object sender, EventArgs e) {
// ** DO I NEED TO CHECK ACCESS AGAIN HERE? **
// < do stuff that only some users have access to >
}
I know under a normal page lifecycle the Page_Load() should always be called before the event handlers, but I'm wondering if there's a tricky way to hit other ASP.NET endpoints with curl or mucking around with javascript or something.
(I'm only talking about regular WebForms-style postbacks, no explicit AJAX stuff. But of course UpdatePanel uses asynchronous javascript and I'm sure other controls do to.)
Yes, it is enough, because Page_Load will be called every time a user requests a new page or posts back the page. You do not need to check again in button click events.
However, it is fine with a website with a couple of pages. In other words, if you have multiple pages, maintenance is will be nightmare.
Normally, you want to use Form Authentication, and restrict acesss to pages by using web.config.

Checking Request.ServerVariables["HTTP_REFERER"] on every request

I am using this code to check if the request came from a page , if not then redirect somewhere.
string referer = Request.ServerVariables["HTTP_REFERER"];
if (string.IsNullOrEmpty(referer))
{
Response.Redirect("/UnauthorizedAccess.aspx");
}
It is working , I don't know whether it is perfect the solution.However I am checking this on load event of one of my page.How can I make it check on every request.Should I check this for all my pages.Also it is a good approach.Can anybody point me in the right direction.Any suggestion is welcome.
If you have logic that you would like to be run on the OnLoad of a bunch of your pages. You should probably create a BasePage that derives from Page and have the logic inside. Then all the pages you want that logic in can derive from BasePage instead of the regular Page.
Another approach can be using Master Pages
Note: After reading OPs additional comments. One thing to look out for when using a Master Page is that the Master Page's Page_Load event happens AFTER the Content Page's Page_Load event.
In other words the lifecycle is like this:
Master Page Init Event
Content Page Init Event
Content Page Load Event
Master Page Load Event
If your response.redirect moves the user to another page with the same master page (and same "validation" check) you might find yourself in an endless loop :)
If you have lot of pages, with these kind of common codes, than one possible solution is creating your own MyPage class as a child of the standard Page class. In your MyPage you can use something like:
Page_Load(object sender, EventArgs e)
{
string referer = Request.ServerVariables["HTTP_REFERER"];
if (string.IsNullOrEmpty(referer))
{
Response.Redirect("/UnauthorizedAccess.aspx");
}
base.Page_Load(sender, e);
}
Then any of your pages can inherit from this own MyPage class instead of the .NET's standard one.
In this way the common code reside in one place. In case of any change you have to modify that only there.
Or another possibility, you can consider using Master Pages.

Page_Load or Page_Init

Let's take a really simple example on using jQuery to ajaxify our page...
$.load("getOrders.aspx", {limit: 25}, function(data) {
// info as JSON is available in the data variable
});
and in the ASP.NET (HTML part) page (only one line)
<%# Page Language="C#" AutoEventWireup="true"
CodeFile="getOrders.aspx.cs" Inherits="getOrders" %>
and in the ASP.NET (Code Behind) page
public partial class getOrders : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string lmt = Request["limit"];
List<Orders> ords = dll.GetOrders(limit);
WriteOutput( Newtonsoft.Json.JsonConvert.SerializeObject(ords) );
}
private void WriteOutput(string s)
{
Response.Clear();
Response.Write(s);
Response.Flush();
Response.End();
}
}
my question is
Should it be
protected void Page_Load(object sender, EventArgs e)
or
protected void Page_Init(object sender, EventArgs e)
So we can save some milliseconds as we don't actually need to process the events for the page, or will Page_Init lack of some sorting of a method by the time it is called?
P.S. Currently works fine in both methods, but I just want to understand the ins and outs of choosing one method over the other
Basic page life cycle will answer your question Full article : http://www.codeproject.com/KB/aspnet/ASPDOTNETPageLifecycle.aspx
check same question answer : Page.Request behaviour
Either one would work, because you're essentially throwing out the page lifecycle by calling response.Clear() and response.End(). Technically you could even go as far as putting that code in prerender and it would work. By accessing the Response object you're basically going over the head of the page and cutting it off mid-stride so that you can perform a much simpler task.
I assume you simply do not want the page lifecycle at all and simply want to return JSON from this page? If so, I highly recommend implementing it as a Generic Handler (ashx). In this case you'd simply use context.Request["limit"] and context.Response.Write in your Process method. The benefit of doing this is that you don't have all the overheads of .NET preparing the page class and starting the page lifecycle, and are instead using a file intended for the task you're doing.
It is nice to understand the page lifecycle, as shown in other answers, but realistically you're not using it at all and you'd be better off moving away from the page class entirely.
Page life-cycle only has meanings in context of page elements (controls), so i don't see any differences in your case, since you don't have any other child controls in your page - this is totally irrelevant.
But here is the real question: if you don't have any rendering of html in your page (only data serialization), why you have choose to work with regular .aspx page?
Web service is ideal candidate for this scenario. And you'll be surprised how much performance improvement you'll gain in the end.
You can very well use the Page Init method. But if you have controls in your page and want to access any property of those controls then better to use the Page load event, but in your case you don't need to use page load event.
You can go through the Asp.Net Page Life cycle here to better understand which event to use.

Asp.Net call function from a different *.aspx.cs page

If I have a button inside one page for example "main.aspx". And upon being clicked I want the clicked method in "main.aspx.cs" to call a function from a different *.aspx.cs page but also redirect to that *.aspx page...is that possible?
A more concrete example of what you're trying to do would be useful. Otherwise you'll get all sorts of answers, many of which will be off the mark.
You should put common code in the App_Code folder. You should also not have any business logic inside a forms code-behind.
The fact that you need one page to call a method in another page indicates that you haven't done this. Pages are for displaying and interpreting actions, but they should not hold any of the business logic.
e.g. a lame example of a shopping cart.
ProductView.aspx - calls Cart.AddToCart(Product p)
CartView.aspx - displays all items in the cart, and the user
can update or remove items.
- calls Cart.RemoveItem(int cartIndex)
- calls Cart.UpdateItem(int cartIndex, int newItemCount)
Cart itself doesn't belong in either CartView.aspx or ProductView.aspx. It instead belongs in ~/App_Code/Cart.cs
So your solution could look something like
/ (root of your web folder)
Product/
ProductView.aspx
ProductView.aspx.cs
Cart/
CartView.aspx
CartView.aspx.cs
App_Code/
Cart.cs
Product.cs
Also, to add the App_Code folder if it's not already there, right-click the web project and select Add ASP.NET folder and choose App_Code
You need to understand the ASP.NET Page lifecycle and you'll see why this is not Kosher. If you really need to call a method from multiple pages, it sounds like a good candidate for some external class/object.
Alternately, instead of using a querystring parameter, you can set a Session flag and then redirect to this new page. Then clear the session flag when you call that page's method.
In a very basic way, for Main.aspx to go to Other.aspx and to pass some small amount of data on the querystring to indicate an action.
Main.aspx
protected void OnSomeButtonClicked(object sender, EventArgs e)
{
if( someCondition )
{
Response.Redirect("~/Other.aspx?action=runAway");
}
}
in Other.aspx
protected void Page_Load(object sender, EventArgs e)
{
if( !IsPostBack )
{
if( "runAway".Equals(Request.QueryString["action"] )
{
RunAway();
}
}
}
You should also read up on Server.Transfer versus Response.Redirect. Which one to use is situation dependent.
Also note that QueryString parameters can be altered easily by the user, so always verify them and never trust the user.
Why don't you just redirect with a querystring parameter and then execute the function on the destination page?
Instantiate an object from your other page class and call the method.
protected Button1_Clicked(Sender s, Eventargs e){
MyNamespace.Page_Other po = new MyNamespace.Page_Other();
po.Method1();
Response.Redirect("~/page_other.aspx");
}

Managing page sequence

In an ASP.NET 3.5 site we have a relatively standard payment checkout progess that contains a number of pages that need to be visited in sequence (shopping basket, payment details etc)
Each page has a "Continue" button that redirects to the next page in the sequence.
I would like a way of managing the page sequence so that:
I can have a Master page that defines the "Continue" button and its code-behind OnClick event handler
If the user attempts to visit a page out of sequence (by typing the URL directly into their browser, for example) they get redirected to the correct page
This page sequence is nicely defined in one place in my code (in an enum for example)
Why not use the ASP.NET Wizard control?
Alternatively (and I haven't tried it so I can't say how well it works), you could use Windows Workflow to define a sequential workflow and let that control the order pages come up in. There's an article at http://www.devx.com/dotnet/Article/34732 that takes you through doing it this way.
Check the HttpRequest.UrlReferrer variable in each Page_Load method...
http://msdn.microsoft.com/en-us/library/system.web.httprequest.urlreferrer.aspx
... and don't forget to check for nulls! You can bounce them to where they are supposed to be, based on where they came from.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Session["PreviousPage"] = Request.UrlReferrer.ToString();
...
}
else
{
...
}
}

Resources