A quick post to say that I’ve finally uploaded my shared source ‘Redirect Manager’ module to http://trac.sitecore.net/RedirectManager/
A picture speaks a thousand words, so you should get the idea from this :
Key features
- Shell – displays links for current item, redirects, and aliases.
- Automatic 301 record generation of historic links (renamed, moved, or even structural changes)
- Manual 301 record generation via right-click or ribbon.
Publishing any item clears the redirect cache. (required after manual redirect creation).
Performance
Rough tests with 100,000 redirect records :
Preload delay: 150-250ms (loads into lookup cache, on startup or after publish)
Http processor delay: roughly 0.15ms (~373 ticks)
See the main trac page for download and install instructions.
Enjoy!
This looks really nice. Thanks for creating it and sharing.
Awesome, looks pretty nice. Thanks for sharing!
Hi Paul,
First off, thanks for what looks like an excellent module. It’s exactly what I want for a client I’m working with. However, I’m having a few issue that maybe you can clear up for me.
There appears to be a bug in the module when it comes to query strings. I can add a redirect URL that contains a query string, but it appears as if the query string is ignored in the lookup. Also, once you’ve added a redirect with a query string, you can’t delete it. It throws an exception.
The reason I’m asking is because the client I’m working with is migrating from an old in-house developed CMS that uses query strings extensively. I am required to redirect from e.g. “/foo/bar.asp?id=some page name”.
I haven’t had a close look, but how’s the support for CM/CD environments? Since the module uses its own database, I’m guessing that’s a no-go unless all CD servers also have access to the database?
Cheers,
Rickard
Hi,
Thanks for your comment. The module currently works by looking at the request path only, everything else (i.e. protocol, host or domain, querystring, fragment) is ignored. This is compared in a case-insensitive manner to the stored redirects, which themselves are expected to be just url paths. There’s obviously some validation (or rather my hidden assumptions) missing there.
While I understand your requirement to redirect different querystring urls to different targets, it is also a feasible requirement to want to ignore different querystring parameters and redirect any request to a url path to a nominated target (this should be the current behaviour).
CM/CD environs – I guess its the same for the other shared databases, like core or security. The module is not database aware. Early versions were, and also stored redirects as sitecore items, but that was dropped due to the performance benefits of using a real SQL db, which in turn made automatic 301 handling possible (to be explained in another post). Entirely untested, but you could host the redirect DB in the live environment, and connect to it from the CM environment (same as some scaling configs). You would need to be aware that the data is shared, so redirects created are immediately live as far as SQL goes (still requires cache to be cleared).
Thank you for your answer.
While I agree that being able to ignore query strings is a feasible requirement, in my case, I need them. Based on your comment though, I’m guessing I shouldn’t wait up for a new version of the module that supports query strings? 🙂
I understand regarding the CM/CD situation. The issue in my case is that we have multiple CD servers that are geographically separated so that latency becomes an issue. A CD server in Japan can’t rely on a SQL server in the UK. In order to use this module, we would have to setup SQL replication.
Cheers,
Rickard
Regarding CM/CD locations, it’s a tricky problem. Originally I went down the route of storing redirects as sitecore items, settings their display name as the url path and so on. This was so that the module would just run ‘out-of-the-box’ It worked fine, but 2000 sitecore redirect items took something like 4000ms to load into the dictionary cache. This would mean that geographic publishing would work as ‘normal’ in Sitecore terms, but the speed would rule out automatic redirect feature, which relies on creating a ‘redirect’ record of item as they are published, or in other words, you store (numberOfContentItems + subsequent item name changes), not just records when something changes. Using SQL instead of Sitecore items I could load 100,000 records in around 200ms (and on just a laptop), which makes this approach very viable.
I felt that automatic 301 redirects was such a useful feature that I ditched all the original work and just used a simple SQL provider instead. I detailed some of this at the Sitecore London user group a few weeks ago in early Feb. I may have an idea for how to mix these two approaches, but I need to check a few things out first.
Hi Paul,
I am running into a publishing error. Below is the error, I got while publishing.
Am I missing something ? Any suggestions ? Also I found a forum post on this topic – http://sdn.sitecore.net/SDN5/Forum/ShowPost.aspx?PostID=44085#44085
Job started: Publish to ‘web’|#Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.UriFormatException: Invalid URI: The format of the URI could not be determined.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at RedirectManager.Pipelines.PublishItem.Processor.Process(PublishItemContext context)
at (Object , Object[] )
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Publishing.Pipelines.PublishItem.PublishItemPipeline.Run(PublishItemContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessEntries(IEnumerable`1 entries, PublishContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.Process(PublishContext context)
at (Object , Object[] )
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Publishing.Pipelines.Publish.PublishPipeline.Run(PublishContext context)
at Sitecore.Publishing.Publisher.Publish()
— End of inner exception stack trace —
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at (Object , Object[] )
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Jobs.Job.ThreadEntry(Object state)
Please post your ‘linkmanager’ and ‘site’ configuration from web.config
Hi,
I am experiencing the same problem. The error message appears only when the attribute “hostName” is defined in the “” section in web.config.
Hi,
I can’t currently reproduce this, with or without a hostname attribute defined. Can you describe your config again or send me an email to paul {at} (this domain)?
Thank you Jørn – I finally managed to spend some time on this. This issue is caused by the linkmanager generating links without a scheme, i.e. starting with :// instead of http:// . This happens only when a single host name is specified in the site definition.
This is turn throws a url parsing error which is now caught and logged but the redirect is not generated.
This can be addressed by adding scheme=”http” to the site definition when the host attribute is used. Additionally, a fix has been added to the module source to add ‘http’ as a default scheme if LinkManager generates a link without one.
An updated module should should be released shortly via Codeplex.
Trying to understand how this hooks into sitecore; I don’t see the class library referenced in any of the config files; so how does sitecore know to load the RedirectManager library. Have a setup where there is a staging server – which has a core/master/web and then a production server that shares the core and has it’s own web (databases). So installing on staging server is easy (typicall package install) – but can’t seem to get the library to load on the production server.
What settings are necessary to make it work in this scenario?
Any help would be appreciated.
thanks.
Figured it out; it was through the additional include which inserted a pipeline for it.
I’ve modified my current version to support regex if anyone is interested.
Hi,
How are you storing your regular expressions?
I store them as a regular string (formatted as regex). I modified the collection/dictionary that is being used to locate the url to first generate a regex object based on the string/url being passed and then tries to match each.
Hi Paul,
Is there a dialog which shows up all url redirects that are entered? Is there a way to define redirects like
I want every request likt /company/(.*) redirected to /company/new-structure/$1?
Thanks,
David
Hi,
Wildcards are not currently supported, although I believe that a different module, the “301 redirect module” supports regex, which sounds like it will do what you want.
Hi Paul,
Thank you for your reply. Yes, the 301 redirect module does support regex. I like the approach of using a database. But what am I missing is a list of all redirects applied. Furthermore, not all redirects are always bound to an item (e.g. when you use regex, but as it is currently not supported this is not the problem). but anyway, a list of all redirects would be cool to fast add, remove, delete, delete all..
Best Regards,
David
Hi,
With MaxItemNameLength set to 100, When we create a redirect it fails. how can we add long item urls. also the RequestPath column length in the database is set to 255. that means its not going to work for url longer than that. Is anyone facing the same problem. Should we not change to the max to supported browser length ‘ 2,000’ or more.
Cheers
S
This project is now hosted on Codeplex. An updated version of this module has been packaged as v0.5.
As well as many minor changes, this fixes a critical issue with url language prefixes and also changes the DB storage of urls to NVarChar 400 to cater for longer urls.
I have been looking for a redirect solution and was originally using the sitecore item version which never seemed to work and does not seem to be supported any longer. I installed this package. Created the database. Added the connection string. I can now create the redirect link in Sitecore, but when I test it out, I just get the usual 404 page. Am I missing something?
Anthony – The module is added to the request pipeline by dropping RedirectManager.config into the the \App_Config\Include folder. Check the logs, there should be something there.
I was able to get the redirects to work. It was actually a great problem of not getting the CD cache refreshed on publish. I was asked about the wildcard option today. I see from your other post that there’s a 301 redirect module that can handle that. I cannot find it. I also noticed that this module does not work with media items. So we installed a non-sitecore related redirect application to handle the media files, and are using this module for page redirects. The last thing I want to do is add a 3rd redirect module into the mix. Any suggestions?
Was the CD cache issue a problem with the module itself?
I did modify the redirect module to support regex – if you want the code.
Hello, thanks for your hard work.
I installed the packages in sitecore whenever I select the content editor, I get this error message:
Redirect Manager SQL Provider: connection string entry not found for ‘RedirectManager’
Is there something I didn’t install correctly?
Thanks,
Jey
You need to add new connection string with name ‘RedirectManager’ and specify the database you’ve created via SQL query in your ConnectionStrings.config.
I have used this tool on v6.5 and it worked great. I now need same functionality on V7.1.
What changes need to be done to get this module working for v7.1? Or does anyone have a beta version of this module that could work on v7.0 or greater?
Thank you.
Hi Paul,
I am running into a publishing Media item error. Below is the error.can you Please suggestion on this issue
Job started: Publish to ‘web’|#Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.ApplicationException: Redirect Manager failed parsing item url generated by linkmanager. Url : ~/media/napocska.ashx ItemId : {B4F98E43-80E2-4247-A775-71A25B3B88D7}, —> System.UriFormatException: Invalid URI: The format of the URI could not be determined.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
at RedirectManager.Pipelines.PublishItem.Processor.Process(PublishItemContext context)
— End of inner exception stack trace —
at RedirectManager.Pipelines.PublishItem.Processor.Process(PublishItemContext context)
at (Object , Object[] )
at Sitecore.Pipelines.PipelineMethod.Invoke(Object[] parameters)
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args)
at Sitecore.Publishing.Pipelines.PublishItem.PublishItemPipeline.Run(PublishItemContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.ProcessEntries(IEnumerable`1 entries, PublishContext context)
at Sitecore.Publishing.Pipelines.Publish.ProcessQueue.Process(PublishContext context)
at (Object , Object[] )
at Sitecore.Pipelines.PipelineMethod.Invoke(Object[] parameters)
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args)
at Sitecore.Publishing.Pipelines.Publish.PublishPipeline.Run(PublishContext context)
at Sitecore.Publishing.Publisher.PerformPublish()
at Sitecore.Publishing.Publisher.Publish()
— End of inner exception stack trace —
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Sitecore.Reflection.MethodInstance.Invoke()
at Sitecore.Jobs.JobRunner.RunMethod(JobArgs args)
at (Object , Object[] )
at Sitecore.Pipelines.PipelineMethod.Invoke(Object[] parameters)
at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists)
at Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain)
at Sitecore.Jobs.Job.ThreadEntry(Object state)
Pingback: SQL Based Sitecore Redirect Manager (now with QueryStrings!) | Cortex Exodus
Hi Paul,
Will this module work for a media item to other media item redirect.
i.e,
http://www.sai,com/~/media/Files/sai1.pdf
to
http://www.sai,com/~/media/Files/sai2.pdf