MVC6 Strange _Layout behaviour - asp.net-mvc

I've created a simple MVC6 site from the empty site template.
Here's my _Layout:
<!DOCTYPE html>
<body>
#RenderBody()
</body>
And my Index page:
<div>
<p>Hello World From a View!</p>
</div>
The Home controller:
public IActionResult Index()
{
return View();
}
Now here's the problem: Templating via _Layout works as expected if the #RenderBody() isn't enclosed in any tags, example:
<!DOCTYPE html>
#RenderBody()
It also works if it's wrapped in a div, but when it's wrapped in <body tags the page just doesn't load and is in a state similar to an infinite refresh (it just keeps loading the page indefinitely).
Can anyone shed some light on this? Maybe I'm missing some dependency?
EDIT:
A bit of extra info I've forgot to include: It's running on IIS10.

It seems to be a bug with IIS10 and ASP.NET vNext.
When I run it directly through dnx it works flawlessly. But when I run it through IIS10 it just hangs.

Related

Workaround for #request.getParameters() in Thymeleaf

We are using CAS 5.2.3 which uses an upgraded version of Thymeleaf. Thymeleaf has restricted access to certain request features - '#request.getParameters()' being one. Is there any work around for it? I am getting the following error when trying to access it - "Access to request parameters is forbidden in this context. Note some restrictions apply to variable access. For example, direct access to request parameters is forbidden in preprocessing and unescaped expressions, in TEXT template mode, in fragment insertion specifications and in some specific attribute processors."
Good question. I face this problem a few months before, it is solvable.
After looking through their source code, I found that they are limiting the usage of #request.getParameters() only on specific tag, they didn't forbid to use #request.getParameters() in some situation.
In my use case, I am able to use CData to bypass this checking. Not sure whether it applies to your use case since you didn't provide any code example....
Anyway, the below example want to redirect user to another page, based on the parameter url
Here's an sample code that was broken in CAS 5.2.x, but worked in CAS 5.1.x :
<html>
<head>
<title> Deforestation </title>
</head>
<body th:attr="onload='window.location.href=\''+${#request.getParameter('url')}+'\''">
</body>
</html>
Here's a work around code:
<html>
<head>
<title> Deforestation </title>
</head>
<body>
Logging out. Please wait...
<script th:inline="javascript">
/*<![CDATA[*/
location.href = /*[[( ${#request.getParameter('url')} )]]*/ ;
/*]]>*/
</script>
</body>
</html>
If this didn't solve your problem, please provide your source code so we can have a better look at the problem.
Note: There is a security reason why this stuff is now banned, using this workaround might compromise the security standard, do remember to sanitize the user input if neccesary
Edit:
as per comment, although not elegant, maybe something like the following will work?
<html>
<head>
<title> Data attribute </title>
</head>
<body>
<span id="foobarid"> </span>
<script th:inline="javascript">
/*<![CDATA[*/
$('#foobarid').data('foo-bar',/*[[( ${#request.getParameter('foo') == 'bar'} )]]*/);
/*]]>*/
</script>
</body>
</html>
Apparently one can spend hours, even days on this simple requirement, which Thymeleaf introduced as a poorly dcumented annoyance in later versions. I've spent hours upgrading from an older Thymeleaf version from 5 years ago and got stuck on this very same problem. The lack of documentation didn't either. When I finally took a think break, I've realized the solution to this problem is as simple as using the <c:set> core tag with JSP.
Simply use the th:with tag in some higher level html tag where accessing request parameters is allowed, like this:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns="http://www.w3.org/1999/xhtml"
th:with="action=${param.action != null ?
param.action[0] : 'none'}">
<head>
...
In this example, the request parameter action is stored in a page context local variable named action (the name can be any unique name that you choose). This variable is now accessible anywhere bellow your high level html tag where you've defined it. It can even be used in following th:xx tags in the same html tag after the declaration. So basically, now you can do this:
<th:block th:switch="${action}">
<title th:case="'edit'" th:text="#{page.contacts.edit}"></title>
<title th:case="'delete'" th:text="#{page.contacts.delete}"></title>
<title th:case="*" th:text="#{page.contacts.add}"></title>
</th:block>
and even call a parameterized fragment by simply referring to your variable as ${action}. In this example I have a navbar template fragment, which accepts three parameters. The last of which, is a request parameter that otherwise, is inaccessible due to the newer Thymeleaf request object access restrictions.
<div id="wrapper">
<div class="nav" th:replace="html/fragments/navbar ::
navbar('html/contact','contact-html', ${action})">
</div>
<div class="content">
...
If you need more request params and more local page context variables, just use a comma to separate the declarations in the th:with tag like this:
th:with="action=${param.action == null ? 'none': param.action[0]},
self=${param.self == null ? 'none': param.self[0]}"
I hope this saves you guys some precious time and voids the frustration of refactoring older Thymeleaf html pages. It definitely beats those horrifically unmanageable CDATA scriptlets inside your pages.

