Checking Request.ServerVariables["HTTP_REFERER"] on every request - asp.net

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.

Related

User control instances are null while using nested master page

I have couple of user controls which are statically referenced in aspx. We are setting some public properties on the user controls in Page_Preinit event.
The page also references a master page
This was working fine so far. Had to do a ui redesign and we implemented nested master pages.
Now, all of a sudden, the user controls are showing up as null. If I change the master page to parent one (instead of child -nested), it works fine.
Appreciate any pointers to this issue.
some sample code: here ucAddress is null
protected void Page_PreInit(object sender, EventArgs e) { ucAddress.City = "Dallas"; }
This blog post describes the problem very well and also offers a solution. I can confirm that the solution works and I'll repeat the relevant parts here:
The problem
We have a user control and initialize its control in the Init event so that it is ready when the ViewState is restored (between Init and Load).
Once you start using this encapsulation technique, it won’t be long until you want to pass in a parameter that affects the data you load. Before we do, we need to be aware that the Init event is fired in reverse order. That is, the child controls have their Init event fired before that event is fired at the parent. As such, the Page.Init event is too late for us to set any properties on the controls.
The natural solution is to try and use the Page.PreInit event, however when you do you’ll often find that your control references are all null. This happens when your page is implemented using a master page, and it relates to how master pages are implemented. The <asp:ContentPlaceHolder /> controls in a master page use the ITemplate interface to build their contents. This content (child controls) is not usually prepared until the Init event is called, which means the control references are not available. For us, this represents a problem.
The Solution
The fix is remarkably simple; all we need to do is touch the Master property on our Page and it will cause the controls to become available. If we are using nested master pages, we need to touch each master page in the chain.
The author of the blog post then offers a nice little snippet that you can execute in the PreInit handler of your Page that uses a MasterPage and contains a user control:
protected override void OnPreInit(EventArgs e)
{
// Walk up the master page chain and tickle the getter on each one
MasterPage master = this.Master;
while( master != null ) master = master.Master;
// Access now initialized user control
ucAddress.City = "Dallas";
}
Found the issue. had to initialize child master page before accessing user control.

multiple master pages for 1 calling page

I have 2 master pages with same (href) links on top of the page. Now these links load on the same master page when clicked on (by requirement). The problem is both these master pages have same links, so basically the same page shall be loaded in the master page.
Now what i need is when the person is on Master Page 1 and clicks on the link it should load in the same page. Whereas if the user is on Master Page 2 and clicks on the same link, i should be able to change the master page from 1 to 2 and load that in Master Page 2. Something like DirectCast.
any ideas?
You can switch the master page in the Page_PreInit event. For more of an explanation check out http://msdn.microsoft.com/en-us/library/ms178472.aspx
It would look like
void _Default_PreInit(object sender, EventArgs e)
{
this.MasterPageFile = "NewMasterPage.master";
}
I don't think I fully understand your use case, but here are some ideas:
You could track which MasterPage the user is on through Session state, and use that to remember which MasterPage to show in subsequent visits.
If you can alter the hrefs slightly, you could use a query string to indicate which MasterPage should be utilized.
Depending on your application, you could store which MasterPage should be used in your database, tied to each user.
I assume you're dynamically switching MasterPages based on some logic, so it just comes down to choosing a method to store which MasterPage should be used.

ASP.NET How to raise load event on previous page with cross page postbacks

I'm working on a wizard-like set of page, and I'm relying on cross page postbacks to navigate between them.
I need to be able to trigger the Load event on the previous page in order to save the form data for the page.
I've been told that for situations of this sort all I had to do is access the PreviousPage property in the destination page and this would trigger the load event of the previous page but for some reason this doesn't seem to be working.
Is there anything else I can do to explicitly trigger the load event on the previouspage if the PreviousPage property is not null?
Thanks for your help,
Yong
Have you considered moving whatever persistence logic you're doing in the load of the Previous Page into a method on the page?
That way you can just hit:
if(PreviousPage != null)
PreviousPage.DoThatSavingThing();
Obviously you'd need to type it to get the specific methods you add unless you added those to all pages.
This sounds a little confusing to me, but if you are wanting access to data, it's best to save that data into something that you can easily get to, like the ASP.NET session cache. So instead of going back to a previously navigated page in order to get data, you will cache the data the first time you reach the first page, and then when the user navigates to the 2nd page, it will have access to that information.
To add - I tested using two methods of getting a "strongly-typed" previouspage.
Added a reference to the destination:
Added the PreviousPage directive on the destination:
When accessing the PreviousPage property in the destination, the Load event was fired on the
PreviousPageName page (source).
Example (assuming there is a public property named Test on the PreviousPageName (Source page)):
protected void Page_Load(object sender, EventArgs e)
{
if (PreviousPage != null)
{
//Using a reference, you have to cast:
PreviousPageName x = (PreviousPageName)PreviousPage;
string test = x.Test;
//Using the PreviousPage directive, you do not need to cast:
string test2 = PreviousPage.Test
}
}

Best way to implement languages menu in an ASP.NET application

I trying to implement a typical languages menu where users can select the language they want to view the site in through a menu that appears throughout all pages in the site.
The menu will appear on multiple master pages (currently one for pages where users are logged in and one for pages where users are not).
My current implementation is having a single master page base class (let's call it MasterBase). MasterBase has an event
public event LanguageChangedEventHandler LanguageChanged;
where LanguagedChangedEventHandler is simply defined as
public delegate void LanguageChangedEventHandler(string NewCulture);
MasterBase also has an overridable method
protected virtual void OnLanguageChanged(string NewCulture)
which just basically fires the event.
Each master page that inherits MasterBase overrides OnLanguageChanged and does the usual stuff like set the Thread's CurrentUICulture and the language cookie then does a
Server.Transfer(this.Page.AppRelativeVirtualPath, true);
to get the page to reload with localized values for the new culture. On the master page for logged in users it also updates the user's language pref in the db.
Each language option is currently a LinkButton on a master page that inherits from MasterBase. When the link is clicked it calls the base OnLanguagedChanged method passing in the correct culture info. E.g.
protected void btnEnglish_Click(object sender, EventArgs e) {
this.OnLanguageChanged("en-US");
}
Each page that needs to handle a language change then has some code in the page load that looks like...
((MasterBase)this.Master).LanguageChanged += this.Page_OnLanguageChanged;
// Where Page_OnLanguageChanged has the signature of LanguageChangedEventHandler
// and has stuff like reloading options in a drop down using the new language.
Quite a convoluted 'framework' =)
Firstly it's hard for new developers to know they have to hook up a method to the MasterBase's LanguageChanged event to handle language changes. Yes, we do document it. But still it's not something straightforward and obvious.
Secondly, all language changes are post backs. This is problematic especially when you want to navigate back with the browser Back button.
I'm looking for a more elegant solution. One that doesn't have both the problems above and also handles my current requirements.
Greatly appreciate any suggestions. Thanks.
It seems to me that it would be better to implement this in a control that sets an application variable that all pages could use. That way you could just implement the code in one place and have it always available on each page that displays the control (could be in your master's so all pages that inherit get it automatically). I think in the control you would have a handler that sets the global language setting and then reloads the page. Each page would check the language setting during page_load or prerender and load the proper localized strings accordingly.
I would just use the PreInit event on base page to set the current ui culture. I am not clear on why you would need each page to know when language is changed.

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