Add Route Parameter to all Razor Pages in an Area - asp.net-core

I'm trying to add a route parameter to all pages in a Razor Pages Area so every URL within an Area has an OrgId e.g. /dashboard/{orgId}/{page}/{route}. I can add them using the AddAreaPageRoute as shown below, but I can't help feeling there's a way to apply this to all pages without having to define an entry for every page in the Area. Is there a way to create a route for all pages in an Area?
.AddRazorPages(options =>
{
options.Conventions.AddAreaPageRoute("Dashboard", "/Index", "Dashboard/{orgId}");
options.Conventions.AddAreaPageRoute("Dashboard", "/AddItem", "Dashboard/{orgId}/AddItem");
options.Conventions.AddAreaPageRoute("Dashboard", "/Items", "Dashboard/{orgId}/Items");
options.Conventions.AddAreaPageRoute("Dashboard", "/Items/Index", "Dashboard/{orgId}/Items/{id}");
})

You can change your code like below:
services.AddRazorPages(options =>
{
options.Conventions.AddAreaFolderRouteModelConvention("Dashboard", "/", model =>
{
foreach (var selector in model.Selectors)
{
var c = selector.AttributeRouteModel.Template.ToString();
selector.AttributeRouteModel = new AttributeRouteModel
{
Order = -1,
Template =c.Replace("Dashboard", "Dashboard/{orgId}")
};
}
});
});
You can see the details in the doc.

Related

Pagination in keystoneJS can not implement it

I have many posts on my blog. I would like to show only 2 per page. I tried to use pagination in keystoneJS. I use https://keystonejs.com/documentation/database/#lists-paginate and should be ok, but I still see all my posts in one page.
Route / View
var keystone = require('keystone')
var Post = keystone.list('Post')
exports = module.exports = function(req, res) {
var view = new keystone.View(req, res)
var locals = res.locals
// Init locals
locals.section = 'blog'
locals.filters = {
post: req.params.post
}
// Load other posts
view.on('init', function(next) {
var q = Post.paginate({
page: req.query.page,
perPage: 2,
maxPages: 10
})
.model.find()
.where('state', 'published')
.sort('-publishedDate')
.populate('author')
// .limit(4)
q.exec(function(err, results) {
locals.posts = results
next(err)
})
})
view.query('blog', keystone.list('Post').model.find())
view.render('blog')
}
blog.pug
.pagination
ul.pagination
li #{posts.totalPages}
a.page-num(href="?page=1") Previous
li
a.page-num(href="?page={{posts.next }}") Next
I see all posts on my page and I cant set a number of page in blog.pug. iI was considering, if I should put any code to my blog.pug. Or only in route? In documentation the code is only in route file.
EDIT
Ok so I found the reason what has happened. I have to remove model.find() from my code in route. Then, in blog.pug I had to add to my loop word 'result'. I had 'each post in posts', and when i remove model.find() I changed my object with data. Now it is 'each post in posts.results' and it is correct.

Nuxt add parameters without page and without reload the page

I have a page with big list of data and some buttons for filtering.
for example 2 buttons to filter by status:
Complete status
Cancel status
I want when the user clicked on the complete the url to be changed to
http://demo.com/list?filter=complete
the page does not reloading, it just for get specific url foreach filter button.
How can I implement the code in Nuxt application?
You cannot use $route or $router to change url, it set a new html5 history state and reload the page. So, to change url without reloading, history.replaceState do the job. In your page or component:
methods: {
onClickComplete() {
if (!process.server) { // I'm not sure it's necessary
history.replaceState({}, null, window.location + '?filter=complete') // or use your own application logic: globalSiteUrl, $route... or queryString some vars...
}
}
}
At first you should change your route with "$route.push" or click on
these ways change the route without reloading
After than you can use "pages watchquery" to handle event of changing route
https://nuxtjs.org/api/pages-watchquery/
first create this helper function
export function getAbsoluteUrl(to) {
const path = $nuxt.$router.resolve(to).href
return window.location.origin + path
}
this is example for my tabs
watch: {
tab(value) {
if (!process.server) {
const url = getAbsoluteUrl({
params: { ...this.$route.params, activeTab: value }
})
history.replaceState({}, null, url) // or use your own application logic: globalSiteUrl, $route... or queryString some vars...
}
}
},

