Un-setting route parameters in razorpages pages - razor-pages

I have a page Index that has two optional parameters: FolderId and OrganisationId.
If I use #page "{OrganisationId:int?}/{FolderId:int?}" at the start of the razorpages page to make nicer URLs then it becomes impossible to remove a parameter from the URL. The behaviour of the URL helpers changes.
For example the browser is at /Index/1/4 and I want to make a link to /Index/1. The code for the link ought to be
<a asp-area="Files" asp-page="/Index" asp-route-OrganisationId="#Model.Organisation.Id">#Model.Organisation.Name</a>
This works for #page, producing the required /Index/.
However, if the razorpages page begins with #page "{OrganisationId:int?}/{FolderId:int?}" then instead this renders /Index/1/4 which is clearly wrong because it is not what was asked for.
I have tried asp-route-FolderId="" and using asp-route-all-data but the unwanted parameter still appears.
Is it possible to get URL helpers to work correctly with the route templates?

Related

Link href in a pug template

I am using pug as the view engine of a nodejs application. I have a layout that every other current view extends, that contains a navbar with links to common urls across the app.
For example, a link to the signin url would look like :
a(href='/auth/signin')`
This works fine from the root url ('/'), correctly leads to '/auth/signin'.
Within the '/auth' module which contains the routes for '/auth/signin', '/auth/signup' and '/auth/signout', the behavior is different. Instead, the route is concatenated with the current module's name. So for example, within the '/auth/signin' route, the link is actually a link to '/auth/auth/signin'. Clicking on it naturally leads to a 404, but on that page the link to signin is a link to '/auth/auth/auth/signin'.
And so on and so forth.
I don't fully understand what is going on here and how to prevent it. Is there away to link to my routes in absolute terms in pug without straight up typing the full url (which is unpractical for a variety of reasons), the same way you'd use a route helper in Ruby on Rails ?
Solution from the comments:
If you start your href's with a slash then these are interpreted as absolute url's. Then it does not matter in which folder your pug file is located. Please check that your href's start with / always.

Internal href of <a tag now refreshes the page

I've got several anchor tags pointing to internal links mainly to scroll to some section titles or to get to the top from a bottom link of the site since some pages can get very long.
All tags like Whatever just scrolled the page to the <a name="whatever"></a> tag as intended until yesterday, but now when clicked they force a page refresh pointing to the root page with just hash, like this localhost/#whatever instead of this localhost/path/to/current/page/#whatever.
1) Is there even the possibility to alter something in the Apache server, browser settings (not touched tough), HTML/JavaScript/CSS code of a page or whatever to force page refreshes when clicking on internal links?
2) If I change the anchor to <a href="path/to/current/page/#whatever> it works, but it's just because a page refresh triggers and then the page is scrolled like normal when interpreting the hash fragment. Also, this way I loose any GET parameters (I can't predict them) which I really need since it's a database website
3) If I alter or remove the <base href="/" /> tag nothing happens, still the internal links worked before with that tag in place
4) I recently updated the .htaccess file and that could potentially be the cause but still routing has no problems and I can't see why any RewriteRule could possibly affect internal links. Also, trying to revert it to previous version didn't help
5) Same behavior applies to both Firefox and Chrome, latest versions
6) I tried to create a test page in the same environment (same .htaccess, same HTML base template) with just a very long <ul> list containing list elements with integers in sequence until 500, then a To 20 at the bottom of the page and it just worked all good... What can force a internal link to redirect?! Please help
I finally solved it! Check here link and here link. The problem was with the <base href="/" /> tag in the <head> section. I solved with a mixture of jQuery and pure JavaScript (jQuery is used only for select anchors and get attribute), here
$("a.local").on("click", function (e) {
e.preventDefault();
document.location.hash = "";
document.location.hash = $(this).attr("href");
});
Please note that I need to set the hash to an empty string before actually setting it to the href of the anchor since document.location.hash = $(this).attr("href"); alone would not trigger automatic scrolling on multiple clicks on the internal anchor (I tried it)

Can I render all zones to an HTML string in a controller method

I'm trying to render the HTML for a content item to a string from within a controller action. Technically I just want to get the "body" part of it without any header/footer stuff. I want to do this so I can get a content item rendering the way I want once, and then display it as a normal orchard page OR by requesting the HTML for the content item via ajax to display it in a div in a JavaScript app. I don't want to have to manually render everything in the JavaScript as that would be duplicating the layout logic I already did. I want to re-use the bulk of the server side rendering so any changes are reflected in my normal orchard page and my JavaScript page. I've been digging into the code and searching everywhere and have gotten close but not all the way there.
I found these:
How to render shape to string?
Using FindView in Orchard
In my controller I have:
var shape = _contentManager.BuildDisplay(contentItem);
Using either of the two methods above, I can render that shape to an HTML string in my controller. All was golden. I was getting the body of that page and using it in JS. Then, I changed a placement file:
<Place Parts_Common_Body="Content:1" />
was changed to:
<Place Parts_Common_Body="/AsideFirst:1" />
The body moved where I wanted it (AsideFirst) in my normal Orchard page but disappeared from the HTML retrieved using the two methods above.
If I look at shape.Content.Items after the BuildDisplay call, I can see the item for the body is no longer there... why is it not rendering all the zones? Or, I guess a more specific question is why is the BuildDisplay method not building the complete shape? Is there a way I can make this work?
I tried a million different things and eventually got this working. Not sure I totally get it yet, but I think the problem had to do with the fact that I was using shape.Content and I'd moved stuff out of the Content zone. And maybe when I was looking at what the BuildDisplay method was returning I was just not looking at some newly created zone that actually did had the stuff I thought was missing. Clearly I need to learn more about zones and shapes... Anyway, I have a new zone called "MainInfo" now that I created in a placement file. I get a MainInfo property on the main shape returned form BuildDisplay and pass shape.MainInfo to the view rendering code and all seems to be working well now.

Orchard - access a content type through different URLs so they use different views

I'm trying to create a CSS documentation library in Orchard. I want to save a description, CSS snippet and HTML snippet against each content type. The first view would show the description and CSS and HTML code written out. The second view would show a preview of what the CSS and HTML look like rendered.
cssdocumentation.com/content/item1
cssdocumentation.com/content/item1/live-preview
I've created the content type and the first view. But I'm not sure how to create the second view. I can see if I can create the alternative URL I can use the Url Alternates module to create an overriding .cshtml
To create an alternative URL I've looked at the autoroute module but this only allows you to adapt a single URL (unless I'm missing something?) and I've looked at Alias UI but this forces me to manually create an alternative URL everytime I create a content item.
Is this possible in Orchard without writting too much C#? (I'm a frontend developer so I only dabble in the behind the scenes stuff)
Thanks for any help
Best solution is to do this within your own module. But as a secondary option instead of having a second page, combine this content with your first page and hide it with CSS. When the user clicks a button to navigate to the next step render the CSS/HTML result on the same page. You can do this in many ways, here are a few ideas:
Render the CSS/HTML result out straight away on the same page but hide it. Show it when the user clicks a button
using jQuery to render the result on the client side. More dynamic if you allow editing of the HTML and CSS.
Redirecting the user to the same page with specific url parameters which you can pick up in your alternate to modify the output.

Preventing iframe caching in browser

How do you prevent Firefox and Safari from caching iframe content?
I have a simple webpage with an iframe to a page on a different site. Both the outer page and the inner page have HTTP response headers to prevent caching. When I click the "back" button in the browser, the outer page works properly, but no matter what, the browser always retrieves a cache of the iframed page. IE works just fine, but Firefox and Safari are giving me trouble.
My webpage looks something like this:
<html>
<head><!-- stuff --></head>
<body>
<!-- stuff -->
<iframe src="webpage2.html?var=xxx" />
<!-- stuff -->
</body>
</html>
The var variable always changes. Although the URL of the iframe has changed (and thus, the browser should be making a new request to that page), the browser just fetches the cached content.
I've examined the HTTP requests and responses going back and forth, and I noticed that even if the outer page contains <iframe src="webpage2.html?var=222" />, the browser will still fetch webpage2.html?var=111.
Here's what I've tried so far:
Changing iframe URL with random var value
Adding Expires, Cache-Control, and Pragma headers to outer webpage
Adding Expires, Cache-Control, and Pragma headers to inner webpage
I'm unable to do any JavaScript tricks because I'm blocked by the same-origin policy.
I'm running out of ideas. Does anyone know how to stop the browser from caching the iframed content?
Update
I installed Fiddler2 as Daniel suggested to perform another test, and unfortunately, I am still getting the same results.
This is the test I performed:
Outer page generates random number using Math.random() in JSP.
Outer page displays a random number on the webpage.
Outer page calls iframe, passing in a random number.
Inner page displays a random number.
With this test, I'm able to see exactly which pages are updating, and which pages are cached.
Visual Test
For a quick test, I load the page, navigate to another page, and then press "back." Here are the results:
Original Page:
Outer Page: 0.21300034290246206
Inner Page: 0.21300034290246206
Leaving page, then hitting back:
Outer page: 0.4470929019483644
Inner page: 0.21300034290246206
This shows that the inner page is being cached, even though the outer page is calling it with a different GET parameter in the URL. For some reason, the browser is ignoring the fact that the iframe is requesting a new URL; it simply loads the old one.
Fiddler Test
Sure enough, Fiddler confirms the same thing.
(I load the page.)
Outer page is called. HTML:
0.21300034290246206
<iframe src="http://ipv4.fiddler:1416/page1.aspx?var=0.21300034290246206" />
http://ipv4.fiddler:1416/page1.aspx?var=0.21300034290246206 is called.
(I navigate away from the page and then hit back.)
Outer page is called. HTML:
0.4470929019483644
<iframe src="http://ipv4.fiddler:1416/page1.aspx?var=0.4470929019483644" />
http://ipv4.fiddler:1416/page1.aspx?var=0.21300034290246206 is called.
Well, from this test, it looks as though the web browser isn't caching the page, but it's caching the URL of the iframe and then making a new request on that cached URL. However, I'm still stumped as to how to solve this issue.
Does anyone have any ideas on how to stop the web browser from caching iframe URLs?
This is a bug in Firefox:
https://bugzilla.mozilla.org/show_bug.cgi?id=356558
Try this workaround:
<iframe src="webpage2.html?var=xxx" id="theframe"></iframe>
<script>
var _theframe = document.getElementById("theframe");
_theframe.contentWindow.location.href = _theframe.src;
</script>
I have been able to work around this bug by setting a unique name attribute on the iframe - for whatever reason, this seems to bust the cache. You can use whatever dynamic data you have as the name attribute - or simply the current ms or ns time in whatever templating language you're using. This is a nicer solution than those above because it does not directly require JS.
In my particular case, the iframe is being built via JS (but you could do the same via PHP, Ruby, whatever), so I simply use Date.now():
return '<iframe src="' + src + '" name="' + Date.now() + '" />';
This fixes the bug in my testing; probably because the window.name in the inner window changes.
As you said, the issue here is not iframe content caching, but iframe url caching.
As of September 2018, it seems the issue still occurs in Chrome but not in Firefox.
I've tried many things (adding a changing GET parameter, clearing the iframe url in onbeforeunload, detecting a "reload from cache" using a cookie, setting up various response headers) and here are the only two solutions that worked from me:
1- Easy way: create your iframe dynamically from javascript
For example:
const iframe = document.createElement('iframe')
iframe.id = ...
...
iframe.src = myIFrameUrl
document.body.appendChild(iframe)
2- Convoluted way
Server-side, as explained here, disable content caching for the content you serve for the iframe OR for the parent page (either will do).
AND
Set the iframe url from javascript with an additional changing search param, like this:
const url = myIFrameUrl + '?timestamp=' + new Date().getTime()
document.getElementById('my-iframe-id').src = url
(simplified version, beware of other search params)
After trying everything else (except using a proxy for the iframe content), I found a way to prevent iframe content caching, from the same domain:
Use .htaccess and a rewrite rule and change the iframe src attribute.
RewriteRule test/([0-9]+)/([a-zA-Z0-9]+).html$ /test/index.php?idEntity=$1&token=$2 [QSA]
The way I use this is that the iframe's URL end up looking this way: example.com/test/54/e3116491e90e05700880bf8b269a8cc7.html
Where [token] is a randomly generated value. This URL prevents iframe caching since the token is never the same, and the iframe thinks it's a totally different webpage since a single refresh loads a totally different URL :
example.com/test/54/e3116491e90e05700880bf8b269a8cc7.html
example.com/test/54/d2cc21be7cdcb5a1f989272706de1913.html
both lead to the same page.
You can access your hidden url parameters with $_SERVER["QUERY_STRING"]
To get the iframe to always load fresh content, add the current Unix timestamp to the end of the GET parameters. The browser then sees it as a 'different' request and will seek new content.
In Javascript, it might look like:
frames['my_iframe'].location.href='load_iframe_content.php?group_ID=' + group_ID + '&timestamp=' + timestamp;
I found this problem in the latest Chrome as well as the latest Safari on the Mac OS X as of Mar 17, 2016. None of the fixes above worked for me, including assigning src to empty and then back to some site, or adding in some randomly-named "name" parameter, or adding in a random number on the end of the URL after the hash, or assigning the content window href to the src after assigning the src.
In my case, it was because I was using Javascript to update the IFRAME, and only switching the hash in the URL.
The workaround in my case was that I created an interim URL that had a 0 second meta redirect to that other page. It happens so fast that I hardly notice the screen flash. Plus, I made the background color of the interim page the same as the other page, and so you notice it even less.
It is a bug in Firefox 3.5.
Have a look..
https://bugzilla.mozilla.org/show_bug.cgi?id=279048
I set iframe src attribute later in my app. To get rid of the cached content inside iframe at the start of the application I simply do:
myIframe.src = "";
... somewhere in the beginning of js code (for instance in jquery $() handler)
Thanks to
http://www.freshsupercool.com/2008/07/10/firefox-caching-iframe-data/
I also had this problem in 2016 with iOS Safari. What seemed to work for me was
giving a GET-parameter to the iframe src and a value for it like this
<iframe width="60%" src="../other/url?cachebust=1" allowfullscreen></iframe>
I also met this issue, after trying different browsers, and a ton of trial and error, I came up with this solution, which works well in my case:
import { defineComponent } from 'vue'
import { v4 as uuid } from 'uuid'
export default defineComponent({
setup() {
return () => (
// append a uuid after `?` to prevent browsers from caching it
<iframe src={`https://www.example.com?${uuid()}`} frameborder='0' />
)
},
})
If you want to get really crazy you could implement the page name as a dynamic url that always resolves to the same page, rather than the querystring option?
Assuming you're in an office, check whether there's any caching going on at a network level. Believe me, it's a possibility. Your IT folks will be able to tell you if there's any network infrastructure around HTTP caching, although since this only happens for the iframe it's unlikely.
Have you installed Fiddler2?
It will let you see exactly what is being requested, what is being sent back, etc. It doesn't sound plausible that the browser would really hit its cache for different URLs.
Make the URL of the iframe point to a page on your site which acts as a proxy to retrieve and return the actual contents of the iframe. Now you are no longer bound by the same-origin policy (EDIT: does not prevent the iframe caching issue).

Resources