Copy placeholder text into a 2nd location - c#

I have an MVC Masterpage.
Within the body, I have a placeholder for a title that all the views using this masterpage populate:
<asp:ContentPlaceHolder ID="TitleContent" runat="server" />
But as well as this title being used how it is, I want the exact same text to go in the title section of the head tag.
Of course, I could use another placeholder and make every single view specify the same content twice, but it would be better if some code could magically copy the literal text out of the placeholder and put it into the head title tag as well.
Obviously Javascriptis no use, because google wont process it to the page title. So I need to do this serverside.

In general, you would bind these values in the view to data either on a model or perhaps in a ViewBag (or ViewData for older versions of MVC) or something of that nature. So in your Layout (Master Page? Must be an older version of MVC?) you might have a couple of references to a ViewBag (or ViewData) value. Something like this:
<html>
<head>
<title><%= ViewBag.PageTitle %></title>
</head>
<body>
<div id="somePageTitle"><%= ViewBag.PageTitle %></div>
</body>
</html>
or:
<html>
<head>
<title><%= ViewData["PageTitle"] %></title>
</head>
<body>
<div id="somePageTitle"><%= ViewData["PageTitle"] %></div>
</body>
</html>
Then in your controller you would set that value as needed:
ViewBag.PageTitle = "This is a page title";
or:
ViewData["PageTitle"] = "This is a page title";
That would bind that value to both locations in the view. It's more common to use ViewBag (or other constructs, like ViewData and TempData, often depending on the MVC version being used) for elements in the layout (Master Page) and to use view models for elements in the specific view.

First off David's answer is right
Actual implementation would be whatever.master
<!DOCTYPE html>
<html>
<head>
<title><%= ViewData["Title"] %></title>
</head>
<body>
<asp:ContentPlaceHolder ID="TitleContent" runat="server"/>
</body>
</html>
In your View
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
<%= ViewData["Title"] %>
</asp:Content>
Change it in the controller
public ActionResult Index()
{
ViewData["Title"] = "My new title";
return View();
}
Or set it in the View itself
<script runat="server">
ViewData["Title"] = "My new title";
</script>
<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
<%= ViewData["Title"] %>
</asp:Content>
Since these are variable, use them anywhere in your page you like
// These are the same
ViewData["Title"] = "My new title";
ViewBag.Title = "My new title";
// These are the same
<%= ViewData["Title"] %>
<%= ViewBag.Title %>
public Dictionary<string, object> ViewData
public dynamic ViewBag // .NET 4.0 +

Thanks for all your help.
I wanted to set the data in the view because I have different controllers using the same view, and also some controllers returning different views depending on the logic, so it made sense to define the page title on the view where it is a known entity, especially since it is usually not model data and is thus always a constant text for that page.
One complication, is that if the view was to be set as a dynamic piece of data taken from the model, that hadn't been calculated yet (such as a deferred execution iqueryable), then the masterpage never realizes the value unless you populate it in the view at a higher point in the page.
In other words, the view has to set the viewdata in script in a content placeholder ABOVE where it will be in the masterpage. You cannot set the viewdata[] property in the body content if the masterpage uses it in the head section.
This works:
<head>
<asp:Placeholder ID="HeadContent" runat="server"/>
<title><%: ViewData["PageTitle"] %></title>
</head>
<body>
<%: ViewData["PageTitle"] %>
</body>
Then in the view you can set the title:
<asp:Content ContentPlaceHolderID="HeadContent" runat="server">
<% ViewData["PageTitle"] = Model.SomeValueThatHasDefferedExecution; %>
</asp:Content>

Related

How ASP.net is used before Razor was introduced

I am a little confused in how ASP.NET code is written before Razor was introduced. All I can see in many pages on the internet is how Razor is used with ASP.net. I want to know how ASP.net code is been written without Razor.
classic ASP
<html>
<body>
<%
response.write("My first ASP script!")
%>
</body>
</html>
ASP.NET with Razor
<html>
<body>
<h1>Hello Web Pages</h1>
<p>The time is #DateTime.Now</p>
</body>
</html>
ASP.net without Razor???
basically I want to know how people coded in ASP.net (not classic ASP) before razor was introduced.
Classic ASP is usually written with <%= %> tags, not with response.write(). Example:
<html>
<body>
<%= "My first ASP script!" %>
</body>
</html>
The ASP.NET syntax is very similar, but the <%: %> tag was introduced to automatically HTML encode the values, similar to what Razor does. Example:
<html>
<body>
<h1>Hello Web Pages</h1>
<p>The time is <%: DateTime.Now %></p>
</body>
</html>
For code more complicated than just showing values, you use <% %> tags around server code, just as in classic ASP. Example:
<html>
<body>
<h1>Hello Web Pages</h1>
<% for (int i = 1; i <= 10; i++) { %>
<p>Line <%: i %></p>
<% } %>
</body>
</html>

What is the PROPER way to create an ASPX View in MVC?

