I have an asp.net content page which is used inside of a master page (with header, menu and some links). I would like to reuse it in a different context without the master page (to not display the header and menu there), or with an empty master page if this is somehow possible. I don't want to violate DRY principle by taking the whole page and creating a standalone clone of it for obvious reasons. Is this somehow possible ?
Yes, you can set the master page dynamically in the content pages Page_PreInit method:
private void Page_PreInit(object sender, EventArgs e)
{
this.MasterPageFile = "MyMasterPage.master"
}
Set up some logic to dynamically choose which master page filename to pass in, and you are now sharing one content page with many master pages.
How about wrapping-up the shared content in a user control?
A user control is a kind of composite
control that works much like an
ASP.NET Web page—you can add existing
Web server controls and markup to a
user control, and define properties
and methods for the control. You can
then embed them in ASP.NET Web pages,
where they act as a unit.
Related
I received a new requirement today: For our product page, they want a completely different layout to be used based on the product type.
For example, say we sell buckets. Currently, all buckets use the exact same page layout. But now, they want wooden buckets to use the current layout, and plastic buckets to use a completely different layout. However, they want the URLs to stay the same (e.g., domain.com/bucket/1), so I can't just forward plastic buckets to a new page.
The current page structure is as follows:
CurrentMasterPage.master > CurrentProductPage.aspx > Several UserControls
The new layout requires new pages (i.e., none of the current ones are reused):
NewMasterPage.master > NewProductPage.aspx > Several UserControls
My first thought was to take all of the markup and code from CurrentProductPage.aspx and put it into a UserControl, then create a second UserControl for the new layout (NewProductPage.aspx), and have CurrentProductPage.aspx dynamically load the appropriate UserControl based on the product type, however, this doesn't work because the new layout requires a new MasterPage, and I can't reference a MasterPage from a UserControl.
Then, I thought about using URL Rewriting, but I don't think it's possible to have the same URL load two different pages.
Is there any way to accomplish this?
Why not use a 100% server side re-direct?
When you use response.Redirect("some different page"). Then the client side browser is sent a whole new copy of that page, and the URL will be updated.
However, the server side can write any page it wants to. The client side will not even know the server decided to dish out a different page for the given URL.
So, you could have a page with fake tabs as buttons. When the user hits a button, the browser round trip starts (for the given URL). But on server side, you can then dish out a different page for that URL.
So, in place of this classic "round trip", you can use:
Server.TransferRequest("MyotherWebPage")
So, for the given URL, before the current page (based on given URL) is sent down back to the browser, the above will simply pump out a different page. The current page will never make it back down to the browser.
In fact for a rich page with lots of buttons and features, you can change the page displayed. So in on-load - simply in place of a "response.Redirect", use a server.Transfer. The current page never makes it to the client - the one you dish out where. Because the client side has zero clue about what the web server decides to dish out - it will also have zero clue that a different page was send back to the client.
Try the above with a test page.
On page A, behind a standard button, jump to web page B
eg:
Response.Recdirect("MyPageB.aspx")
Note the URL change - classic round trip.
Now, do this with the button:
Server.Redirect("MyPageB.aspx")
In this case, no full round trip occurs. The server transfers directly to the new page and sends that out. (and note how your URL does NOT change).
You can change the Master Page on PreInit on the Page using a Master. This is possible because a Master is basically the same as a User Control and is loaded AFTER the page's code behind.
protected void Page_PreInit(object sender, EventArgs e)
{
if (NewProductPage)
{
MasterPageFile = "~/NewMasterPage.master";
}
}
I'm writing a website in Visual Studio Web Developer 2010 (Express edition). I have created a Master file which my content is styled with.
I want to put a right hand menu in my master file, but from the actual website pages, I want to say whether it should show particular menu items. For example, the home page would have a certain set of menu items on the right where as the contact page might have another set.
Should I set it up so that the master file handles true or false as to whether to show certain menu items (default all to false)... or should I handle this from the content pages? ie: call menu functions to draw from there?
You can add a master page declaration to the page, so that you can access it programmatically like so:
<%# MasterType virtualPath="~/MasterPage.master"%>
Put that right under the Page tag on the page you want to enable or disable access from.
Then, in your code behind, you can access the master page methods, one of which can be a method to enable or disable that side menu.
Something like:
Master.MyEnableMenuMethod();
Additionally, you can add that Master Page declaration dynamically, like so:
void Page_PreInit(Object sender, EventArgs e)
{
this.MasterPageFile = "~/MasterPage.master";
}
See http://msdn.microsoft.com/en-us/library/c8y19k6h(v=vs.85).aspx for more.
The way I've done this sort of thing is by putting some code withing the menu markup as so:
<% if(!HttpContext.Request.Path.Contains("Contact.aspx")) { %>
<li> Contacts</li>
<%}%}>
And so on...
I have two similar master pages, basically they are pretty extensive, but the difference relies in one using
common content
<form id="form1" runat="server" enctype="multipart/form-data">
common content
</form>
common content
and the other being
common content
<dn:Form id="form1" runat="server">
common content
</dn:Form>
common content
I was wondering how I could accomplish this, without having to create two master pages and just changing the form tags...
The way I currently though of doing this, is basically have one master page with the other content, a second one with the inner contents, and two others that just have the form tags and a placeholder inside them, and then dynamically choosing one master page over the other.
Is there a better way to do this or is this the correct way? thanks.
Update: I'm not sure my current idea is well expressed:
Base.master would have the outer contents, no inheritance.
Regular and Modified.master would have just the different form tags, both inherit from Base.Master
Shared.master would have the inner contents, inherit from Regular.Master and in case it requires the other form control, then it chooses the other master (which has the same ContentPlaceHolderID for FormContent), dynamically with something like this, maybe reading from web.config or the like
protected void Page_PreInit(object sender, EventArgs e)
{
this.MasterPageFile = "~/App_Shared/RegularWebForm.Master";
this.MasterPageFile = "~/App_Shared/UrlRewritableWebForm.Master";
}
The goal for this is being able to use the same Master page across three different applications for one same web domain.
The idea that my solution proposed would be that I have those four master page files in a given "App_Shared" folder, which is referenced via svn:externals from all the projects, so I don't have to repeat the code. The idea would be that I choose whether Shared.Master (which would be the functional base master page file for all three applications) uses the regular form or the user control in the current application, and that choice could be made by a setting in the web.config for the application.
In the master page code behind, you should be able to override OnInit (or OnLoad or in any number of other places) and determine when you need multipart encryption, and when you do, call:
Attributes.Add("enctype", "multipart/form-data");
Even better:
Expose a boolean property:
public bool EncodeMe {get;set;};
In each form that uses the master control set
Master.EncodeMe = true; // or false of course
then in the master page use the bool to determine whether or not to encode.
I've developed my own custom users and roles objects using ActiveRecord that do NOT extend the default Asp.Net providers and therefore I can't get the user from the HttpContext. I can create a custom htmlhelper to render menus but should my views render the menu or the master page?
If it's the master page how can I pass to the custom htmlhelper things like current user since some menu items depend on the user roles.
Also, how can I detect what controller is being viewed inside my master pages?
1) If your menu functionality is supposed to exist on multiple pages, then it makes sense to put it in the master page. If not, then the normal view.
2) A popular choice is to make all of your ViewModels inherit from a base view class, and then your Master page uses that. Example:
System.Web.Mvc.ViewMasterPage<ViewBase>
System.Web.Mvc.ViewPage<MyViewModel>
public class MyViewModel : ViewBase { }
3) You can pull out the specific controller from the route data. However, if you need specific functionality for certain controllers, I would just suggest using a different master page for those views than trying to make all of your views use the same master page.
In general, all ASP.NET controls (whether WebForms or MVC) should control their own state.
In the case of handling navigation, I'd say create a .ASCX (partial view) and place it on your master page. Let the partial view control how it is displayed based on the HttpContext.
From what I've already read this appears to be impossible, but I wanted to see if anyone out there has a secret trick up their sleeve or at least a definitive "no".
Supposedly a master page is really just a control for a content page to use, not actually the "master" of a content page. If I wanted to go from one content page, to another content page with the same master page, I would just say
Response.Redirect("PageB.aspx");
But this would immediately cause a postback, flickering the page, which is the crappy pre-ajax way of doing things.
In this current project, I'm trying to see if I could figure out how to change the current content page of a ContentPlaceHolder in the master page asynchronously, when a button is clicked on the master page.
Is this possible, if so how?
I don't know if you can between pages (.aspx) but it can definitely be done using UserControls.
ASP.Net pages each have their own URL so what you're trying to do is to go from one URL to another without any postback, that's just not how it's supposed to work.
Using user controls (.ascx):
Create a page that uses the MasterPage and use something like this in the content
<ajax:UpdatePanel ...>
<ContentTemplate>
<asp:PlaceHolder ...>
</ContentTemplate>
</ajax:UpdatePanel>
Search for UpdatePanel and tweak its settings to do what you want, then learn how to swap user controls in a placeholder.
No, you cannot because a master page is actually a control rendered on a particular aspx page, rather than actually containing the aspx page as it deceptively appears to be programmatically and in design view.
More Info:
You could however use a variety of other controls to simulate this effect. The asp:MultiView control is one example, each "page" could be made in a single view and placed in an update panel, thus allowing it to be switched asynchronously. Alternatively you could define each page in a separate user control and put those in an update panel, asynchronously switching the visible property on those controls as needed.
There are really a lot of different ways to achieve an effect similar to changing the master page's content placeholder.