How to get ID of Tab of exist url

i want to get ID of Tab of exist url
For exemple i have 3 tabs in chrome
tab 1 is youtube
tab 2 is google
tab 3 is twitter
and i want get id of tab already existed url google com
Here is an example:
// get all the tabs, you can also limit it to the current window if you wish
// chrome.tabs.query({currentWindow: true}, ...)
chrome.tabs.query({}, tabs => {
// loop through the tabs
for (const tab of tabs) {
if (tab.url === 'theOneYouWant) {
// do whatever needed with tab.id
// break/stop the loop
break;
}
}
});
You can change the code to to check for the domain (not the whole URL) or any other relevant criteria.
Use chrome.tabs API in your extension page such as the browserAction popup or the background script.
manifest.json:
"permissions": ["tabs"]
Simplest case - no variations in domain name:
chrome.tabs.query({url: 'https://www.youtube.com/*'}, tabs => {
// use 'tabs' inside the callback
});
Simple case - variations in sub-domain but the TLD (top level domain) name doesn't have variations:
chrome.tabs.query({url: 'https://*.twitter.com/*'}, tabs => {
// use 'tabs' inside the callback
});
Tough case - TLD varies:
const RE_ALL_GOOGLE = /^https:\/\/(www\.)?google\.([a-z]{2,3}|com?\.[a-z]{2})\//;
// the tabs API doesn't accept wildcards in TLD so we need to enumerate all tabs
// and we restrict the list to https-only as an optimization for the case of many open tabs
chrome.tabs.query({url: 'https://*/*'}, tabs => {
const googleTabs = tabs.filter(({url}) => RE_ALL_GOOGLE.test(url));
// use 'googleTabs' here inside the callback
});
You can write a more restrictive regexp by using the full list of all Google domains and a RegExp generator like this one.
Content scripts can't use chrome.tabs directly so you'll need to do it via a background script.
content script:
chrome.runtime.sendMessage({
action: 'getTabs',
url: 'https://*/*',
// messaging can't transfer regexps so we convert it to a string
pattern: /^https:\/\/(www\.)?google\.([a-z]{2,3}|com?\.[a-z]{2})\//.source,
}, tabs => {
// use 'tabs' inside the callback
});
manifest.json:
"permissions": ["tabs"],
"background": {
"scripts": ["background.js"],
"persistent": false
}
background.js:
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.action === 'getTabs') {
chrome.tabs.query({url: msg.url}, tabs => {
if (msg.pattern) {
const re = new RegExp(msg.pattern);
tabs = tabs.filter(({url}) => re.test(url));
}
sendResponse(tabs);
});
// keep the reponse channel open since the chrome.tabs API is asynchronous
return true;
}
});

MVC4 Razor DisplayTemplate called, HTML generated, but not rendered to browser

I've got a view that iterates a collection and calls DisplayFor() for each element in the collection.
I need to manually iterate (as opposed to passing the collection to DisplayFor) in order to tell the template if a break in the list should be drawn. The items in the list will only be of 2 types, ordered by them, so I only need to show this break once.
My template is found and called correctly.
I can see the HTML it generates correctly, ie: DisplayFor().ToHtmlString()
I can set this HTML as a scoped variable, ie: var html = DisplayFor().ToHtmlString() ..
But even Html.Raw(html) does not render it in the browser - the HTML has simply vanished.
What's going on?
var renderBreakInList = Model.Items.Any(x => x.IsSomeType);
foreach(var item in Model.Items)
{
var renderBreak = renderBreakInList && item.IsOtherType;
Html.DisplayFor(x => item, new { renderBreak = renderBreak });
if (renderBreak)
{
renderBreakInList = false;
}
}
The Html.DisplayFor method in itself does not render anything to the response just returns the generated HTML as a MvcHtmlString.
In order to actually write the rendered HTML to the response you need to tell this to Razor with using the # sign:
#Html.DisplayFor(x => item, new { renderBreak = renderBreak })
So your whole code should look like this:
#{
var renderBreakInList = Model.Items.Any(x => x.IsSomeType);
foreach(var item in Model.Items)
{
var renderBreak = renderBreakInList && item.IsOtherType;
#Html.DisplayFor(x => item, new { renderBreak = renderBreak })
if (renderBreak)
{
renderBreakInList = false;
}
}
}
Or you can use the WebPageBase.Write method (which gets called under the hood when using the # sign):
Write(Html.DisplayFor(x => item, new { renderBreak = renderBreak }));
finally figured this out after trying a lot of different things and reworking how I tell the Template to draw the break.
Rather than send a bool which I'd prefer to make the template more robust (if the order changes), I'm passing in the ID of the item that should draw the break.
#{
var breakItem = Model.Items.FirstOrDefault(x => renderBreakInList && x.IsSomeType);
var breakID = breakItem == null ? (long?)null : (long)breakItem.ID;
}
#Html.DisplayFor(x => x.Items, new { breakID = breakID })
Also like nemesv pointed out, Html.DisplayFor() needs to be prepended with #. I got out of the habit of doing this inside code blocks because I would always get the 'once inside a code block you don't need #` error..