Pages not being unloaded from DOM when using index.html

I have two very simple pages as below. If I browse to "mysite.com/" the webserver returns the "index.html" content, as is normal. If I then click the "page2" link, jquery mobile loads the 2nd page into the DOM, but doesn't unload the first page from the DOM, although it is hidden (display:none) from view.
I now have 2 <div data-role="page"> elements in the DOM, with only page2 page visible on screen. If I then click the "index" link on page2, jquery mobile unloads page2 from the DOM, and loads the index.html page into a new DOM element. I now have two instances of <div id="index"> in the DOM which is obviously incorrect!
What is going on? I thought I'd ask on here before reporting it as a bug but it seems like a very simple example that is completely broken!
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<div data-role="page" id="index">
Page2
<p>index page</p>
</div>
</body>
</html>
page2.html
<html>
<body>
<div data-role="page" id="page-2">
Index
<p>Page 2</p>
</div>
</body>
</html>
EDIT:
I found a workaround of page2.html linking to rather than "index.html", which prevents the 2nd duplicate loading, but it still seems wrong that the original page loaded is always kept in the DOM.
EDIT 2: This is a known issue https://github.com/jquery/jquery-mobile/issues/4050 - I just didn't manage to find it despite extensive googling before posting this question. I might raise a bug report against their documentation though, because it is highly unexpected behaviour IMO.
This is the default behavior of jQuery Mobile, first landing page is always kept in DOM. It only removes external pages which aren't cached data-dom-cache="true". You will always have two pages in DOM, landing page and active external page.
Nevertheless, if you wish to remove landing page once you navigate to another page, add data-external-page="true" to page div of the landing page. Once it's created pagecreate, flag it for removal .page("bindRemove"). This is the way jQuery Mobile removes external pages.
Note that is fix will work as long as .page() widget isn't removed and replaced by .pagecontainer() widget.
<div data-role="page" id="pageID" data-external-page="true">
$(document).on("pagecreate", "#pageID", function (e) {
$(e.target).page("bindRemove");
});
Demo
I created a test as described in your question with the two files index.html and page2.html and tested with Chrome (version 38.0). I loaded index.html and then navigated to page2.html and then back to index.html. Using Chrome Developer Tools, I then examined the elements in the page and found the following (screen shot):
As we see, there is one instance of the page called index and one instance of the page called page-2 but no duplicates.
I realize that this does not line up with your own results but am offering this is an answer demonstrating that the story works as expected. If we determine a flaw in the logic of this answer, I'll happily delete it.

JSP equivalent of ASP.NET MVC's partial views?

What is the JSP equivalent of ASP.NET MVC's partial views?
I'd like to separate some complicated view logic out of a page into a separate page that only handles that logic. How can I render that page as part of my page?
There isn't. JSP is not a fullworthy equivalent of ASP.NET MVC. It's more an equivalent to classic ASP. The Java equivalent of ASP.NET MVC is JSF 2.0 on Facelets.
However, your requirement sounds more like as if you need a simple include page. In JSP you can use the <jsp:include> for this. But it offers nothing more with regard to templating (Facelets is superior in this) and also nothing with regard to component based MVC (there you have JSF for).
Basic example:
main.jsp
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
</head>
<body>
<h1>Parent page</h1>
<jsp:include page="include.jsp" />
</body>
</html>
include.jsp
<h2>Include page</h2>
Generated HTML result:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
</head>
<body>
<h1>Parent page</h1>
<h2>Include page</h2>
</body>
</html>
See also:
What is the Java alternative to ASP.NET/PHP?
Analogues of Java and .NET technologies/frameworks
What is the difference between JSF, JSP and Servlet?

Adding a script reference to the html head tag from a partial view

