Automatically generate sitemaps for all controllers - c#

I'm trying to create the sitemap.xml file automatically for my Asp.Net Mvc 5 website. I have installed the MvcSiteMapProvider.MVC5 4.6.1 package from Nuget and I have read the getting started guide. To my understanding I have to add ALL the controllers and their actions to its configuration file. However, somewhere in the doc, it said that the package automatically keeps track of the visited URLs and generates their nodes in the sitemap.xml, "for free"! I visited a few pages and refreshed the sitemap.xml file but it didn't change. Am I missing something? Does this package really provide dynamic sitemap.xml files?

First of all, the \sitemap.xml endpoint is not a "file", it is a controller action that dynamically generates the XML based on the configuration of the SiteMap. It generates the XML to submit to search engines as per sitemaps.org.
Being that this endpoint is for search engines, it doesn't make any sense to keep track of a user's visits on the site and show the pages the user visited in this result. Instead, it contains all of the pages that are configured (either by URL or by controller, action and other route values).
However, the main purpose of MvcSiteMapProvider is to provide menus and breadcrumb trails to individual pages. Again, this doesn't work by tracking a user's position, it works by determining the relative position (in relation to other nodes) of the URL within the SiteMap. For more information, read How to Make MvcSiteMapProvider Remember a User's Position.
You don't necessarily have to add all of the controller actions to MvcSiteMapProvider, technically you only have to add the URLs that you need indexed by search engines. And then you get the sitemaps XML for free.
However, for pages that you don't need indexed (administration pages, for example) it is possible to use a combination of preservedRouteParameters, [TitleAttribute], and ISiteMapNodeVisibilityProvider to fake the breadcrumb trail so you don't have to add a node for every record in the database to make it function, as described in the above article.

Related

What options are there to not reload whole page for a file browser on ASP .NET Core Razor page?

