I'm using html provided by a designer to create a master page.
The html doctype is set to be HTML 4.0 Strict. The meta tags in the html do not have closing end tags (they end with > rather than />) and this html is compliant using the W3 validator tool.
For example:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
However, ASP.NET changes the head attributes before rendering the page and modifies the end tags, as below
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Now the addition of the /> at the end of the tag causes errors in the W3 validator.
How do I prevent this from happening, and ensure the html rendered is as the designers intended?
You can change how ASP.NET renders HTML by forcing it to use a particular XHTML conformance rendering mode. I'm not sure what other side effects changing the renderer may have on the HTML output produced by ASP.NET. This can be set in the web.config with the following.
<system.web>
<!-- other elements here -->
<xhtmlConformance
mode="Legacy" />
</system.web>
There are other caveats to using the "Legacy" rendering mode, see the following MSDN resources for other rendering modes and details.
XHTML Standards in Visual Studio and ASP.NET
How to: Configure XHTML Rendering in ASP.NET Web Sites
Related
I started to learn xhtml as it's the first topic from the book I'm reading and tried creating a simple form to enter just a name.
This is half of what I copied from the book only keeping the input text field:
<?xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>Enter Customer Name</title>
</head>
<body>
<h:outputStylesheet library="css" name="styles.css"/>
<h:messages/>
<h:form id="test">
<h:outputLabel for="firstname" value="first name:"></h:outputLabel>
<h:inputText id="firstname" label="first name" value="#{test.firstname}" required="true">
<f:validateLength minimum="2" maximum="10">
</f:validateLength>
</h:inputText>
</h:form>
</body>
</html>
But when I open it int he browser, this is what I get
The output
What am I doing wrong?
Your document isn't XHTML.
The Doctype claims it is, but then you have a bunch of errors and non-XHTML content.
The browser is parsing the document in XML mode, which is a good first step if you were actually writing XHTML.
As pointed out in a comment:
The xmlns attribute is not OK. It should be "http://www.w3.org/1999/xhtml" rather than "http://w3.org/1999/xhtml"
Since you got it wrong, your default namespace isn't recognised as XHTML and the browser treats it as an unknown XML format with no special handling. This is why you get view of the XML node tree.
When you correct that, your document begins to be parsed as XHTML.
now all i get is a blank screen
This is because the only XHTML elements you have are the root element, the head and its descendants, and the body.
Everything else (e.g. h:form) is not XHTML. You have imported it from the http://java.sun.com/jsf/html namespace (except for those parts you imported from the http://java.sun.com/jsf/core namespace). (Note that this is forbidden by your choice of Doctype).
Web browsers do not know what to do with elements from those namespaces, so they get inserted into the DOM but are not rendered.
You need to either:
Determine what tool those elements are designed for use with and use that instead of a web browser. (It is possible that that tool outputs code you can use with a web browser).
Write code using languages designed for use with a web browser. That could be real XHTML, but the benefits of it only apply to rare edge cases and you would almost certainly be better off writing HTML.
What is the most correct way to include another XHTML page in an XHTML page? I have been trying different ways, none of them are working.
<ui:include>
Most basic way is <ui:include>. The included content must be placed inside <ui:composition>.
Kickoff example of the master page /page.xhtml:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Include demo</title>
</h:head>
<h:body>
<h1>Master page</h1>
<p>Master page blah blah lorem ipsum</p>
<ui:include src="/WEB-INF/include.xhtml" />
</h:body>
</html>
The include page /WEB-INF/include.xhtml (yes, this is the file in its entirety, any tags outside <ui:composition> are unnecessary as they are ignored by Facelets anyway):
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h2>Include page</h2>
<p>Include page blah blah lorem ipsum</p>
</ui:composition>
This needs to be opened by /page.xhtml. Do note that you don't need to repeat <html>, <h:head> and <h:body> inside the include file as that would otherwise result in invalid HTML.
You can use a dynamic EL expression in <ui:include src>. See also How to ajax-refresh dynamic include content by navigation menu? (JSF SPA).
<ui:define>/<ui:insert>
A more advanced way of including is templating. This includes basically the other way round. The master template page should use <ui:insert> to declare places to insert defined template content. The template client page which is using the master template page should use <ui:define> to define the template content which is to be inserted.
Master template page /WEB-INF/template.xhtml (as a design hint: the header, menu and footer can in turn even be <ui:include> files):
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title><ui:insert name="title">Default title</ui:insert></title>
</h:head>
<h:body>
<div id="header">Header</div>
<div id="menu">Menu</div>
<div id="content"><ui:insert name="content">Default content</ui:insert></div>
<div id="footer">Footer</div>
</h:body>
</html>
Template client page /page.xhtml (note the template attribute; also here, this is the file in its entirety):
<ui:composition template="/WEB-INF/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:define name="title">
New page title here
</ui:define>
<ui:define name="content">
<h1>New content here</h1>
<p>Blah blah</p>
</ui:define>
</ui:composition>
This needs to be opened by /page.xhtml. If there is no <ui:define>, then the default content inside <ui:insert> will be displayed instead, if any.
<ui:param>
You can pass parameters to <ui:include> or <ui:composition template> by <ui:param>.
<ui:include ...>
<ui:param name="foo" value="#{bean.foo}" />
</ui:include>
<ui:composition template="...">
<ui:param name="foo" value="#{bean.foo}" />
...
</ui:composition >
Inside the include/template file, it'll be available as #{foo}. In case you need to pass "many" parameters to <ui:include>, then you'd better consider registering the include file as a tagfile, so that you can ultimately use it like so <my:tagname foo="#{bean.foo}">. See also When to use <ui:include>, tag files, composite components and/or custom components?
You can even pass whole beans, methods and parameters via <ui:param>. See also JSF 2: how to pass an action including an argument to be invoked to a Facelets sub view (using ui:include and ui:param)?
Design hints
The files which aren't supposed to be publicly accessible by just entering/guessing its URL, need to be placed in /WEB-INF folder, like as the include file and the template file in above example. See also Which XHTML files do I need to put in /WEB-INF and which not?
There doesn't need to be any markup (HTML code) outside <ui:composition> and <ui:define>. You can put any, but they will be ignored by Facelets. Putting markup in there is only useful for web designers. See also Is there a way to run a JSF page without building the whole project?
The HTML5 doctype is the recommended doctype these days, "in spite of" that it's a XHTML file. You should see XHTML as a language which allows you to produce HTML output using a XML based tool. See also Is it possible to use JSF+Facelets with HTML 4/5? and JavaServer Faces 2.2 and HTML5 support, why is XHTML still being used.
CSS/JS/image files can be included as dynamically relocatable/localized/versioned resources. See also How to reference CSS / JS / image resource in Facelets template?
You can put Facelets files in a reusable JAR file. See also Structure for multiple JSF projects with shared code.
For real world examples of advanced Facelets templating, check the src/main/webapp folder of Java EE Kickoff App source code and OmniFaces showcase site source code.
Included page:
<!-- opening and closing tags of included page -->
<ui:composition ...>
</ui:composition>
Including page:
<!--the inclusion line in the including page with the content-->
<ui:include src="yourFile.xhtml"/>
You start your included xhtml file with ui:composition as shown above.
You include that file with ui:include in the including xhtml file as also shown above.
I've got a bit of a weird issue that I'm trying to figure out how to get around. Basically, the company I work for uses a CMS that only allows inline code for ASP.net and uses a 'styles' system to do things like Header/Footer.
Now the issue I have is on a certain page that displays course information, we have some asp.net code that generates the page based on factors from the previous linking page I.E a course search page that then takes you to the course you have selected.
Now we've got terrible SEO and I need to be able to dynamically create the title/meta tags for the page based on the selections from the course search.
Problem is for SEO, I need the title tag to be in the header but the identifiable information for that page comes within the asp.net code that grabs the course information from a DB and this is run in the body of page.
Is there any way for me to grab information or run another block of asp.net code at the header to set up the tags I need?
I apologise if this doesn't make much sense but then our CMS system makes everything more difficult but I'm unable to remove it.
Thanks!
So if I understand you correctly, you want to add <title> and <meta ...> tags into your rendered pages' <head> tag in your server-side code?
If you're using ASP.NET 2.0 or higher, you can change the <head> element to be accessible to the server code by adding runat="server" to the declaration. You can then set the title value through the Pages' Title property.
To add <meta> tags you'll need to be running ASP.NET 4.0, which adds MetaKeywords and MetaDescription properties to the Page object.
So to put this all together, your page markup should include:
<% Page ... %>
<html>
<head runat="server">
...
</head>
<body>
...
And then in your serverside code:
Page.Title = "My course page";
Page.MetaDescription = "My Page for Course x";
Page.MetaKeywords = "course, education, learning";
This should then render out as:
<html>
<head>
<title>My course page</title>
<meta name="description" content="My Page for Course X" />
<meta name="keywords" content="course, education, learning" />
....
Put placeholder in head tag and from code behind add meta tags using below code.
HtmlMeta meta = new HtmlMeta();
meta.Attributes.Add("property", "og:title");
meta.Attributes.Add("content", lblBannerTitle.Text.Length > 68 ? lblBannerTitle.Text.Substring(0, 68) : lblBannerTitle.Text);
MetaPlaceHolder.Controls.Add(meta);
This way, you can have any number of meta tags.
Just make sure Title meta tag max length is 68 and description meta tag max length is 148.
Let me know is it working with your case.
I recently found out over the weekend that iframes are not valid in XHTML strict. What would the correct way to refresh certain content then? A friend said just use divs and have JavaScript refresh them, is this true?
Your friend is right in a sense. You can achieve a similar effect to iframes by using AJAX to load a page into a <div> container. The problem is that AJAX requests are usually limited within the same domain, so you will not be able to load other websites. You can load other pages from your own domain though.
AJAX is ridiculously easy with jQuery. Check out this function:
http://api.jquery.com/load/
<div id="externalcontent">This text will be replaced.</div>
<script type="text/javascript">
$('#externalcontent').load('separate_pages/page2.html');
</script>
This would be kind of pointless as you could just load the content using server-side methods, but it shows how easy loading another page can be with jQuery.
Use XHTML Frameset
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
http://www.jonasjohn.de/snippets/html4strict/frameset-example.htm
Javascript is good. Check out jQuery (http://jquery.com/) for easier DOM manipulation!
I have a asp.net mvc site with a master page and it has following tag in the head.
<head runat="server">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
But when I goto view source in any browser, the meta tag is shown as
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
Who is adding the / to the end as />
Issue is when the site is validated with w3 validator it shows an error saying that the meta tag should be closed as > not as />. But I cannot find how the /> is created.
Doct type is
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Site is online at http://tipila.com if you want to see it for yourself.
I'm totally clueless here. Any help is appriciated.
This happens in both casini and IIS 7
Try removing the runat="server" attribute from the head tag.
As ZippyV mentions, the problem is the asp.net runtime is rewriting your tags because they're enclosed in server control (runat="server"). I would suggest not using it.
Also, you should really choose to specify the X-UA-Compatible as a header, rather than as a meta tag. This allows the browser to select the correct mode BEFORE it starts rendering the page.
As an example:
void Application_BeginRequest()
{
Response.AppendHeader("X-UA-Compatible", "IE=edge");
}