How do I inject a script tag such as
<script src="somejsfile"></script>
or
<script type="text/javascript>some javascript</script>
into the head tag of a page from a partial view?
Update: Answer for the old question
This is about ASP.NET MVC. We can use the RenderSection. Here the sample for MVC 3 using Razor view engine:
layout view or master page:
<html>
<head>
<script ...></script>
<link .../>
#RenderSection("head")
</head>
<body>
...
#RenderBody()
...
</body>
</html>
View, e.g. Home:
#section head{
<!-- Here is what you can inject the header -->
<script ...></script>
#MyClass.GenerateMoreScript()
}
<!-- Here is your home html where the #RenderBody() located in the layout. -->
Even if THX's answer works, it's not a good one as MVC's intention is to be stateless by nature. Moreover his solution does not let you place your scripts where they should go - most sites want their script declarations at the very bottom of their page just before the </body> tag as it is best for performance and search engine optimization.
There is an answer, thanks to Darin Dimitrov:
Using sections in Editor/Display templates
His answer allows you to register scripts from a partial view within the layout view.
The caveat is his answer marks items using a GUID in a dictionary object, so there is no guarantee the scripts will be rendered in the master page in the same order they are listed in your partial view.
There are two workarounds for that:
Register only 1 script from a partial view -or-
Change his HTML Helper implementation to support ordering
I'm trying to work on the later myself.
Good luck.
Partial views are UserControls. Can't you use RegisterClientScriptInclude method of ClientScriptManager?
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
Page.ClientScript.RegisterClientScriptInclude("some key", "http://website/javascript.js");
}

How does Grails know to apply a "layout" to pages it renders?

I've been going through the book "The Definitive Guide to Grails" (Rocher/Brown) and in Chapter 04, this mysterious thing called a "layout" just appeared with no explanation. (And there's no "layout" in the index. As far as I know, it's never explained.)
How does the system know to "inherit" the pages from layout/main.gsp? There's nothing about "layouts" in the index, and it seems to have just appeared.
On their sample app, a simple store site, the URL mappings for the / homepage say
"/"(controller:"store")
and store controller's empty "index" closure
package com.g2one.gtunes
class StoreController {
def index = {
}
}
simply tells it to render store/index.gsp
The store/index.gsp just has a few lines of HTML; no layout gets included with any directive
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="layout" content="main">
<title>gTunes Store</title>
<g:javascript library="prototype"></g:javascript>
</head>
<body id="body">
<h1>Your online music store and storage service!</h1>
<p>Manage your own library, browse music and purchase new tracks as they become available</p>
</body>
</html>
When I run the sample the page shown for "/" isn't just this simple HTML, it's the contents of "layouts/main.gsp" with this information magically inserted inside it.
I don't see how the information in layout/main.gsp gets applied to the page, how the elements get mixed together. I've been following through the book page by page and this functionality just "appeared" with no explanation.
The <meta name="layout" content="main"> tag includes the layout in the gsp page.
You can view the grails-app/views/layouts/main.gsp to view and modify the layout. You can copy main.gsp to mymain.gsp, modify it, then change layout entry in the gsp page to reference mymain.gsp instead of main.gsp and experiment with customizing your layout preserving your ability to easily back out your changes.
Grails uses sitemesh under the covers (like it uses hibernate and spring) to do view layouts. There is a web-app/WEB-INF/sitemesh.xml configuration file in the project directory as well. This particular file isn't that helpful, but it references a class in the groovy project if you wanted to deeply understand how grails is using sitemesh (this probably isn't necessary).
Here's your directive:
<meta name="layout" content="main">
main.gsp contains <g:layoutHead> and <g:layoutBody>, where the <head> and <body> content of the index.gsp are folded into the layout to create the final page.
One recent trick that appears to work, if you name your layout to match your controller it appears (in Grails 2.3.4 at least) to automatically use that template.
For example, my controller:
// grails-app/controllers/myapp/HomeController.groovy
package myapp
class HomeController {
def index() {
[ myvar: "Test" ]
}
}
my layout:
// grails-app/views/layouts/home.gsp
<html>
<head></head>
<body>
<h1>Home</h1>
<g:layoutBody />
</body>
</html>
my view:
// grails-app/views/home/index.gsp
<p>${ myvar }</p>
renders using the home layout.
Also, you can specify a layout for all your actions in a controller like this:
class HomeController {
static layout = "someotherlayout"
// actions will render using grails-app/views/layouts/someotherlayout.gsp
}

Resources