I've got an application written in ASP .NET Core 3.1 that uses Razor pages to display various content.
I have a kind of project details view, where the details of the project are shown like image, description, some fields but also a list of files of the project.
The files of the project I collect using the Graph API (using credentials stored in Configuration/Azure Key Vault) and currently I list them out in a flat list. I store the list of files in my model (in a list with a custom object, to include metadata for the file)
I would like to show the files with folders, so the user only sees the top level folders and files when he opens the page. When he clicks on a folder, the folder should "open" and the user should now see the contents of the this folder (with an option to navigate one level up again).
Honestly, I am not quite sure how to start. I don't want to reload the whole page when the user clicks on a folder and as far as I know there is nothing like an Update Panel in ASP .Net Core that lets me only update parts of a page.
I also programmed some other Reat.JS applications, I know I could create a very dynamic react app to display those files but I am not sure if there is a good way to integrate such a react component in my ASP .NET Core app and also I don't know how I would pass the credentials to this component.
Hope someone can point me in the right direction and give me some tips.
Yes, there is no Update Panel in ASP.NET core MVC, but that doesn't mean you cannot update individual parts of the page. You can use a View Component to render just the content of a folder. The following is a list of key things you need to do to implement it:
Add a MVC action to your controller that returns View Component.
Enclose the folder content in a container div of known id.
Attach JavaScript event listeners to subfolders
When the user clicks one subfolder the event listener uses the fetch API to call the MVC action.
The event listener sets innerHtml property of the container div to the HTML returned by the MVC action
Attach event listeners to subfolders of recent loaded content.
This approach doesn't require any JavaScript framework or library. It can be implemented with plain vanilla JavaScript.
Probably you will want to add fetch and promise polyfills.
Unfortunately, this question is fairly broad and is likely to result in it being closed. (I didn't vote to close it). The challenge with this question is that there are so many different ways to handle this sort of programming problem.
Using ajax is one very common way to handle this. Which then brings us to javascript libraries, and there are a bunch of choices. You mentioned react. That is one good choice. If react feels too heavy for you then give my answer here a read with regard to Vue. VueJs is extremely lightweight and can easily be used on a single page or on a group of pages. Vue may be a great solution for you.
The main thing to know is that there is no "right" answer to your question which is why unfortunately it's not a great fit for StackOverflow. Here we prefer questions that have definitive answers. And this one has none.

Is there a way of having editable shared content between pages on Umbraco?

I'm relatively new to Umbraco (but have read through the docs), so I apologise in advance.
I have a partial view on a website that I want to make editable (e.g. using page properties in Umbraco admin). The properties for this partial view will remain consistent on every page it's on. Is there a way I can edit those properties in one place or is there a concept of a shared component? At the moment the alternative is going through every single page and setting the properties wherever the partial view is displayed, which isn't a great solution for the number of pages it will appear on.
I have looked around, but I haven't found anything that points me in the right direction. I'm using Umbraco 7.6.6, so I'm a little restricted in what I can do.
The Umbraco.com website has some great documentation on getting started and setting up Umbraco. Umbraco TV is great for getting up to speed quickly too.
This is a HUGE topic, which requires a conceptual explanation of how Umbraco works, and the documentation is the best place to start, but I'll try to summarise the relevant elements.
What you're looking for is a Document Type. Document Types represent the data used by Umbraco pages and are stored in the database.
You create a Document Type for your page with an accompanying Razor Template from inside Umbraco. When the page is rendered by Umbraco on the front-end the Razor view is loaded, it references the Document Type (Model) and inserts the data. The Razor views can be created from inside Umbraco or using Visual Studio. Naturally you can include partial views inside the Razor Template.
Once you've created your page(s) in the Umbraco back-end and accompanying Document Type(s), which includes Data Types (inputs - media pickers, URL pickers, text inputs, Etc.), these can reference what is called a Composite Document type which can be included\shared in more than one page, a Composite Document Type is where you'd include properties which need to appear in more than one page but which have different data, such as SEO properties.
For Global properties I tend to add these to the root or landing page, then reference it in the relevant Razor page using LinkQ, inserting the properties where and when I need them in the page. An example of this would be including something like the Google Analytics ID in the master page. A Composite Document Type wouldn't be need for that.
The Umbraco documentation on querying gives this example of getting all the Name (default properties) of each page found under the root node, which may help as a starting point for referencing Document Type properties.
// Get the children of the first content item found in the root
#foreach (var child in Umbraco.ContentAtRoot().First().Children) {
#child.Name
}

How to publish a Node but not create a link to it in Umbraco

I am trying to create a "Node Pointer" document type that allows the content manager to select one or more Nodes not located under the Home Node. This is basically so that they can select which controls to add to a page without having to create a ton of them under the page. My question is, how do I create that "Node Pointer" and publish it without a link to it being created?
Links are generated by your template, so you need to include some logic in your template to exclude those pages you don't want links to.
You can do it by checking the docTypes, or excluding items with no temlate, or use a property such as umbracoHaviHide.
Alternatively avoid creating nodes that are not pages, perhaps like so:
We often use a similar technique to create a collection of sidebar elements that are prefabricated outside the home branch, then re-used.
They are re-used by selecting the desired components via a uComponents MultiNodeTreePicker which is a property on every page that should have selectable sidebar components. This way there are no nodes under the home branch that are not supposed to be pages, hence you don't have to do anything to excluded links to them.
Edit
The CMS will give every node a URL, this generally does not matter, because if there is no template associated with the node anyone visiting that url will get the 404 page. Older versions of umbraco will serve a blank page. (pre 4.5? ish? I think?)
You can't.
If you create a node in the content area, it will always have a url associated. You can either make sure the document type doesn't have a default template, if you don't want it to be navigable, or you can assign it a blank template.
Alternatively, you could create a new media type. Media nodes do not have urls associated to them by default.

Custom folder for custom codes

