I have a routine which finds all the controls on a page, which I then apply some changes to.
The routine works quite well but I will have to add the chunk of code to every master page and content page to get my results.
I would like to create a single sub routine (which will be in a module) which when called from each page will carry out the work. The only thing I think I need to do to do to make this work is to be able to pass the page name the controls are on to the sub routine to run my routine and have the module make the changes I require to the page I pass to it.
I am sure this is an easy process, but for the life of me I can’t work it out. Can someone help me on how to pass the page name so the routine will apply the changes to that page?
I am using asp.net in Visual Studio 2010, and the code behind is vb.net.
My routine is written in the code behind, not java or aspx. I don’t care if the answer is in C# or vb.net as I can convert if required.
Thanks in advance
Chris
You can send this.Page.UniqueID value as a parameter to the subroutine when you call it from the module.
If you want the current page's class name use:
this.GetType().Name;
If your page inherits from another page, you would use:
this.GetType().BaseType.Name;
What I would do is create a base page that all your pages inherit from and put your FindAllControls() method there.
Here's an example of what that might look like:
using System.Web.UI;
public abstract class BasePage : Page
{
public void FindAllControls()
{
var currentClassName = this.GetType().BaseType.Name;
// Do stuff.
}
}
Then, for example, if you had a Login page, it would look like this:
using System;
public partial class Login : BasePage
{
protected void Page_Load(object sender, EventArgs e)
{
this.FindAllControls();
}
}
Related
I'd like to know if it's possible to access a page's global variables from a user control that is on that page.
public partial class index : System.Web.UI.Page
{
FormsIdentity id = (FormsIdentity)User.Identity;
string custID = "some guid";
string accID = "some guid";
protected void Page_Load(object sender, EventArgs e)
{
}
}
This is just an example, my actual global variables are more complex custom configuration objects but it should be the same.
I'd like to access the variables from a user control. this would be helpful since I'd need to use the same objects on both the page and the user control and I don;t really want to have retrieve and store in in memory twice.
Anyone know if/how to do this? Thanks!
Yes, you can. It is called passing the variables to the user control. Sure it is stored in memory more than once, but that is a bit of the "price" of keeping a separation of concerns and making reusable controls.
If the items are constants, you can store them as true globals and access via a static method in global.asax. If on a request basis, this won't work in a simple manner, but you can fashion it.
Now, for your not wanting to store in memory twice comment. I would not worry about this, as it is a small amount of information (1), especially since it will only last for the duration of the request (2). Not completely true, as GC does not fire immediately.
If you are depending on this information over multiple controls, its best to have a UserControlBase that inherits from UserControl and then make your controls inherit from UserControlBase. Do the same with the Page classes. Then you can add the property to your BasePage. To reference in your UserControlBase just do...
protected UserInfo UserInfo
{
get
{
return ((BasePage)this.Page).UserInfo;
}
}
This is possibly very lame question and I lack knowledge about ASP.Net. In this case a link to an article explaining would be very welcome.
I'm working on web-site on ASP.NET with C# as codebehind. My current project involves developing few pages with very similar functionality and a many functions are the same. For example
private void PermissionCheck()
{
if (null == Session["UserID"] ||
null == Session["ProjectID"] ||
null == Session["AssetID"] ||
null == Session["ProjectName"])
{
Response.Redirect("~/Login.aspx");
}
}
Would be the same on 2 pages. Some other things are the same as well. I would like to put this into common base class. But there are other functions that don't really belong to pages at all:
private string GetAttachmentTempPath()
{
return Request.PhysicalApplicationPath + WebConfigurationManager.AppSettings.Get("AttachmentsTempFolder");
}
I would like to move this into Attachment class, but to get the physical path of the application, I need to pass in Request object into that method, which is not really nice, as it couples Attachment class with Page.Request object.
Is there any way to move these functions somewhere else without needing to pass Page.Request objects around??
p.s. The appliction is huge, and there is no scope to change the entire architecture.
For your permission thing you could make a base page class:
class BasePage : Page
{
...
protected override OnInit() {
// do check here
}
}
Now you can implement your page like this class MyOtherPage : BasePage { ... }
The OnInit gets executed everytime your MyOtherPage gets loaded.
You can see a complete page lifecycle here: Link
For your other problem: Consider to implement a global available static tool class
Update
A good approach for making things like web.config easier to access is a Singleton. In asp.net a singleton is only created once and lives until the asp worker process gets stopped . So this values are shared across the whole asp.net application. This is also good for storing data in a global context that you dont want to get out of your database or file anytime a user makes a page request (for example a version number or things like that)
Update 2
To access the request without passing it to every function, use this:
HttpContext.Current.Request
Base page is a good option for reusable code in Page level. Other than that for things like configuration values it's good to come up with utility classes specifically for those methods base don there type of operations.
If you need to avoid passing in Page object into these types of utility methods,
HttpContext
class would be handy because you can access many of the ASP.Net object through static members through this class. HttpConext # MSDN
If you have similar functions behind the page, you can use ASP.NET WEb User Control.
You can create the functions in the usercontrol and use the control in the pages where necessary.
Have look at this article about Web User Control in Asp.Net
How can I find the name of (default.aspx ) current page or web control in the code behind?
I want to write a superclass that uses this name.
You mean that you want to find the original filename of the object that is currently executed? I.e., from inside a control MyControl you want to retrieve MyControlOnDisk.ascx? In general, this information is lost upon compiling, and moreover, many pages and controls are built on partial classes and the filenames they're from are compiled into a single assembly.
For a page, you can use the following, but only if the page is not internally redirected, is not instantiated as a class from another page, it is not a master page and you're not inside a static method:
string currentPageFileName = new FileInfo(this.Request.Url.LocalPath).Name;
In the case of a control, it is generally not possible as far as I know (it is compiled away), but perhaps someone can shed some light on this.
"i want to write a superclass that use this name "
I assume you mean to write a subclass? If you write a superclass you just create a virtual method and have it implemented in your subclass (the page). If you mean to create a subclass, you can take the classname of the page, which looks like this:
// current page
public partial class MyLovelyPage : System.Web.UI.UserControl
and use it like this to derive from it:
public partial class NewDerivedPage : MyLovelyPage
I would recommend an alternative:
Server.MapPath(Page.AppRelativeVirtualPath)
This works with ASP.Net to get the full path and filename for the current page.
Request.ServerVariables["SCRIPT_NAME"]
if you not use Routing :
string sPath = HttpContext.Current.Request.Url.AbsolutePath;
string[] strarry = sPath.Split('/');
int lengh = strarry.Length;
string sRet = strarry[lengh - 1];
In my master page I have the line
<div class ="breadcrumbs" runat="server"><%= SitePath()%></div>
SitePath() involks a custom class that builds navigation elements based on the combination of the static sitemap and dynamically generated pages. It returns the html for a custom breadcrumb navigation element.
Here is the SitePath() code from my code behind
public string SitePath()
{
BreadCrumbNav breadNav = new BreadCrumbNav();
breadNav.divClass = ".dv";
breadNav.homeTitle = "ABC Home";
return breadNav.Build();
}
I'd like to be able to override this from my dynamic pages so I can add to the path. For Example...
public override string SitePath()
{
BreadCrumbNav breadNav = new BreadCrumbNav();
breadNav.divClass = ".dv";
breadNav.homeTitle = "ABC Home";
breadNav.AddPage("Cooking Equipment", "PathyGoodness/Cooking+Equipment.ASPX");
breadNav.AddPage("Toasters", "PathyGoodness/Cooking+Equipment/Toasters.ASPX");
return breadNav.Build();
}
Is there a way to bring the master page methods into scope so I can override them- or do I need to go about this in a different way? It feels like I'm missing something really obvious, but I seem to be stuck.
Thanks for your help!
Since the Master page is not actually inherited, but rather used as a template, this is not directly possible.
A few other approaches you could try:
Firstly, put this in a ContentPlaceholder and override it in the ASPX markup of your individual pages only where necessary.
A more complicated approach would be to create an interface for all your pages to inherit from that guarantees they have a SitePath() method. Call that method on the page instead, from the Master, and in those pages that do not "override" the behavior, simply call the Master. In others, add your specific implementation to that method, and voila! (I suppose you could also use an abstract BasePage-type class to call the Master from that method)
Generally im against putting page/context specific methods in the masterpage class. Why? Because, as Josh mentioned, Masterpages is just templates. You'll never inherit from a masterpage and you can't show a masterpage without also having access to a Page object. Therefor it makes more sense to put such methods in the Page class.
A much simpler way is to reference a master control directly from your child page.
In your master page, replace the sitepath() function with a literal control like so:
<div class ="breadcrumbs" runat="server"><asp:Literal id="litSitePath" runat="server" /></div>
then in the code for the master page use this:
BreadCrumbNav breadNav = new BreadCrumbNav();
breadNav.divClass = ".dv";
breadNav.homeTitle = "ABC Home";
litSitePath.Text = breadNav.Build();
and in the child page you can override this by using the Master.FindControl method like this:
BreadCrumbNav breadNav = new BreadCrumbNav();
breadNav.divClass = ".dv";
breadNav.homeTitle = "ABC Home";
breadNav.AddPage("Cooking Equipment", "PathyGoodness/Cooking+Equipment.ASPX");
breadNav.AddPage("Toasters", "PathyGoodness/Cooking+Equipment/Toasters.ASPX");
Literal litSitePath = (Literal)Master.FindControl("litSitePath");
litSitePath.Text = breadNav.Build();
Easy peasy and no messing around with eventhandlers or interfaces or anything like that.
I want to get a type of a "BasePage" object that I am creating. Every Page object is based off BasePage. For instance, I have a Login.aspx and in my code-behind and a class that has a method Display:
Display(BasePage page) {
ResourceManager manager = new ResourceManager(page.GetType());
}
In my project structure I have a default resource file and a psuedo-translation resource file. If I set try something like this:
Display(BasePage page) {
ResourceManager manager = new ResourceManager(typeof(Login));
}
it returns the translated page. After some research I found that page.GetType().ToString() returned something to the effect of "ASP_login.aspx" How can I get the actual code behind class type, such that I get an object of type "Login" that is derived from "BasePage"?
Thanks in advance!
If your code-beside looks like this:
public partial class _Login : BasePage
{ /* ... */
}
Then you would get the Type object for it with typeof(_Login). To get the type dynamically, you can find it recursively:
Type GetCodeBehindType()
{ return getCodeBehindTypeRecursive(this.GetType());
}
Type getCodeBehindTypeRecursive(Type t)
{ var baseType = t.BaseType;
if (baseType == typeof(BasePage)) return t;
else return getCodeBehindTypeRecursive(baseType);
}
After some additional research I found that if I call Page.GetType().BaseType it returns the code-behind type of the Aspx page.
page.GetType().BaseType, it has been said before, but let me elaborate as to why.
Aspx pages inherit from their code-behind pages, meaning that the inheritance hierarchy looks like this:
...
Page
BasePage
Login
ASP_Login
Where the top is the parent and the bottom is the child.
This allows your code behind to be accessible from the aspx page, without requiring all of the generated code related to your actual aspx page to be copied into the base class page.
It depends where you're calling Display() from. If you're calling it from the ASPX, then you'llse "ASP_login.aspx". If you're calling it from the code-behind (i.e. the Page_Load() method) you should get the Login page type.
Instead of passing the Page in, you might consider just using the Page property (i.e. this.Page.GetType()) which should always be the current page/codebehind type, if I recall correctly.
I should also make the point that you might consider moving this sort of stuff out of the ASPX/codebehind and into some sort of service. It's generally a good idea to minimize the amount of things you do in a code behind and, instead, push logic into a presenter class and follow the MVP pattern for ASP.NET Web Forms development.