Essentially, my issue is this: I'm trying to display a ViewData variable on an ASPX page, but I'm getting "ViewData does not exist in the current context."
What led me here? I'm new to MVC, and am following an online tutorial. In Lesson 1, he has us create a view by going to Add > View, which creates a Razor view. Then, in the next tutorial, he's teaching us to use ViewData to pass a variable to the view. But, when he displays it, he's doing so using the <%: %> method, which doesn't work on my Razor page. So, I try to create an ASPX page in my View folder by creating a Web Form the traditional way. When I do that, I get the error mentioned above. I have successfully figured out how to get the Razor method working in my cshtml page, but what is the appropriate method should I want to do it the "angle bracket - percent" way?
Edit: Basically, all I did was follow the instructions for Tutorial 2 in the following walk-through. He doesn't really explain HOW he created the ASPX page (or that he used an ASPX page at all). If anyone knows of a better tutorial that's more complete, I'm all ears.
http://www.codeproject.com/Articles/207797/Learn-MVC-Model-View-Controller-step-by-step-in#Lab1:- Creating a simple hello world ASP.NET MVC Application
Edit2: By request, here's my code:
ASPX:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MVCLearn.Views.FirstMVC.Index" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= ViewData["vwTest"] %>
</div>
</form>
</body>
</html>
And here is my Controller:
public class FirstMVCController : Controller
{
// GET: FirstMVC
public ActionResult Index()
{
ViewData["vwtest"] = "Something";
return View();
}
public ActionResult SayHello()
{
return View("HelloView");
}
}
<%= ViewData["vwTest"] %>
ViewData["vwtest"] = "Something";
vwTest != vwtest
You should write same name
<%= ViewData["vwTest"] %>
ViewData["vwTest"] = "Something";

Where are navigation elements declared in default Web Forms template?

VERY very basic question. I'm trying to learn ASP.NET. I created a default website1 in VS 2013 Community I get a ton of files. When I run the app in IS, the default.aspx web page appears and all is OK, but above the web page is a banner with links to contact.aspx, login.aspx. register.aspx, etc. and I cannot find where that banner is? It's not on default.aspx. Where is it? Seaching the project for "Contact.aspx" only returns one result, the page itself, as an example.
It's probably coming from a Master Page. Look at the <%# Page %> header at the tops of the .aspx files. You'll see they reference a master page. A Master Page is used to provide structure to the site. It means you don't have to write the same HTML for common elements on every single content page. Content pages (.aspx) then can have their content inserted into the Master Page. And yes, you can nest master pages. This is all done through the <asp:ContentPlaceHolder /> (higher level Master Page) and <asp:Content /> (nested Master Page or Content Page) tags.
Let's look at an example:
MasterPage.master
<%# Master Language="C#" %>
<!DOCTYPE html>
<html>
<head runat="server" >
<title>Master page title</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder id="Main" runat="server" />
</div>
<div>
<asp:ContentPlaceHolder id="Footer" runat="server" />
</div>
</form>
</body>
</html>
Default.aspx
<%# Page Language="C#" MasterPageFile="~/MasterPage.master" Title="Content Page 1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Main" Runat="Server">
Main content here.
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Footer" runat="Server" >
Footer content here.
</asp:Content>
The resulting HTML will look like this on the client when you access Default.aspx:
<!DOCTYPE html>
<html>
<head>
<title>Content Page 1</title>
</head>
<body>
<form id="ContentPage_form1">
<div>
Main content here.
</div>
<div>
Footer content here.
</div>
</form>
</body>
</html>
Take special note of how the ID of the form changed from the server side to the client. This trips a lot of people up when they start doing client side JavaScript. If you want the ID to not change, you have to add the ClientIDMode="Static" attribute to the control (you can also set it at page, web.config, or machine.config levels).

How to call view as full page (ignoring render body)?

I have a regular application _Layout.cshtml and #RenderBody() to render all views inside, but only for the Login view need to be render as full page not inside #RenderBody().
Regards
You need to set the Layout property to null at the beginning of your view.
So, your Login.cshtml file should start with:
#model YourModel
#{
Layout = null;
}
You may not want to have no layout for your view. You probably want a custom layout (something like _LayoutFullPage.cshtml
<!DOCTYPE html>
<head>
<title>SOMETHING HERE ALONG WITH OTHER HEAD ATTRIBUTES</title>
</head>
<body>
#RenderBody()
</body>
</html>
and then use that layout in the view with
#{
Layout = "~/Views/Shared/_LayoutFullPage.cshtml";
}
Other options are to set the view as null in the cshtml (as suggested by RePierre) or to call return PartialView(model); within your controller.

Referencing Page.Title after it has been set as part of a asp:contentplaceholder

I've got a master page setup with a contentplaceholder control inside the title tag as so:
<head id="head1" runat="server">
<style type="text/css">
body { font-family: Tahoma; font-size: 9pt; }
</style>
<title><asp:contentplaceholder id="title" runat="server" /></title>
</head>
That contentplaceholder is implemented inside a page that uses that masterpage as so:
<asp:content runat="server" contentplaceholderid="title">
Welcome: <%= this.BasketID %>
</asp:content>
I'm trying to then get a copy of the substituted title inside the masterpage body (also tried inside the page - and this doesnt work either) like:
<p>
<strong>Subject:</strong> <%# Page.Title %>
</p>
In all cases Page.Title and Page.Header.Title are "" (I've tried both databinding and using the <%= %> syntax to no avail.
Does anyone know what is going on here and how I can overcome this?
Thanks.
The problem you're getting is because you are 'tricking' the page cycle. You'd better use this in the codebehind of the page:
Master.Title = "Welcome: " + basketId
You could do it this way however; on the masterpage: create a HtmlTextWriter, configure it to write to a MemoryStream. Render the 'title' contentplaceholder to the HtmlTextWriter, attach a StreamReader to the stream to grab the content as a string, and output this to your page. Yet, this is not efficient, and way too much work :-)

Categories

Resources