ASP.NET Templating with BasePage vs MasterPage - c#

I have to deal with an ASP.NET project in which i have to support localization and translation.
Change of colture may happen only in InitializeCulture method of Page object and not on MasterPage.
Usually when i have to deal with common elements (header/footer) i put them in MasterPage but doing so prevent me to properly localize those elements.
So i am intereseted in understand how to template a page using a common base page that will be derived by all other pages (a sort of MasterPage).
I have found this article that explain clearly how to handle such situation, but i think is a bit outdated :
https://www.codeproject.com/Articles/2915/ASP-NET-Page-Templates-Using-Inheritance
So i would ask if there is a better approach or technology to achieve my goal.

Here a simple demo of how to send a variable to the Master Page. Put a public property in the Master named Language.
public partial class Site1 : System.Web.UI.MasterPage
{
public string Language { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = $"My language is {Language}.";
}
}
Then add a property for the Master in the normal page and cast Page.Master to your Master Page's partial class (Site1 by default).
public partial class Default1 : System.Web.UI.Page
{
public Site1 master;
protected void Page_Load(object sender, EventArgs e)
{
master = (Site1)Page.Master;
}
Then you can access Language in the Master from the Page.
master.Language = "nl-NL";

Related

Property accessible from all pages but change only once per session

I don't think the title is the best description for my problem but, the problem is as following:
I have a base class like:
public class BasePage : System.Web.UI.Page
{
public static ProjectDTO Project { get; set; }
// some other code
// Setting the project once per session.
public void SetProject()
{
Project = (ProjectDTO)HttpContext.Current.Session["Project"];
SiteMaster masterPage = Master as SiteMaster;
masterPage.Project = Project;
}
}
And then i have an aspx page like:
public partial class SomePage: BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
//callling the base method to set the project
SetProject();
}
//some db method which requires the Project.Id property.
GetSomeInfo(Project.Id)
{
//irelevant code
}
}
Everything works fine, but, when i have 2 users online at the same time, they will obviously call the SetProject method, and if one of them uses GetSomeInfo method, the Project.Id property will be the latest one set, not the one from the current user session.
Can anyone help me fix this problem?
PS:
A dirty fix would be to read the session variable every time i have to use the Project, won't be a problem, but my page has like 10 methods requiring that property (a lot of redundant code)
A secondary fix would be to declare a public property on SomePage and use that, but then, i would find Project from the BasePage redundant and i don't like that approach because there are quite a few pages requiring the Project property and using the BasePage (filters, searches, etc on objects belonging to that Project)
EDIT After some more testing, 2 different users at the same time, and after Glubus comments, the problem happens only when the page is loading for one of the users (the user which is not loading anything will get wrong results from the database while the other user is loading a page.)
EDIT2 The workflow is as following:
User goes to home page where a list of projects are available (read from db) -> clicks on one project (when the user clicks the project i'm setting a session variable to be read later). Then the user can see/use other data related to this project.
EDIT3
When a user click on a project, they will navigate to a Dashboard page. Here, on the Page_Load even i'm setting the session variable, like:
public partial class Dashboard : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
int projectId;
int.TryParse(Request.QueryString["projectId"], out projectId);
if (projectId > 0)
{
Session["Project"] = ProjectSvc.GetProjectById(projectId);
SetProject();
}
}
}
ProjectDTO class:
public class ProjectDTO
{
public int idProject { get; set; }
public string Title { get; set; }
public string Users { get; set; }
public string Description { get; set; }
}
I'm setting the Project to the Site Master because i have a label which requires to be seen on the screen with the Project Name and description.
In order to access the Project from the current Session from all places, including WebMethods, declare a static readonly property in BasePage that directly accesses the Session.
public class BasePage : System.Web.UI.Page
{
public static ProjectDTO Project
{
get {return (ProjectDTO)HttpContext.Current.Session["Project"];}
}
// some other code
// Passing the Project to the Master.
public void SetProject()
{
SiteMaster masterPage = Master as SiteMaster;
masterPage.Project = Project;
}
}
You can get rid of the SetProject() call altogether if you also use BasePage.Project to access the current project from the Site Master.
During testing, make sure that you are not using the same browser instance for testing. When session managements happens via cookies and you have two users logged in into the same browser instance, they will actually use the same ASP.net session.
Perhaps a worst case scenario solution - but....
If you are really intent on making the Project variable accessible to all subsequent users, you maybe need to move away from sessions and just declare it as a static?
This way it will be shared application wide, retaining the last assigned value.

Pass down master page object to nested master page

