Forum Moderators: open

Message Too Old, No Replies

Leaving the URL alone, but loading in alternative page (for every page

How to load a page when the page URL and its physical location differ.

         

katebp

10:19 am on Jun 17, 2009 (gmt 0)

10+ Year Member



Hello,

I am looking for a way to load a page when the page URL and its physical location differ, and to load that file without rewriting the URL. For every page throughout my site.

I have a simple site CMS that generates pages according to their entry in the database and outputs a classic asp file in the format pages/14/content.asp (where 14 is the id of that page in the dbase). At the moment, for each page request (in the format www..... index.asp?pageid=14) the file index.asp loads in the site xml, matches the pageid from the URL (determining the page title, if it's a duplicate page etc) and performs a server.execute to load the correct page.

The site itself doesn't run off the database - that's just the CMS, and all the content generated is totally database independent so the db table could be moved or deleted and it wouldn't affect the site - just the CMS.

Ideally I'd like to keep the CMS but upgrade it to produce .NET sites.

So, on my .NET site - if the user entered www.mysitename.com/aboutus/wherearewe.aspx the page that would loaded would be www.mysitename.com/pages/22/page22.aspx - but the url would stay the same.

The information about both the url and the real page id would be stored in the sitemap xml.

i.e. mysite.sitemap :


<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode url="~/index.aspx" title="Home" id="1" description="">
<siteMapNode url="~/aboutus.aspx" title="About us" id="14" description="">
<siteMapNode url="~/aboutus/whoweare.aspx" title="Who we are" description="" pageid=""/>
</siteMapNode>
<siteMapNode url="~/investors.aspx" title="Investors" id="15" description="" />
<siteMapNode url="~/contactus.aspx" title="Contact us" id="16" description="" />
</siteMapNode>
</siteMap>

I had an idea that, in theory, the web.config file could load the xml, match the url attribute of siteMapNode to the actual URL and from there load in the correct page from the id attribute.

I wondered about using server.transfer but it seems a pretty server intensive way to go about things. Does anyone have any recommendations?

All sugestions welcome!

ang_bain

12:14 pm on Jun 17, 2009 (gmt 0)

10+ Year Member



Hi katebp...i think you may be under estimating the complexity of cms and getting it to produce .net sites

..or is it a new software upgrade you mean by

'Ideally I'd like to keep the CMS but upgrade it to produce .NET sites.'

your storage solution is good as long as there are only a few pages...otherwise i would use a lookup table for your pairings

on the redirection issue within dotnet...server.transfer is fine...as is good old response.redirect or the new postbackurl..

cheers

ang_bain

12:29 pm on Jun 17, 2009 (gmt 0)

10+ Year Member



Just in case i misunderstood katebp...which is quite likely..check out this link which might help

[bestechvideos.com...]

thanks
Ang

marcel

12:45 pm on Jun 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi katebp,

Here is an option for reading your Sitemap file in the Application_BeginRequest of the Global.asax. (I have used a Server.Transfer here as an example.

Remember to import the System.Linq namespace

<%@ Import Namespace="System.Linq" %>


Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)

Dim PagePath As String = "~" & Request.ServerVariables("URL")
Dim el As XElement = XElement.Load(Server.MapPath("/Web.Sitemap"))

Dim node = (From sitemap In el.Descendants() _
Where sitemap.Attribute("url").Value = PagePath _
Select New With { _
.id = sitemap.Attribute("id").Value _
}).SingleOrDefault()

If node Is Nothing Then
Server.Transfer("/Index.aspx")
Else
Server.Transfer(String.Format("/pages/{0}/page{0}.aspx", node.id))
End If

End Sub

From your example Sitemap, this would transfer www.mywebsite.com/aboutus.aspx to www.mywebsite.com/pages/14/page14.aspx
As you are from a classic ASP background I have written this in VB.Net, let me know if you prefer a c# example.

katebp

2:26 pm on Jun 17, 2009 (gmt 0)

10+ Year Member



@marcel - thanks, that looks just like what I'm looking for.

Am trying to convert it from vb now, but if you have the time to put it into c# I'd really appreciate it.

marcel

4:41 pm on Jun 17, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Here you go, in C#

public void Application_BeginRequest(object sender, EventArgs e)
{
string pagePath = "~" + Request.ServerVariables.Get("URL");
System.Xml.Linq.XElement el = XElement.Load(Server.MapPath("/Web.Sitemap"));

var node = (from sitemap in el.Descendants()
where sitemap.Attribute("url").Value == pagePath
select sitemap.Attribute("id").Value).SingleOrDefault();

if (node == null)
{
Server.Transfer("/Index.aspx");
}
else
{
Server.Transfer(string.Format("/pages/{0}/page{0}.aspx", node));
}
}


You'll also need a second import

<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Xml.Linq" %>

katebp

1:56 pm on Jun 18, 2009 (gmt 0)

10+ Year Member



That is brilliant - thanks so much for your help!

katebp

1:33 pm on Jun 19, 2009 (gmt 0)

10+ Year Member



The technique above works really well - in fact a bit too well!

It's checking every file - so, for instance, the .ashx file I'm loading in to do the CSS is getting bounced to index.aspx...

If there any way I can limit it to checking .aspx files? I had a look for a way to determine the file type from the querystring but couldn't find anything.

marcel

1:42 pm on Jun 19, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You could try this:
string pagePath = "~" + Request.ServerVariables.Get("URL").ToLower();
if (PagePath.EndsWith(".aspx"))
{
// do your stuff
}

(I've also added ToLower() to the Request.ServerVariables.Get)

katebp

10:30 am on Jun 22, 2009 (gmt 0)

10+ Year Member



Brilliant, thanks.

marcel

12:07 pm on Jun 22, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Another thing you should take into account, this works fine in theory, but if you are expecting many visitors, you should look into caching the XElement object (el).

At the moment the document is loaded from file for *every* single request (ending with .aspx). This causes an unecessary (and easily avoidable) IO load on the server.

katebp

8:51 am on Jun 23, 2009 (gmt 0)

10+ Year Member



Great thanks - I'll add it to the list!

g1smd

1:25 am on Jun 24, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



It's great that this forum has a bunch of IIS experts helping out, but everytime I look at solutions like this I boggle at how convoluted and bass ackwards the whole IIS edifice really is, compared to the simplicity of doing this stuff in Apache.

marcel

5:11 am on Jun 24, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I boggle at how convoluted and bass ackwards the whole IIS edifice really is, compared to the simplicity of doing this stuff in Apache.

If you're using this example to base that quote on, you'll have to realise that this is a custom solution as katebp wants to use the web.sitemap file as the source. (and also specifically stated no URL rewriting, although in essence that is what we have achieved with the above solution)

In IIS 6 or earlier you are correct (although there are some great third party tolls like ISAPIRewrite) but IIS 7 has made an enormous leap forward with a new plugin architecture. See modules like the URL Rewrite module [learn.iis.net] and the SEO Toolkit [blogs.iis.net].

Also, IIS 7 now uses the web.config file for almost all IIS settings, meaning that (finally!) we can configure IIS without having to use the IIS Management console, which is great news for shared hosting.