Grails: links for text files - grails

In my Grails app I need to serve links to actual text (*.txt) files. If the user clicks the link, they should view the text file as plaintext inside their browser:
MyFiles.groovy controller:
==========================
class MyFiles {
def index() {
render(view: "myfiles")
}
}
myfiles.gsp:
============
<!DOCTYPE html>
<html>
<head>
<!-- Omitted for brevity -->
</head>
<body>
Click me to view a file
</body>
</html>
My questions:
Where should I place myfile01.txt inside the Grails project? Directly inside web-app? Inside a web-app/myfiles dir? Inside WEB-INF?; and
What should the link be in the GSP, such that Grails correctly resolves correctly and displays the file? I don't see anything under g:links that stands out as an obvious choice.

I'd recommend creating another folder where you have images/css.
<a href='<g:resource dir="somedirectory" file=myfiles01.txt" absolute="true" />'>my file</a>

Related

How to remove a parent element, but keep its children elements in Thymeleaf?

I am working on an AngularJS Project hosted on a SpringBoot App with Thymeleaf, and I that need AngularJS to grab JUST the section element from another webpage via views and routing.
However, I can't figure out how to make it so that ThymeLeaf only gives the section element instead of the whole HTML page, while still allowing me to view the webpage as a natural template when developing.
So in the server it is stored as
<html>
<title>Don't keep this </title>
<body>
<section>
Keep this
</section>
</body>
</html>
But when AngularJS reads the page, Thymeleaf makes it read this:
<section>
Keep this
</section>
Yeah, this is pretty simple with fragments. If your html file looks like this:
<!-- whatever.html -->
<html>
<head>
<title>Don't keep this </title>
</head>
<body>
<section th:fragment="section">
Keep this
</section>
</body>
</html>
And your controller, like this:
#RequestMapping(value = "whatever.html", method = RequestMethod.GET)
public String get() {
return "whatever :: section";
// Where the string 'whatever' resolves to the template, and section
// resolves to the text in th:fragment.
}
It will return the html
<section>
Keep this
</section>

How do I set the content type in Grails?

I'm just trying to setup a very simple controller to return a very simple view (with a very simple layout), however I keep getting errors related to the content type.
class SimpleController {
def index() {
render(view: "simple")
}
}
_simple.gsp:
<html>
<head>
<meta name="layout" content="blank" />
</head>
<body>
Simple test page.
</body>
</html>
blank.gsp:
<!DOCTYPE html>
<html>
<head>
<g:layoutHead />
</head>
<body>
<g:layoutBody />
</body>
</html>
It doesn't get much simpler than that. The controller method is found correctly, the issue seems to be during the rendering. Here's the error I'm getting:
2016-07-05 16:07:14,931 [http-bio-8085-exec-5] ERROR errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [GET] /testApp/simple/
Stacktrace follows:
Message: null
Line | Method
->> 15 | in com.opensymphony.module.sitemesh.filter.HttpContentType
| 49 | build in com.opensymphony.sitemesh.compatability.PageParser2ContentProcessor
| 89 | getContent . . . . . . . . . . in org.codehaus.groovy.grails.web.sitemesh.GrailsContentBufferingResponse
| 107 | obtainContent in org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutView
Debugging confirms that context.contentType is null. I've found four different way to set the content type, but none of them seem to work.
<%# page contentType="text/html;charset=UTF-8" %>
At the top of the view.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
In the head tag of the view.
contentType: "text/html"
Passed to the render method in the controller.
response.setContentType("text/html")
Called in the controller method.
This is in an existing project, where many other controllers and views work perfectly fine. I need to add a new controller and view, which I originally copied existing working pieces. When that didn't work, I tried to reduce the problem down to be as simple as possible, and ended up with the above code, which is still not working.
Btw, this is with Grails 2.5.1 (stuck with this version).
What you have there should work.
If you're using the default URL mappings you should name your view simple.gsp instead of _simple.gsp
If it's not as simple as that you might try recreating a simple app.
Could be even simpler and incidentally solve your problem.
class SimpleController {
def index() {
}
}
Rename _simple.gsp to index.gsp and needs to be located in views/simple/ directory. If blank.gsp its in views/layouts directory it should work now.
As #jmallen said, the page should be named "simple.gsp".
The underscore at the beginning is something I only know for templates, gsp-files, that could be included in other pages with the following statement:
<g:render template="/layouts/menu" />
than the gsp file for the menu is named
_menu.gsp

Partial file not found in mvc application

I am getting following error.
An exception of type 'System.InvalidOperationException' occurred in System.Web.Mvc.dll but was not handled in user code
Additional information: The partial view '../Shared/Partial/_ReferencePartial.cshtml' was not found or no view engine supports the searched locations. The following locations were searched:
I am having login controller in Area/Admin. In Login.cshtml view file, I am referencing Partial View file that contains references to script files. This file is in the folder, Solution/Project/Views/Shared/Partial.
Below is my Login.cshtml view file code.
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>#Messages.Login</title>
#Html.Partial("../Shared/Partial/_ReferencePartial.cshtml")
</head>
...
If you want to load the partial view directly inside the main view you could use the Html.Action helper:
#Html.Action("Load", "Home")
or if you don't want to go through the Load action use the HtmlPartial hepler:
#Html.Partial("_LoadView")
If you want to use Ajax.ActionLink, replace your Html.ActionLink with:
#Ajax.ActionLink(
"load partial view",
"Load",
"Home",
new AjaxOptions { UpdateTargetId = "result" }
)
and of course you need to include a holder in your page where the partial will be displayed:
<div id="result"></div>
Also don't forget to include:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
in your main view in order to enable Ajax.* helpers. And make sure that unobtrusive javascript is enabled in your web.config (it should be by default):
<add key="UnobtrusiveJavaScriptEnabled" value="true" />

