I'm looking to execute code in my code behind on my Masterpage, and use it on the .aspx page of child pages like Default.aspx, without having to call it through the Default.aspx.cs page.
This is my attempt by accessing it like so <% MasterPage.getPlanCost() %>, however, this does not work. As there's "no definition" for getPlanCost()
Master Page code behind:
public string getPlanCost()
{
var country = getCountry();
string gbp = "£5.99";
string euro = "€6.99";
string usd = "$8.99";
var currencyCost = usd;
if (country == "United Kingdom") // gbp
{
currencyCost = gbp;
}
else if (country == "United States" || country == "Canada" || country == "Australia" || country == "New Zealand") // usd
{
currencyCost = usd;
}
else // euro
{
currencyCost = euro;
}
return currencyCost;
}
Default.aspx page:
<p class="text-center under-title text-muted"><%=MasterPage.getPlanCost() %> Cancel Anytime.</p>
What is the quickest / most efficient way of achieving this? Furthermore, I have tried to use alternate methods seen on StackOverflow, using get and set however I was unable to get this working. Fairly new to C# so I apologise.
Although you have found a workaround, it is possible to access master page methods from child web forms, useful in cases where want your child page to affect the master page in some way. You can do this through the Page.Master property, but you will first have to register the type or cast it.
Method 1: Registering Master Type
Web Form:
<%# Page Language="C#" MasterPageFile="~/Example.Master" ... %>
<%# MasterType VirtualPath="~/Example.Master" %>
Code Behind:
Page.Master.getPlanCost();
Method 2: Casting Master Property
Code Behind:
((Example)Page.Master).getPlanCost();
To anybody wondering, I created a class called Utilities.cs
Then called it directly from here from my Default.aspx page instead.
<%=Utilities.getPlanCost()%>
I'd also like to thank #Joel Coehoorn for his comments which got me halfway there.
Related
I have been searching the internet and most I find resolves the issue of accessing the master page properties from the user control's code behind. But I am unable to find a solution where the user control can have access to the master page's properties within the markup.
Background:
The master page dynamically adds user control onto the page.
The master page has two properties which the user control needs to access via markup.
Here is some code to represent my problem:
Master page's code behind properties:
public IModule Module
{
get
{
return MyContext.Current.Module;
}
}
public IDictionary<string, object> Arguments
{
get
{
return MyContext.Current.Arguments;
}
}
Master page dynamically adds to control in code behind (it HAS to be dynamically added in master page's code behind):
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!(Page is VehicleForm) && !(Page is VsrManageForm) && !(Page is VpbManageForm))
{
MenuTab view = (MenuTab)this.LoadView(plhMenu, "~/Controls/MenuTab.ascx", "", MyContext.Current.Module);
}
}
User control's markup:
<web:FlowLink class="tools__lnk" arguments="<%# Arguments %>" id="flowLink1" runat="server" contextmodule='<%# Module %>' flowcall="FavouritesView" title="" rel="nofollow" ClientIDMode="Omitted">Shortlist</web:FlowLink>
<web:FlowLink class="tools__lnk" arguments="<%# Arguments %>" id="flowLink2" runat="server" contextmodule='<%# Module %>' flowcall="CompareView" title="" rel="nofollow" ClientIDMode="Omitted">Compare</web:FlowLink>
<web:FlowLink class="tools__lnk" arguments="<%# Arguments %>" id="flowLink5" runat="server" contextmodule='<%# Module %>' flowcall="UserView" title="" rel="nofollow" ClientIDMode="Omitted">Account</web:FlowLink>
Error:
Compiler Error Message: CS0103: The name 'Arguments' does not exist in the current context
Question:
How do I access <%# Arguments %> and <%# Module %> master page properties from the user control?
It might be possbile (have not tested it though) to do something like this:
arguments="<%# ((MasterPageType)this.Page.Master).Arguments %>"
Although it does not look right. You might want to redesign the way you control gets the data. Or atthe very least do the same somewhere in code behind and verify whether a current masterpage is of an expected type.
Update. The final solution that OP used incorporated ideas above, and resulted in having properties like below declared in the control:
public IDictionary<string, object> Arguments
{
get
{
MasterPageType master = this.Page.Master as MasterPageType;
if (master != null)
{
return master.Arguments;
}
else
{
return null;
}
}
}
I want to update master page hyperlinks from child page. Here is the code i written to update
master page elements.
HyperLink h1 = this.Master.FindControl("AnLogin") as HyperLink;
h1.NavigateUrl = "#";
h1.Text = Session["UserName"].ToString();
HyperLink h2 = this.Master.FindControl("AnLogout") as HyperLink;
h2.Text = "Logout";
h2.NavigateUrl = "~/Logout.aspx";
if (Session["UserType"].ToString() == "Admin")
{
Response.Redirect("~/Admin.aspx");
}
Master page is updating only when i am not redirecting to another page. If i am redirecting to another page, that hyperlinks remain same as static.
Here i need to update master page hyperlinks that should be same for all pages further i can traverse. How to accomplish this?
Here i suggest not to post back the page for such small operations.
You can set this condition on aspx page like :-
<% if (Session["UserType"].ToString() == "Admin") {%>
// do something
<%} else { %>
// do something
<%} %>
I have a master page:
<%# Master Language="C#" AutoEventWireup="true" Codefile="AdminMaster.master.cs" Inherits="AlphaPackSite.MasterPages.AdminMaster" %>
Then I have a public variable:
public partial class AdminMaster : System.Web.UI.MasterPage
{
protected bool blnShowDialogue = false;
In my content page I would like to set this variable:
blnShowDialogue = true;
So that in my master page I can have the code:
$(function() {
<%if(blnShowDialogue == true){%>
$("#dialog").dialog();
<% } %>
}
Does this make sense? When I try combinations of Master.blnShowDialogue, or blnShowDialogue = , etc etc nothing seems to work.
The name 'blnShowDialogue' does not
exist in the current context
Use #MasterType directive, as explained here:
http://msdn.microsoft.com/en-us/library/c8y19k6h.aspx
You need to cast the Master page to the actual type.
((AdminMaster)Master).blnShowDialogue = "Foo";
Otherwise Master will simply be referring to the base class Master - you're trying to access a property in your actual class which derives from the Master class.
The error you are getting is because a property called blnShowDialogue does not exist in the class System.Web.UI.MasterPage - which makes sense, as you're not telling it which specific MasterPage instance you are trying to refer to.
Hope that helps.
What I would like to do, is be able to pass two attributes to a user control, a ListName and a Permission, like so:
<uc:check id="uc" List="Shared Documents" Permission="OpenItems" runat="server">
<!-- have some HTML content here that is rendered if the permission is true -->
</uc:check>
Then in the actual check user control, have something similar to:
<%# Control language="C#" ClassName="check" %>
<%
// determine permission magic placeholder
if (DoesUserHavePermissions(perm))
{
// render nested HTML content
}
else
{
// abort rendering as to not show nested HTML content
}
%>
I have read the page on creating a templated control on MSDN, and while that would work - it really seems to be a bit overkill for what I am trying to do. Is there a control that already renders content based on a boolean expression or a simpler template example?
http://msdn.microsoft.com/en-us/library/36574bf6.aspx
Update:
The following code can be used in the ascx to model a very simple version of this:
<%# Control Language="C#" ClassName="PermissionCheck" %>
<%# Import Namespace="System.ComponentModel" %>
<script runat="server">
void Page_Init()
{
if (Allowed != null)
{
Panel container = new Panel();
Allowed.InstantiateIn(container);
PermissionBasedMessage.Controls.Add(container);
}
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Allowed { get; set; }
</script>
<asp:Placeholder runat="server" ID="PermissionBasedMessage" />
Note: I oversimplified the check in the Page_Init method for this sample code. Additional logic checks can be added as needed.
And reference it in the calling HTML page:
<%# Register src="PermissionCheck.ascx" tagname="PermissionCheck" tagprefix="uc1" %>
<uc1:PermissionCheck ID="PermissionCheck1" runat="server">
<Allowed>Allowed Access</Allowed>
</uc1:PermissionCheck>
You could create a custom control instead of a user control: derive from the asp.net panel, add your two properties, then only render the control if the user has the required permission. E.g. something like this:
The control (put this in App_Code for example):
namespace MyControls
{
public class MyPanel : Panel
{
public string Permission { get; set; }
public string List { get; set; }
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if (UserHasPermission()) base.Render(writer);
}
}
}
Using the control:
<%# Page ... %>
<%# Register Namespace="MyControls" TagPrefix="mc" %>
<html>
...
<mc:MyPanel runat="server" List="Shared Documents" Permission="OpenItems">
put content and/or other controls here
</mc:MyPanel>
...
Why don't you extend the LiteralControl, add properties for your settings, then render html to the .Value of the LieralControl? Seems pretty simple and a lot less of a headache than using Templated controls
The other answers are good for the generic form of your question, but for checking permissions SPSecurityTrimmedControl might do what you need.
Wrap your content with a place holder control and set the control's visibility to true or false (controls that have .Visible = false won't render any html)
<asp:PlaceHolder id="phWrapper" runat="server">
...
</asp:PlaceHolder>
Then in your code-behind set phWrapper.Visible = DoesUserHavePermissions(perm);
Hope that helps!
In my web app (asp.net C#) I have menus as "All", "Education", "Fun", "Comedy". I want when I select All then it should be displayed as current menu, for which I have a CSS class current.
In case of WebUserControls I can do it easily by passing parameter of current page to select as below:
mywebpage.aspx
<uc:header ID="header1" runat="server" selectedMenu="comedy" />
header.ascx (code (c#))
public string selectedMenu
{
get { return strSelected; }
set { strSelected = value; }
}
header.ascx (html)
<ul>
<li><a href="/all/" title="All Videos" <%if (strSelected == "all"){%>class="current"<%} %>><span>All</span></a></li>
<li><a href="/fun/" title="Fun Videos" <%if (strSelected == "fun"){%>class="current"<%} %>><span>Fun</span></a></li>
<li><a href="/comedy/" title="Comedy Videos" <%if (strSelected == "comedy"){%>class="current"<%} %>><span>Comedy</span></a></li>
</ul>
When I'll pass comedy from my webpage to usercontrol then it will select comedy menu. I want to implement the same kind of functionality in case of master pages, could anyone tell me how to achieve this type of facility for master pages.
One way what I feel is to pass a query string parameter http://example.com/all/?select=all, I'll check on master page_load function if select parameter is "all" or fun or comedy then select corresponding menu. But this is not good, because I don't want to add an extra query string parameter to my URLs.
Please tell me how to solve this issue.
Thanks
You can access master page properties from your content page after casting the master to the correct type:
public class MyMasterPage : MasterPage
{
public string MyMenuProperty { get; set; }
protected void Page_PreRender(object sender, EventArgs e)
{
if (MyMenuProperty == "comedy")
{
/* do your menu stuff */
}
}
}
public class MyContentPage : Page
{
protected void Page_Load(object sender, EventArgs e)
{
var myMaster = Page.Master as MyMasterPage;
if (myMaster != null)
{
myMaster.MyMenuProperty = "comedy";
}
}
One way i have done simular in the past is add this to the page derivatives of any content pages:
<%# MasterType VirtualPath="~/YourMaster.master" %>
Then in the master i exposed this:
private PageTypes currentPageType;
public PageTypes CurrentPageType
{
get { return currentPageType; }
set { currentPageType = value; }
}
On this job this was used so the master knew what type of page it was on and therefore changed a few things, colours, controls etc. So from a contents pageload i did
Master.CurrentPageType = PageTypes.System;
One thing to note however, VS tends to moan about the MasterType derivative until you do a rebuild all.
I'm thinking that maybe a completely different approach might be easier to implement and maintain.
How about you just parse the URL in your header.ascx?
For example:
<li><a href="/all/" title="All Videos" runat="server" class='<%= Request.Url.ToString().Contains("/all/") ? "current" : "" %>' ><span>All</span></a></li>
That way, you won't have to worry about setting properties, accessing/casting master pages etc...
Hai prashant,
I had the same issue a month back and i posted in stack overflow check this one it may help you Find a UnorderedList <UL> control inside a master page from a content page in asp.net