Apologies if this is too trivial but I seem to be running into an issue where I cannot access an object from a nested master page.
I'm having trouble passing down a User object from my main master to my nested master. By the time it gets to my nested master page it's null. I don't ever remember having trouble getting master pages talking but in this instance it just doesn't want to work.
So the set up, Some code omitted:
public partial class RWCMSMain : System.Web.UI.MasterPage
{
public Business.BusinessEntities.User LoggedOnUser { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
//Get the user
var loggedOnUser = userRepo.GetUser(securityToken);
//Now set the property
this.LoggedOnUser = loggedOnUser;
}
}
If I was to access this from a content page that inherits the main master all is great but the idea was to have a master page that contains side bar.
Now my side.master inherits from main master:
public partial class RWCMSSide : System.Web.UI.MasterPage
{
//Create property for nested master
public Business.BusinessEntities.User LoggedOnUser { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
//Assign main masters user to the new property
//Master.LoggedOnUser is always null
this.LoggedOnUser = Master.LoggedOnUser;
}
}
You could argue that I could recreate the user on the nested master page but then that would create two hits to the database when it could be done as one.
Whilst debugging the main master the user exists, it's just not being passed down.
Any pointers would be greatly appreciated!
Regards,
Problem
The Master's Load is executed after the Child's Load:
...
Master page Init event.
Content page Init event.
Content page Load event.
Master page Load event.
Master page controls Load event.
...
That's is why the property is null.
Solution
1. You can set it in the Init event - protected void Page_Load(object sender, EventArgs e)... if it is not dependent on the page being loaded (as it is probably).
2. Or you can turn the property into the lazy property(no need for actual Lazy<T> if it is not (and it probably should not be) intended to be used in multithreaded code):
public partial class RWCMSMain : System.Web.UI.MasterPage
{
private Business.BusinessEntities.User m_LoggedOnUse;
public Business.BusinessEntities.User LoggedOnUser
{
get
{
if (this.m_LoggedOnUse == null)
this.m_LoggedOnUse = userRepo.GetUser(securityToken);
return this.m_LoggedOnUse;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
}

ASP.NET C# object in Master Page to be visible to all other pages that are based on that Master Page

I need to be able to make an object that is instantiated in a ASP.NET Master Page to be visible to all of the pages in the application that are based on that Master page. At the moment I'm defining the object here:
public partial class Control : System.Web.UI.MasterPage
{
public User TheUser;
protected void Page_Load(object sender, EventArgs e)
... but I think that's where I'm going wrong. Can anyone help?
Are you trying to create a control that inherits from a MasterPage? What you really want to do is create a MasterPage and add a property to it:
public partial class MyMasterPage: System.Web.UI.MasterPage
{
public string MyProperty {get;set;}
}
Now, from a Page that uses that MasterPage, you can just reference the MasterPage and access its members directly:
protected void Page_Load(object sender, EventArgs e)
{
MyMasterPage m = Master as MyMasterPage;
string masterProperty = m.MyProperty;
}
You'd be better off creating a base page (that inherits from System.Web.UI.Page) that all your pages inherit from, add your TheUser object to the base page.
Please note, pages do not inherit their master pages.

Is it possible to persist the viewstate between pages in ASP.NET?

I have a button (view state enabled) in Master web page and set it to visible=false in one of the child web pages. If a second child page is opened, the button state (visible=false) is not persisting.
It seems viewstate is only valid for one page and is not transferred to other web pages. Is there some kind of trick to make viewstate global for all web pages?
No, viewstate is page specific. You will need to use something like a session variable or a querystring parameter to pass your state between pages.
No, You cannot make view state global, they are page specific. I would suggest to use cookies if you really want to make it client side otherwise you can use session.
If you need to store on a "global" level, you should be using the Application State. You could also use Cache Object.
You may be wanting to pass values from one page to another, you can achieve this by using the Context object in combination with the Server.Transfer.
1) You need a public property on the source page returning the Value to pass
namespace SomeNameSpace
{
public partial class SourcePage: System.Web.UI.Page
{
public string ValueToPass
{
get
{
if (Context.Items["ValueToPass"] == null)
Context.Items["ValueToPass"] = string.Empty;
return (string)Context.Items["ValueToPass"];
}
set
{
Context.Items["ValueToPass"] = value;
}
}
........
}
}
2) Do a Server.Transfer(DestinationPage.aspx)
3) In the Page_Load event of the destination page
namespace SomeNameSpace
{
public partial class SourcePage: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var value = this.Context.Items["ValueToPass"];
}
}
}
Hope this helps

variable declared in master page not available in content page

I have the master page code behind like this:
public partial class TheMasterPage : System.Web.UI.MasterPage
{
string test = null;
protected void Page_Init(object sender, EventArgs e)
{}
}
When I'm in the Page_Load function in the code behind of the content page, I don't see the variable test as being available. Am I declaring it wrong?
Thanks.
Your property should be public and should have get, set
public string test
{
get; set;
}
I already answered it a little early Accessing property of master page inside content page
Having a master Page is not the same as inheriting a page class. What you would want to do is have a public property on the master page, and then access that from the content page.

Categories