how to server html pages with play - html

Hi I would like to serve my index.html page from the controller. and i do not want it to be a view, i want it to be a pure html file i have no need for plays template engine.
Consider the following:
Route: GET / controllers.MainApp.index
And the route implementation is:
def index = Action { implicit request =>
if (AuthenticatedAction.isAuthenticated) {
Ok(controllers.Assets.at(path="/public/", file="index.html"))
}
else Redirect(controllers.routes.Authentication.login()) }
I get the following error:
Cannot write an instance of play.api.mvc.Action[play.api.mvc.AnyContent] to HTTP response. Try to define a Writeable[play.api.mvc.Action[play.api.mvc.AnyContent]]
Is there any way to serve an html page like that?
A possible solution is to do something like that:
route: GET /*file controllers.Assets.versioned(path="/public", file: Asset)
and then return from the controller:
Redirect("/index.html")
Which gives me a url path which i don't want:
http://localhost:9000/index.html#/
Thanks

I think the solution is to return
controllers.Assets.at(path="/public/", file="index.html")
rather than
Ok(controllers.Assets.at(path="/public/", file="index.html"))
The at method already returns a Result, so you don't need to use Ok here.

Related

How to make "Pretty" URL after dynamic content load using ajax

I am currently developing a website that will dynamically load the page content using ajax triggered by hash changes.
The code looks like this
$("*").delegate("a", "click", function () {
// Trigger Hash Change
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function () {
let newHash = window.location.hash.substring(1);
$("#main-content").load(newHash + " #ajax-content", function (responseTxt, statusTxt, xhr) {
}).hide().fadeIn();
});
Basically what I am working on now is making the URL look "Pretty", I have modified the .htaccess file to remove the .html extension
So a URL that looks like this
www.example.com/about.html
will become this
www.example.com/about
If I navigate the index (home) "www.example.com" page of the website and then navigate from there to the about page, the URL looks fine. "www.example.com#about" since the server does not display the "index" in the URL.
However, if I navigate straight to the about page like this www.example.com/about, then from the about page to another page, for example, the contact page. I get a URL that looks like this www.example.com/about#contact. When it should look like this www.example.com#contact.
My question is what is the best way to handle this? should I use jquery to redirect all to the index page and then add the hash to load the correct content? or is there some way I can not display the unnecessary part of the URL?
I hope my question was clear, I'm new to the server-side stuff involving the .htaccess file. FOr the ajax stuff I was following this tutorial from CSS tricks
https://css-tricks.com/video-screencasts/85-best-practices-dynamic-content/
You can use history.pushState
window.history.pushState("object or string", "Title", "/new-url");
The url will be www.example.com/new-url
in fact you can get history.state after use this method.
console.log(window.history.state)
output should be "object or string"
You can see the docs here.
Remember to use / to override the entire path.
To do what i think that you want, you can just override the url to / and set the hash.
This is probably not the best way to do this, but I have managed to redirect any page to the home page and then replace the / with the hash value so that the site wont end up wit "messy" URLs.
if(window.location.pathname != "/home.html")
{
window.location.replace("home.html" + window.location.pathname.replace("/", "#"));
}
what happens id the user navigates to "*www.example.com/about*" they will actually be sent to the homepage with the #about.html. So the never end up like this "*www.example.com/about#about*"

Using Angular to get html of a website URL

I am new in Angular
What I am going to try is to get the HTML of a page and reproduce it into an iFrame (it is an exercise).
I am using the following piece of code:
var prova = this._http.get(myUrl, {responseType: "text"}).subscribe((x) =>{
console.log(x);
});
I did it on a website (if is needed I can also insert the name of the pages) and it returns the html only of some pages.
In the other case the string x is empty.
Could it depend on connection?
Or there is some way to wait the end of the get request?
Or simply is wrong my approach and I should make a different type of request?
Your most likely going to need to use a library like puppeteer if you want to render a page properly. Puppeteer is a node library and useless headless chrome so I am not sure how well you could really integrate with Angular.
https://github.com/GoogleChrome/puppeteer

How to have multiple HTML static pages on a ASP.NET MVC project using the Layout page?

On my MVC project I have to incorporate 40 static pages.
I want these pages to use the Layout page.
What is the best way to do that?
I know this question was asked before but I didn't find any good answer.
Any advise?
I don't relly know ASP, but I try to give a generic answer.
So I think if you have a lot of similar static pages, somehow you could make a controller action that handles all these pages. For example the action gets the name of the page as a path variable in the URL, and return the view according to that.
But if that is not possible in the language you are using, you can just make simple separate actions for these pages. Maybe you could group the related ones into the same controller, so you would have a few controllers that handle these pages, and they are not stuffed in one controller.
Basically the solution is very simple, you have to create views for you static HTML (cshtml), then you should add a Route to your Route.Config like this:
routes.MapRoute(
"OrdeForm",
"OrderForm/{file}",
new { controller = "MyController", action = "Page", file} = "" }
);
Where "File" is a dynamic parameter that gets the View name from the URL and renders the right View.
The global controller should be something like this:
public class OrderFormController : Controller
{
public ActionResult Index(string file)
{
return View(file);
}
}
That works perfectly!
Thank you #Erik Philips for the excellant answer!

Yii2: exclude specific controller actions from '$this->goBack()'

I have views from various controller actions which are solely to be run from an iframe placed in another view.
Currently, when the iframe loads, and I go to the log in page to log in, on success the login controller (using yii2 user module) calls $this->goBack(), redirecting me to the iframe source URL (since it's the last page visited), rather than the original page containing the iframe.
Basically, I'd like to exclude specific controller actions from being set as the return URL when $this->goBack() is called. Bonus points if all actions loaded in iframes are automatically excluded from $this->goBack().
Ok, I'll have a go at this! This code is totally untested! Your problem is that the action has no way of knowing whether it's been called from an iframe or not, unless you give it one. So, the basis of my attempt at an answer is that all urls for iframes should have an additional get parameter. Lets call that caller. So each iframe should look something like
<iframe url="index.php?r=controller/action&caller=this-controller/action</iframe>
Now you can always test the request url to see if it was called from an iframe. In addition, every link within the iframe should have this parameter added to it's url.
So, now we have at least two problems. Firstly, how to automatically add caller as a get parameter, without having to re-write every url, and secondly, how to reconfigure the goBack() method so it knows the difference between the two types of request.
The first problem can be relatively easily resolved by adding another view layer in between the controller and the view you want I'll call it iframe. So in your controller action, add this;
$view = 'The name of the view you want to render';
$this->render('iframe', 'view' => $view);//Add in any other parameters you want to pass
Your iframe view file should contain something like this;
<iframe src="<?php Url::to(['however you generate the url for your iframe', 'caller' => Url::to($this->context->route)]); ?>">
<?php $this->render($view); ?>//Pass additional parameters to the view if needed
</iframe>
Now we have a way of testing a controller/action call to see if it being requested by am iframe. The caller parameter is important because it allows us to extract a string to use as the value for goBack() and other methods.
Next, we need to extend UrlManager, as all request, response, Url:to() and goBack() methods and classes ultimately use the UrlManager to complete the methods for generating urls.
So, create a new UrlManager. We'll copy most of the code from the existing UrlManager, just adding some spiciness of our own. I've stored mine in commands, but put your where you like and change the namespace accordingly.
<?php
namespace app\commands;
use Yii;
use yii\web\UrlManager;
class CustomUrlManager extends UrlManager {
public function createUrl($params){
$request = Yii::$app()->request;
$caller = $request->get('caller');
if ($caller && !$params['caller']){
$params['caller'] = $caller;
}
return parent::createUrl($params);
}
}
So now, the iframe generates a caller parameter, and every link within the iframe will also have caller appended as a parameter, as long ass you've used either Url::to() (or variants on that method) or Yii::$app->UrlManager to generate your links.
Now all we need to do is customise the goBack() method of your controller to send any goBack() requests to the original source iframe.
public function goBack($defaultUrl = null)
{
$caller = Yii::$app->request->get('caller');
if ($caller){
return Yii::$app->getResponse()->redirect($caller);
}
return Yii::$app->getResponse()->redirect(Yii::$app->getUser()->getReturnUrl($defaultUrl));
}
Finally you need to configure Yii to use your new UrlManager, in your config file;
'components' => [
'urlManager' => [
'class' => 'app/commands/CustomUrlManager'
]
]
I'd love to know if this works, it's been an interesting challenge!

Node.js - where to find incoming parameter in the HTML/document

I have the following function in my Node.js code that renders an HTML page and passes it an javascript object called htmlParamObj
exports.getPage = function (req, res, next) {
var htmlParamObj= {
propertyOne: 'yada',
propertyTwo: 'yada yada'
};
res.render('myPage.html',htmlParamObj);
};
I can access the incoming parameter (htmlParamObj) with EJS like so: <% propertyOne %>, but I don't know how to access htmlParamObj via the document itself. I believe htmlParamOb' will be attached to the document of the html - but what field in the document can I find it in? Is it in the head, the body, the childNodes? Where?
The object passed is only used while rendering the HTML, and will not be passed to the browser in any way.
If you need that data inside the page you need to put it there.
The solution I've used when I need to pass complex data to a client side script is to place a script tag near the top of my HTML EJS file and populate that with my data. For example I might add the following to my template:
<script>
window.MY_DATA = <%= JSON.stringify(myData) %>
</script>
Notice that since JSON is a subset of javascript, I can use JSON.stringify to serialize my data into a form suitable for placement inside a script tag, and assign it to whatever variable I want.
The limitation here is that you can't send any data that can't be serialized with JSON.stringify. Not a heavy burden, but could trip you up if you want to send a function or other object.
The solution I found is to define a global attribute in my HTML like so:
<a name="team" value="<%=team._id%>"></a>
then I can access it in any script like so:
<script>
var team = document.getElementsByName('team');
</script>
This will return the correct object.
However, I don't think this is the best answer, especially given that any globally defined variable is usually a bad idea. I am hoping another answer is given to this question.