Is there a way to get a value I am storing in a Master Page hidden field from a User Class which I created and placed in the App_Code folder of my ASP.Net 2.0 Application?
Some examples would preferably in VB.Net is highly appreciated.
Thanks.
To give further details, assume the following:
MasterPage.Master
MasterPage.Master.vb
MyPage.aspx
Mypage.aspx.vb
IN the app_code folder, add a new class, say TESTClass.
I have placed some logic in master page. MyPage.aspx uses the Masterpage.master as its master page. In the master page, the logic which I did stores a value into a hidden field.
in my TestClass, how do I access the master page hidden field?
Please take note that TestClass is NOT a user control but a user defined class, which contains some Business-Specific logic which is accessed by myPage.aspx.vb.
I tried ScarletGarden's suggestion but it did not seem to get the Masterpage Hiddenfield which I need to get the value.
Would something like this work?
((HiddenField)this.Page.Master.FindControl("[hidden control id]")).Text
You can get it by these :
hiddenControlValue = HttpContext.Current.Request["hiddenControlId"]
or you can pass your page to your method that belongs to your class under App_Config, and reach it as :
public static string GetHiddenValue(Page currentPage)
{
return currentPage.Request["hiddenValue"];
}
or you can get it over context :
public static string GetHiddenValue()
{
return HttpContext.Current.Request["hiddenValue"];
}
hope this helps.
EDIT: I re-read the question after answering, and realize my answer was probably not quite what you were after. :/
Jared's code might work, but you can also try the following.
In your MasterPage, make the HiddenField a public property, and store the content in the ViewState to make keep it during post backs.
Something like so:
public HiddenField theHiddenField
{
get
{
if (ViewState["HiddenField"] == null)
return null; //or something that makes you handle an unset ViewState
else
return ViewState["HiddenField"].ToString();
}
set
{
ViewState["HiddenField"] = value;
}
}
You then have to add the following to your ASCX-file:
<%# Reference Control="~/Masterpages/Communication.Master" %>
You then access it thusly.
Page mypage = (Page) this.Page; // Or instead of Page, use the page you're actually working with, like MyWebsite.Pages.PageWithUserControl
MasterPage mp = (MasterPage) mypage.Master;
HiddenField hf = mp.theHiddenField;
Sorry if the answer got a bit messy. This is, of course, how to do it in C#, if you want to use VB have a look at this link for the same idea.
Related
So I have 2 master pages and one user control which is used on almost every page. Page may have one of 2 master pages and both master pages have one property common. It is a list variable that I need access. How do I know which master page is being used and then access it?
I am trying
MasterPage mp = (MasterPage)this.Page.Master;
but when I debug, I don't see the list property. mp.List doesn't work. Any idea on how to get this property?
Thanks in advance
Consider using a simple interface to make this easy.
public interface IHasProperty
{
List<string> MyVariable {get;set;}
}
public partial class MasterPage1 : (other stuff), IHasProperty
{
List<string> MyVariable {get;set;}
}
public partial class MasterPage2 : (other stuff), IHasProperty
{
List<string> MyVariable {get;set;}
}
then from the user control, you can access this by using something like this.
var myPropPage = Page.Master as IHasProperty;
if (myPropPage == null)
{
//this property isnt on the page.
return;
}
myPropPage.MyVariable.Add("new Value");// or whatever you needed to do with it.
Add a strongly typed reference to the master page on your aspx as so:
<%# MasterType VirtualPath="~/Site.Master" %>
Then in the code behind you can do this.Master without having to cast and the list should be accessible.
I have a webusercontrol with a public int property SelectedCatID. I use this control on other pages and in other controls as follows:
<NewStore:LeftMenuLinks runat="server" SelectedCatID="<%#CatIDToSelect%>" />
How do I output cache this control based on SelectedCatID? Everything I've tried fails.
The closest I've gotten is getting it to cache, but it doesn't vary on SelectedCatID leaving the same menu item selected until the cache expires. Without caching, the control works as expected.
I figured out why the VaryByControls approach you used initially does not work. Sadly you edited it out of your question, so my research for this will just have to go into a blog post. Update: the blog post in question: http://tabeokatech.blogspot.be/2014/09/outputcache-on-user-controls.html .
The long and short of it though is that VaryByControls is kinda shorthand for VaryByParams, and does nothing for properties: it only looks at POST values. The fact that it ever worked for properties with a static value appears to be a bug - any string whatsoever in the VaryByControls would have made that part work. The accepted answer to this question is wrong: Vary by control properties using PartialCaching in ASP.NET .
There is no built-in way to vary by control property values.
That wouldn't make sense anyway, because user controls need to be created to have property values, and you want to avoid creating them, instead caching their rendered markup - cached user controls fields are null in code-behind if cached markup is served for them.
This works by injecting a PartialCachingControl into the page instead of the actual user control. This PartialCachingControl checks the cache, and only creates the control if no cached version exists.
As for making it work, I see two options:
If you only have 1 usercontrol per page, you could use the VaryByCustom approach. To make things easy you could write an interface that returns your property value for that page, and implement it on every page that hosts the user control, e.g.:
interface INumberProvider
{
int GetNumber();
}
// and the page:
public partial class _Default : Page, INumberProvider
{
public int GetNumber()
{
return this.SomeNumberPropertyOrWhatever;
}
...
In your Global.asax you cast the current handler to INumberProvider and get the number:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (custom == "INumberProvider")
{
var page = context.CurrentHandler as INumberProvider;
if (page != null)
{
return page.GetNumber().ToString();
}
}
return base.GetVaryByCustomString(context, custom);
}
And in your control you obviously add:
OutputCache Duration="180" VaryByCustom="INumberProvider" VaryByParam="None" Shared="true"
That's if you only have one user control per page, and should be pretty straightforward. If you need more than one user control per page you're out of luck:
Build your own wrapper around your user control by writing a custom WebControl. Add the properties you need, capture the output of the rendered user control, and insert it into HttpContext.Current.Cache with a key that includes the SelectedCatID. Basically write your own custom PartialCachingControl.
There's also option 3:
Decide caching is not that important after all
<%# OutputCache Duration="60" VaryByParam="SelectedCatID" %>
Now store youre <%#CatIDToSelect%> as an a parameter ex ?SelectedCatID=12
Now you're Page or UserControl depending on what you want to cache will output the cache depending on what the Request.Param["SelectedCatID"] is equal to.
You can also do something like this (although not the easiest way)
This goes on the page/usercontrol you want cached:
<%# OutputCache duration="120" varybyparam="None" varybycustom="SelectedCatID" %>
This goes into the Gloabal.asax file:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if(custom == "SelectedCatID")
{
return CatIDToSelect;
}
return String.Empty;
}
I'm late to the party here what with an accepted answer and a 500 point bounty awarded. Still wanted to give my few cents on how this could be achieved.
It can be made to work in the control itself. You can have the control store it's own output in the cache and use the cached version in the Render method if found. I have made a really simple UserControl to test with. The markup looks like this:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="TestUC.ascx.cs"
Inherits="Webforms_Test.UserControls.TestUC" %>
<div>
<asp:Label ID="curTime" runat="server"></asp:Label>
</div>
It just contains a label that is set to DateTime.Now when it is initialized. The code behind looks like this:
public partial class TestUC : System.Web.UI.UserControl
{
private string cachedOutput = null;
public bool RenderFromCache = true; // set to false in containing page if this control needs to be re-rendered
protected void Page_Load(object sender, EventArgs e)
{
cachedOutput = HttpContext.Current.Cache["key"] as string;
if (cachedOutput == null)
{
// not found in cache, do the heavy lifting here to setup the control
curTime.Text = "UC:" + DateTime.Now.ToString("yy-MM-dd hh:mm:ss");
}
}
protected void Page_PreRender(object sender, EventArgs e)
{
if (cachedOutput == null || !RenderFromCache)
{
RenderFromCache = false;
StringBuilder b = new StringBuilder();
HtmlTextWriter h = new HtmlTextWriter(new StringWriter(b));
this.RenderControl(h);
cachedOutput = b.ToString();
HttpContext.Current.Cache.Insert("key", cachedOutput, null, DateTime.UtcNow.AddSeconds(10), TimeSpan.Zero);
RenderFromCache = true;
}
}
protected override void Render(HtmlTextWriter writer)
{
if (!RenderFromCache)
base.Render(writer);
else
writer.Write(cachedOutput);
}
}
In this sample, the control itself checks if its output is found in the cache, and if so the Render method will just write the cached output. If it is not found in the cache, the PreRender method will run the Render method normally and capture the output and store it in the cache.
In your case you would of course need a bit more logic which would check the relevant property on the control and use that to check if a cached version exists.
Disclaimer: This is an extremely simple test control. I have not tried to figure out how to make all of this work with controls that contain event handlers etc. So take it for what it's worth...
I have this following property in my custom user control:
public string selectedtab
{
get
{
if (ViewState["AdminCurrentNavID"] != null)
{
return ViewState["AdminCurrentNavID"].ToString();
}
else {
isfirstload = true;
return null;
}
}
set { ViewState["AdminCurrentNavID"] = value; }
}
I am setting the value of it on my Page_Load() in ascx control. What i need to do is that after setting the value of this property I need to access it from masterpage.cs in code behind. you can see how currently I am trying to do in below code, but the issue is that I am not able to get the value i thing it is because the masterpage's Page_Load() rendering before the ascx control so I thats why I am getting null value, please help, thanks.
masterpage.cs:
usercontrols.mainmenu adminmenu = (usercontrols.mainmenu)LoadControl("~/mymenupath.ascx");
lbmsg.Text = adminmenu.selectedtab;
When you call LoadControl in your master page, you are actually creating a new instance of your user control, not accessing the one you have somewhere in your site.
When you declare the User Control in your page you should have given it an id. You could access the property with something like ((usercontrols.mainmenu)MyUserControlId).selectedtab
I found the solution by using Delegate, you can see in the link below.
http://webdeveloperpost.com/Articles/Return-value-from-user-control-in-ASP-NET-and-C-Sharp.aspx
I'm curious to know that using .net 2.0 with a master page if there is a way that I can pick up what page I am on so that i can use it to style a tab?
My master page has a nav bar on it, and what I wan to do is:
If the user is, say on the contact page, that the tab for the contact page would be a different color, can this be achieved. I have seen some examples that don't use master pages and of course you can use the encapsulating body tag to signify where you are but this isn't available with a masterpage.
Thanks R.
MasterPage though the name sound otherwise behaves like a child to a page that uses it.
Think of it as a UserControl to a page. You can actually access to the Page instance and it's Request property.
Here's an example on how you can use it
switch(Request.Path){
case "/page1/aspx":
//dosomething to your tabs
break:
case "/page1/aspx":
//dosomething to your tabs
break:
.
.
.
default:
//dosomething else
.
.
.
}
If you want to change the content on the masterpage from the page (i.e. change the tab color) you should:
In the masterpage, publicly expose a property or method that will change the color of the tab.
i.e.:
public void changecolor(string PageName, string Color){
switch(PageName){
case "home":
this.TabHome.Color=Color;
}
}
Then put a directive at the top of the aspx page with the masterpage path. Like such:
<%# MasterType VirtualPath="~/Site.master" %>
Once this is done, from the codebehind, you can access the masterpage and see its exposed method, then just call this and you're done.
protected void Page_Init(object sender, EventArgs e){
Master.changecolor("home", "red");
}
this way, you won't have to parse pagenames and deal with the maintenance that comes when you try to change the name of the page etc. you will also limit your case statement to the number of tabs, and not the number of pages in your site.
Create the following method in your masterpage (or helper class) and then add a reference to it in your Page_Load method in the masterpage:
public string GetCurrentPageName()
{
Uri uri = Request.Url;
string[] uriSegments = uri.Segments;
string pageName = "";
if( 0 < uriSegments.Length )
{
pageName = uriSegments.Last();
}
return pageName;
}
}
That should give you the current filename - you might want to strip out the ".aspx" part of the filename also. I haven't tested this with a QueryString yet so not sure if Last() still returns the filename in that case.
If your tabs are asp.net controls, you can use FindControl() to find the tab - you'll need to match your tab ids with your page names of course. Once you have the control you can add a "selected" style in code-behind.
I am trying to use the ASP.NET (3.5) "Routing Module" functionality to create custom pages based on the contents of the URL.
Various articles explain how to use ASP.NET Routing to branch to existing pages on the web server.
What I would like to do is create the page on-the-fly using code.
My first attempt looks like this:
public class SimpleRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string pageName = requestContext.RouteData.GetRequiredString("PageName");
Page myPage = new Page();
myPage.Response.Write("hello " + pageName);
return myPage;
}
}
But this throws an HTTPException saying "Response is not available in this context." at the Response.Write statement.
How to proceed?
UPDATE: In the end, I went with an approach based on IHttpModule, which turned out to be rather easy.
You can't write to the response from an IRouteHandler - it's way too early during the request life cycle. You should only write to the response from within the IHttpHandler, which is what the Page is.
As is shown in other examples, you'll have to get a page instance from somewhere that has all the necessary content.
Here's how you can load an existing page:
Page p = (Page)BuildManager.CreateInstanceFromVirtualPath("~/MyPage.aspx");
Or you can create one from scratch:
Page p = new Page();
p.Controls.Add(new LiteralControl(
#"<html>
<body>
<div>
This is HTML!
</div>
</body>
</html>"));
Instead of trying to write directly to the response, you might want to simply add controls to the page. Since the page is brand-new and has no markup, you may have to add all of the HTML elements to make it legal HTML in order to get it rendered correctly. Having never tried this, I have no idea if it will work.
Page myPage = new Page();
page.Controls.Add( new LiteralControl( "hello " + pageName ) );
return myPage;
It's not clear to me that this will have the required HTML, HEAD, and BODY tags. It might be better to create a base page that has skeleton markup that you can just add your controls to and use the BuildManager as in the example to instantiate this page, then add your controls.
Put requestContext before Response.Write, so requestContext.Response.Write