Dynamically Adding / Removing Route in Durandal Router when application is loaded

I need help in dynamically adding/removing route in Durandal Router. What I want is after user is logged in then I would be able to add or remove specific route depending upon logged in user's type.
I tried to add/remove route from visibleRoutes/allRoutes array ... but get binding exception from knockout library...
I was hoping it would be common scenario... but still couldn't find any solution ... please help me in fixing this issue.
Thanks.
Wasim
POST COMMENTS:
I tried this function to dynamically hide/show route... and similary tried to add/remove route from allRoutes[] ... but then get exception on knockout bidning
showHideRoute: function (url,show) {
var routeFounded = false;
var theRoute = null;
$(allRoutes()).each(function (route) {
if (url === this.url) {
routeFounded = true;
var rt = this;
theRoute = rt;
return false;
}
});
if (routeFounded)
{
if (show)
{
visibleRoutes.push(theRoute);
}
else
{
visibleRoutes.remove(theRoute);
}
}
}
In Durandal 2.0.
You can enumerate the routes to find the one you wish to show/hide.
Then change the value of: nav property
Then run buildNavigationModel();
here is an example:
// see if we need to show/hide 'flickr' in the routes
for (var index in router.routes) {
var route = router.routes[index];
if (route.route == 'flickr') {
if (vm.UserDetail().ShowFlickr) { // got from ajax call
// show the route
route.nav = true; // or 1 or 2 or 3 or 4; to have it at a specific order
} else if (route.nav != false) {
route.nav = false;
}
router.buildNavigationModel();
break;
}
}
Durandal 2.0 no longer has the method visibleRoutes. I found that the following works for me.
router.reset();
router.map([
{ route: 'home', moduleId: 'home/index', title: 'Welcome', nav: true },
{ route: 'flickr', moduleId: 'flickr/index', title: '', nav: true }
])
.buildNavigationModel()
.mapUnknownRoutes('home/index', 'not-found');
This removes all previous routes, if you want to maintain current routes you could try using the router.routes property to rebuild the array of routes.
I had a similar requirement. If I were you, I would take another approach. Rather than adding/removing routes when application loads - get the right routes to begin with per user type.
Two options, (I use both)
1) have a json service provide the proper routes per user type, this approach would be good if you need to 'protect/obscure' routes... i.e. I don't want the route referenced on any client resource.
2) A simpler solution see Durandal.js: change navigation options per area
You can have a settings property identify the user type.
I hope this helps.
I had a similar problem: First, router.visibleRoutes() is an observable array. In other words, when you change its value, the routes automatically update. However, the items in this array are not observable, so to make a change you need to replace the entire array and not just make a change to a single item in it.
So, all you have to do is find which item in this array you want to remove, and then create a new array without this item, and set router.visibleRoutes() to this new array.
If, for example, you find out the it is the 3rd item, then one way of doing it is:
router.visibleRoutes(router.visibleRoutes().splice(2, 1))
Note that splice() returns a new array where an item is removed. This new array is put into router.visibleRoutes.