import external header (link) in MVC4 _layout page?

My company has common header that developed in php. I need to import that page into my layouts page in the project. The header can me called "company.com/inc/custom/footer2sn/"
How can call this?
If your page is to include is a static HTML page you can use Partial.
Simply change the somepage.html to somepage.cshtml.
Example:
#Html.Partial("~/Path/to/somefile.cshtml")
Trying to render a normal HTML file will give you an error such as Page cannot be found or no rendering engine could be found.
SO if you have a static HTML page, change the extension to CSHTML and use #Html.Partial()
OR
If the header you want to include is a PHP file it is possible as long as you have a server that is up and running and ready to serve the generated HTML from the PHP page.
You could write a custom HTML Helper
public static class MyHelpers
{
public static HtmlString RenderPHP(this HtmlHelper helper, string path)
{
var requestContext = helper.ViewContext.RequestContext;
UrlHelper url = new UrlHelper(requestContext);
var client = new WebClient();
var returnString= client.DownloadString(new Uri(string.format("Http://{0}{1}", requestContext.HttpContext.Request.Url.Host, url.Content(path))));
return MvcHtmlString.Create(returnString);
}
}
In short, this simply takes the HTML generated from the PHP page and injects it into a section within your page.
To use this inside your page use Razor Syntax like so:
<div id="phpPage">
#Html.RenderPHP("company.com/inc/custom/footer2sn/somepage.php"). <!-- Note this must on a server capable of rendering the php -->
Source
You can use Html.RenderPartial:
#{ Html.RenderPartial("SomeView"); }
But, it's better to have your layouts inherit each other hierarchically, and put your HTML directly in the layer it belongs to for common layout elements:
_Layout.cshtml
<!doctype html>
<html>
<head>
...
</head>
<body>
<header>
...
</header>
#RenderBody()
<footer>
...
</footer>
</body>
</html>
_TwoColumnLayout.cshtml
#{ Layout = "~/Views/Shared/_Layout.cshtml"; }
<div id="container">
<div id="content">
#RenderBody()
</div>
<aside id="sidebar">
...
</aside>
</div>
You can keep building layers like this as deep as you need. Just set Layout to the template it should inherit from and then put #RenderBody() where the content of the next child template or view should go.

How to get at Header

I'm trying to pass the header object here:
<%=FileUtil.AddStylesheetToHeader(Header, "UsedItems.css") %>
In my Master page I have a <head runat="server">. And my aspx page definitely has a reference to my MasterPageFile in the page directive at the top of my MVC based .aspx.
I also have an import statement the namespace that the FileUtil class resides in :
<%# Import Namespace="xxxx.Web.Utilities" %>
In standard ASP.NET you could reference the header with this.Header but in MVC I'm not able to do this...or I'm missing some kind of Imports or something.
for some reason though at runtime, with that call to AddStylesheetToHeader, I get the following error:
The best overloaded method match for 'System.IO.TextWriter.Write(char)' has some invalid arguments.
I'm not sure why it's looking at a .NET type as I know when I mouseover my FileUtil at compile time it's definitely referencing xxxx.Web.Utilities.FileUtil.
In that method I'm using HtmlLink styleSheet = new HtmlLink(); I may not be able to use this as it's an ASP.NET Web control? Here's that method:
public static void AddStylesheetToHeader(HtmlHead header, string cssFilename)
{
HtmlLink styleSheet = new HtmlLink();
styleSheet.Href = "content/css/" + cssFilename;
styleSheet.Attributes.Add("rel", "stylesheet");
styleSheet.Attributes.Add("type", "text/css");
header.Controls.Add(styleSheet);
}
I don't think I can use conrols that stem from System.Web.Controls since this is an ASP.NET application? If so, the how can I add a control to the header controls collection? Would I need to do this differently in MVC?
There may be a way to do it the way you're attempting, but it's more common in ASP.NET MVC to create a content placeholder in the <head> rather than accessing it programmatically. For example, your master view could look something like this:
<html>
<head>
<asp:ContentPlaceHolder ID="HeadContent" runat="server" />
</head>
</html>
And your view could look like this:
<asp:Content runat="server" ContentPlaceHolderID="HeadContent">
<link href="/content/css/UsedItems.css" rel="Stylesheet" type="text/css" />
</asp:Content>
have you tried this.Request.Header?
You can use JavaScript to dynamically add content to your HEAD section as shown in the code below:
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$("head").append("<link href='Content/Site.css' rel='stylesheet' type='text/css' />");
});
</script>

Resources