We're having a restructuring on our application and currently the idea is to break the codes into Core library codes + customized codes for our developer.
I'm thinking of the possibility to have a folder (i.e. 'custom') that is empty by default, and when the developer need to customize any codes either from existing asp pages or new pages, they just need to put them into the folder and it will work. Example:
Lets say core folder store the default asp pages.
core\customer\createCustomer.asp <-- the default page
And when the developer want to overwrite that page, he needs to copy that asp page to the custom folder, like
custom\customer\createCustomer.asp <-- modified asp page
The application will automatically load the one in the custom folder rather the one in the core folder.
Is this doable in C#?
This MSDN article explains how to use an IHttpModule implementation to intercept HTTP requests and perform custom actions (they point out logging, but since you're intercepting the request you might as well fetch some different content, such as your 'customized' code).
You can use a VirtualPathProvider to load a different file than the "actual requested one". This works well with IIS and caching for instance as well.
Basically you inherit the VirtualPathProvider and override the FileExists, GetFile, and DirectoryExists, GetDirectory methods (there's an example in the linked page). Then, in your AppInitialize, register the provider with
HostingEnvironment.RegisterVirtualPathProvider(sampleProvider);
By the way, don't forget to have a different (non-editable) page so the user can revert any changes that was made, in order to restore a potential misedit so to speak. I would probably have a simple version control system and use commit whenever the user made changes, and allow the user to revert to a previous changeset.

Making Dynamically Created ASP.net Page SEO Friendly

im starting the pseudo code of a new site, and want it to be as SEO friendly as possible.
the site i am creating is a booking agency site with c# and asp.net. essentially bands will register on the site with their availability and other info, and fill out their profile information with images etc. this info will be stored in a db.
creating this is not a problem, but i want the site to be a SEO friendly as possible.
I know google loves huge sites with great content. And all of these profile pages would be an excellent addition to my site for seo purposes. i also hear that google cannot see dynamically generated content when crawling a site.
i want to find a method of coding these pages, so google can see the content when it crawls them.
i need a pointer in the right direction for a solution for this. nothing is off limits - i will basically code my entire site around this principle, i just have no idea where to start looking for a solution. im not looking for a code solution, just what i should be researching to solve this issue.
Thanks in advance
i also hear that google cannot see dynamically generated content when crawling a site.
Google can see anything you can retrieve via http GET request (ie: there's a specific URL for it) and that someone either linked to or is listed in a published xml site map file.
To make sure that your profile pages fit this, you will want to make sure that profiles are all rendered via a single asp.net *.aspx file that determines which page is shown via a url parameter. Something that looks like this:
http://example.com/profiles.aspx?profile=SomeBandName
Now, you probably also want a friendly URL, that looks like this:
http://example.com/profiles/SomeBandName
To do that, you need to set up routing.
In order to crawl and index your pages by google or other search engine properly. Follow the following guidelines.
i: Page title must be precise and according to content available in page.
ii: Page url should be user friendly.
iii: Content is king (useful content)
iv: No ajax or javascript oriented way to load contents.
v: No flash or other media files. if exist must have description via alt tag.
vi: Create url sitemap of all static and dynamically generated contents.
vii: Submit sitemap to google and keep tracking how google crawl and index your pages.
fix issues contineously if google found via crawling.
In this way your most pages and content will be index properly and fastly.
I'd look into dynamic URL Rewriting.
Basically instead of having one page say http://localhost/Profile.aspx you'll have a bunch of simulated urls like
http://localhost/profiles/Band1
http://localhost/profiles/Band2
http://localhost/profiles/Band3
etc.
All of those will then map to back to the orgial profile.aspx page with a parameter so internally in your code it would look like http://localhost/Profile.aspx?Name=Band1, http://localhost/Profile.aspx?Name=Band2, etc
Basically your website appears to have a bunch of pages for each band but in reality they are all getting mapped back to the same asp.net page but have different parameters.
This is article I read about it some time back. http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx
i also hear that google cannot see dynamically generated content when crawling a site.
you could create a sitemap.xml with the urls pointing to the dynamic profile pages. using google webmaster tools you can submit and monitor the crawling progress.
you may also create an index page or something similar ('browse by category' pages) that link to matching profile pages.
a reference for seo I regularly use is http://www.seomoz.org/learn-seo

Categories