I am designing a page which needs to have boxes (partial views) on both the left and the right side of the main content. The boxes will contain extra information just like on SO. I would like to group the pages, so certain pages will have some boxes, and pages of another group will have other boxes.
I am though in doubt how this is best accomplished in MVC.NET.
I see two options:
1) On every page I include the partial controls I need.
2) Create sub-master pages where I can assign a page to, and which can control which partial views should be shown.
Are there any other ways of doing this, which would be smarter or easier to implement?
Boxes on SO pages are strictly related to content of the page, so I would create one master page with 3 content placeholders (Site.Master):
<asp:ContentPlaceHolder ID="LeftContent" runat="server" />
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
<asp:ContentPlaceHolder ID="RightContent" runat="server" />
If you had some range of functionalities, that have the same boxes, I would create master page for them and place something like (Controller.Master):
<asp:Content runat="server" ContentPlaceHolderID="RightContent">
<% Html.RenderPartial("RelatedTagsInfo", ViewData['RelatedTagsInfoModel']) %>
<% Html.RenderPartial("RelatedQuestionsInfo", ViewData['RelatedQuestionsModel']) %>
<asp:ContentPlaceHolder ID="RightContentSubcontent" runat="server" />
</asp:Content>
Actions using Controller.Master would place additional boxes in RightContentSubcontent.
If boxes are really independent of current page, you can also use RenderAction:
<asp:Content runat="server" ContentPlaceHolderID="RightContent">
<% Html.RenderAction("RelatedTagsInfo", "Question", new { id = Model.Id} ) %>
<% Html.RenderAction("RelatedQuestionsInfo", "Question", new { id = Model.Id} ) %>
<asp:ContentPlaceHolder ID="RightContentSubcontent" runat="server" />
</asp:Content>
RenderAction creates new request to render part of the page. It may be easier to use, but I would use RenderAction for boxes, that do not share any information with the main view (for example if you wanted to display "Clock" box, "Latest downloads" box or "Login" box).
There are many ways to put content into sidebars on pages...
Build different master pages, each containing a different subset of sidebar content. I would use RenderAction for this and not RenderPartial, that way you do not have to worry about having each ActionResult in your MVC Solution be responsible for sending content to these partials.
set up a single RenderAction in the Master page and in the ActionResult for the RenderAction, have it inspect the calling Controller and/or the ActionResult (all contained in the HttpContext). Based on that you can send back content conditionally, and render it in the partial view conditionally.
Related
I am using ASP.NET MVC 2 & 3 with aspx View not Razor View, my question is:
How to set the title in Site.Master page? I wish every pages which use Site.Master page can add a Master title follow the page title show like: "Index -MasterTitle" ; "About -MasterTitle".
I've try in Site.Master page and it's doesn't work:
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" />
-MasterTitle
</title>
so I try to use asp:Literal server control:
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" />
<asp:Literal runat="server">-MasterTiltle</asp:Literal>
</title>
Or:
<title><asp:ContentPlaceHolder ID="TitleContent" runat="server" />
<asp:Literal runat="server" Text="-MasterTiltle"></asp:Literal>
</title>
fine, it's solve the problem, but later I want to load the value of MasterTitle from web.config, I've try:
<asp:ContentPlaceHolder ID="TitleContent" runat="server" />
<asp:Literal runat="server">
<%: System.Web.Configuration.WebConfigurationManager.AppSettings["SiteTile"] %>
</asp:Literal>
</asp:Literal>
compiler toled me a server control can't contain a child control, so I try the other:
<title>
<asp:ContentPlaceHolder ID="TitleContent" runat="server" />
<asp:Literal ID="ltlTitleBack" runat="server" Text='<%: System.Web.Configuration.WebConfigurationManager.AppSettings["SiteTile"] %>' >
</asp:Literal>
</title>
it's compiler ok but not the answer what I want cause it show: "pagetilte <%: System.Web.Configuration.WebConfigurationManager.AppSettings["SiteTile"] %>"
and later I found a way can solve this problem here: CodeExpressionBuilder
but I think that is not a proper solution cause I should set too many things that not relate to ASP MVC. Is there any better solution can solve this problem?
Note:
I don't want set the value of MasterTitle in every pages not Site.Master page, that's a stupid way.
I don't want set the value of MasterTitle in Controller or Action or Model, that's not right.
I don't want set the value of MasterTitle via ViewData.
I don't want to use CodeExpressionBuilder.
I'm not use Razor View.
thanks for any help.
Edit: Actually I want something like web.config so I can change the value of MasterTitle when server is running. :)
I had similar issues and here is what I had to use:
<title>
<asp:ContentPlaceHolder ID="TitleContent" runat="server" /><%= "-MasterTitle" %>
</title>
You should use your Resource files for this kind of text...
http://msdn.microsoft.com/en-us/library/ms227427.aspx
Not only does it let you set the text in a nice central place, but it is designed for this exact purpose - it will also make it easier for your to create regional language versions of your website later on!
I have a series of nested master pages, like so:
site.master:
<asp:ContentPlaceHolder ID="SearchFormContent" runat="server">
<%Html.RenderPartial("SearchFormControl"); %>
</asp:ContentPlaceHolder>
in the nested (child) master page, area.master
<asp:Content ContentPlaceHolderID="SearchFormContent" ID="SearchFormContentContainer" runat="server">
<asp:ContentPlaceHolderID="SearchFormContent" runat="server"/>
</asp:ContentPlaceHolder>
I have two separate content pages. One wants to add its own content to SearchFormContent, the other would like to keep the content that was defined in the top-level master page. Of course, since the child master page defines content for the SearchFormContent block so that the child pages can potentially access it, the content defined in the top level master page is obliterated.
Any way to do this?
I can't think of any way other than having the following in your child master page
<asp:Content ContentPlaceHolderID="SearchFormContent" ID="SearchFormContentContainer" runat="server">
<asp:ContentPlaceHolder ID="SearchFormContent" runat="server">
<%Html.RenderPartial("SearchFormControl"); %>
</asp:ContentPlaceHolder>
</asp:ContentPlaceHolder>
Nasty I know, but its the only way I can think of when using master pages.
HTHs,
Charles
Remove all your ContentPlaceHolders and leave the SearchFormControl directly on the site.master. If you never want to override the SearchFormControl then you don't need to define the ControlPlaceHolders
you can put content in the contentPlaceHolder on the masterpage. that will be rendered by default if you don't override the with a content on a child page.
Lately when I've been building my asp.net mvc apps I tend to have a number of items that consistently need to be calculated, formatted and configured in my master pages. Some of these items include:
I like to attach specific classed to the body tag like WordPress does to help my CSS out. I usually attach the name of the action, controller, page template, etc.
I like to work with a custom IIdentity in my master pages. This IIdentity includes the users nice Display Name, UserID, UserName, etc.
etc... depending on the project
The way I've gone about accomplishing this has evolved as well. I started out by sending ViewData along with every action result to populate things in the master page. example->
// in the action
ViewData["BodyClasses"] = "index home default";
ViewData["UserData"] = userData;
return View();
// in the master page
<% UserData userData = (UserData)ViewData["UserData"] %>
...
<body class="<%= (string)ViewData["BodyClasses"] %>">
That was horrible. So I started putting some variables at the top of my master pages and populating them based on the objects we have to work with in the master page. example ->
<%# Master Language="C#" Inherits="System.Web.MVC.ViewMasterPage" %>
<% string controller = ViewContext.RouteData.Values["controller"].ToString().ToLower();
string action = ViewContext.RouteData.Values["action"].ToString().ToLower();
CustomIdentity identity = (CustomIdentity)User.Identity %>
...
<body class="no-js <%= controller + " " + action %>">
That's better but I feel like there has to be an easier solution. I started playing around with creating a custom ViewMasterPage and adding some public properties. Is anyone else doing this with the master page or is there another solution to this that I'm completely missing?
I've used just regular content placeholders for body tag id's and classes.
<body id="<asp:ContentPlaceHolder ID="BodyTagId" runat="server" />">
Then use it in the given page that references the master page:
<asp:Content ContentPlaceHolderID="BodyTagId" runat="server">about-page</asp:Content>
i see that this question has been answered:
Are there nested master pages in ASP.NET MVC?
but i have a follow up questions, if i have nested master pages:
site.master
section.master
page
where page has a master of section.master and section.master itself has a master of site.master
can i refer to sections in both section.master and site.master?
or maybe the better questions is that i would like to the do the following and when i try to reference a section in site.master i get "can't find content section.
any suggestions?
i see examples where the page references section.master but i can't find any examples where page references site.master. For example: http://msdn.microsoft.com/en-us/library/x2b3ktt7.aspx
I believe you cannot reference content of parent master page if the page has child master page set.
Instead you can chain the content from child master to parent. Like this:
Top.Master:
<asp:ContentPlaceHolder ID="TopContent" runat="server" />
Child.Master:
<asp:Content ContentPlaceHolderID="TopContent" ID="childContent1" runat="Server">
<asp:ContentPlaceHolder ID="ChildContent" runat="server" />
</asp:Content>
Page.aspx:
<asp:Content ContentPlaceHolderID="ChildContent" ID="pageContent1" runat="Server">
<p>This will go to the Top.Master through Child.Master</p>
</asp:Content>
I have a page composed from multiple partial asp.net mvc views rendered dynamically.
How can I register in the header of the page some javascript files based on what is needed on on each partial view?
I set up a ContentPlaceHolder in the header of the master page for the view. In the view, I include both the header and body content place holders and add my javascript includes in the place holder corresponding to the header. I typically don't add the javascript include to the partial view itself since I (too) want it to appear in the html head element. I just make sure to include all the javascript files that all of my partials will need in the view that includes them. I will, often, include inline script in the partial view itself though you need to be careful with this if the partial can be embedded multiple times.
View Code:
<asp:ContentPlaceHolder ID="headerContent"
ContentPlaceHolderID="Header"
runat="server">
... javascript includes go here...
</asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="bodyContent"
ContentPlaceHolderID="Body"
runat="server">
... body content goes here...
<% Html.RenderPartial( "PartialView1", Model, ViewData ); %>
<% Html.RenderPartial( "PartialView2", Model, ViewData ); %>
</asp:ContentPlaceHolder>