Can I route specific pages through specific controlllers?

Vote:
 

What is EPiServer MVC's capacity to route specifc pages through specific controllers?  Not page types, but actual, single pages.

Say I have 1,000 articles in my system.  I want all requests for those articles to be handled by ArticleController...except for Article #459.  I want that one to go through SpecialArticleController.  It's the same page type ("Article Page"), but I want it to just route that single page through a different controller.

Granted, this is a ridiculously contrived example, but here's what I'm trying to do --

Most sites generally have at least some application-ish functionality.  These are pages which aren't content so much as little applications of some sort.

Now, in MVC, it's super easy to just hook up a new route, write a new controller, etc.  The problem is that to render properly, a request usually has to be in the context of a page.  For the master layout to work, for instance, it has to know where this page lies in the navigation, etc.

Stop now and read this -- this will all make more sense:

"Using Proxy Content Objects for Non-CMS Content"
http://gadgetopia.com/post/7088

So, my little application has to "represent" a page in the tree in order for it to render property.  This being the case, I want to create a page "wrapper," but handle that page with its own controller.  So all pages will go to Controller X, but this one will go to Controller Y.

Now, a way around this might be to write my application as a block, then just embed that in a page.  This would work, but it seems odd to me.  I don't like the idea that someone can delete or remove this block that's really foundational to the page.  I don't like the idea of the main purpose of that page being so...temporal.  (Maybe this is irrational...?)

So, my original question is how to route specific pages through specific controllers, but my larger question is: am I thinking through this correctly?

#79313
Dec 13, 2013 8:59
Vote:
 

Routing in EPiServer is to content (what I mean is that during the routing step no attention is taken to how the content should be rendered). After routing is done (that is a content has been decided/found) a call is made to TemplateResolver which then selects which template that is most suitable to handle that content item (it can then return e.g. a WebForm, a MVC controller or a HttpHandler).

So what you probably want is not to hook into routing but instead hooki in to TemplateResolver and say that for this specific page I want to use this controller. Templates are registered per type but there is actually two events TemplateResolver.TemplateResolving and TemplateResolver.TemplateResolved where you can specify which template to use. In the eventargs you have the actual instance to render so there can you check if it is your "special" page and if so set your special controller to handle the request.

#79338
Dec 13, 2013 12:44
Vote:
 

This is great, Johan.  Exactly what I needed.

My only question is the phrase "set your special controller."  I've looked through the SDK, all the samples, and your blog post, and I'm fuzzy on how to change the controller.  It has something to do with SelectedTemplate, but I'm not sure what the correct syntax is for changing this.

#79358
Dec 14, 2013 0:30
Vote:
 

Hey Deane, this should help, you can also use tags as well

[InitializableModule]
    public class MobileRedirectSample : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            context.Locate.TemplateResolver().TemplateResolved += MobileRedirectSample_TemplateResolved;
        }

        public void Uninitialize(global::EPiServer.Framework.Initialization.InitializationEngine context)
        {
        }

        private void MobileRedirectSample_TemplateResolved(object sender, TemplateResolverEventArgs eventArgs)
        {
            if (eventArgs.ItemToRender != null && eventArgs.ItemToRender is PageData &&
                eventArgs.WebContext.Request.RequestContext.GetContentLink() == new ContentReference(459))
            {
                var specialTemplate = eventArgs.SupportedTemplates
                    .SingleOrDefault(r => r.Name.Contains("YourSpeacialPageController"));

                if (specialTemplate != null)
                {
                    eventArgs.SelectedTemplate = specialTemplate;
                }
            }
        }

        public void Preload(string[] parameters)
        {
        }
    }

    

#79359
Edited, Dec 14, 2013 7:59
Vote:
 

I saw this sample, but I'm not sure it's exactly what I need.  This line seems to be the important line, but how do I get a controller into the "SupportedTemplates" collection?

var specialTemplate = eventArgs.SupportedTemplates
                    .SingleOrDefault(r => r.Name.Contains("YourSpeacialPageController"));



#79360
Edited, Dec 14, 2013 13:12
Vote:
 

It is a very important line,  What it does is since a page can have multiple templates, ie, starndard page, standard page with a tag, and so one,  we are just specifing out of the supported templates which controller(template) we want this template to use.  

So, since we have a page type called News, NewsPageController: PageController<NewsPage>, you can also have a controller like this as well, NewsListingPageController : PageController<NewsPage>.  With that said, you can also have another controller with a templatedescriptor on it as well, since the page is oftype(NewsPage), this is how the supported templates are filled is based on their algorithm for finding the pages,

#79361
Dec 14, 2013 16:19
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.