A new type of PageList

by aanund 26. May 2011 01:36

A PageList where it is possible to define different Templates for different pagetypes. More of a proof-of-concept than anything else.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.Web.WebControls;
using System.Web.UI;
using EPiServer.Core;
using System.Collections.Specialized;
using System.Collections;
using System.ComponentModel.Design;
using System.ComponentModel;

namespace Custom.Web.Code
{
    [ParseChildren(true)]
    public class PageTypePageList : PageList
    {
        private PageTypeTemplateCollection _pageTypeTemplates;

        [PersistenceMode(PersistenceMode.InnerProperty)]
        public List<PageTypeTemplateContainer> PageTemplates
        {
            get
            {
                if (_pageTypeTemplates == null)
                {
                    _pageTypeTemplates = new PageTypeTemplateCollection();
                }

                return _pageTypeTemplates;
            }
        }

        protected override void CreateChildControls()
        {
            if (ItemTemplate != null)
            {
                PageDataCollection pages = base.GetPages();
                if (pages.Count != 0)
                {
                    PageData page = null;
                    if (!PageReference.IsNullOrEmpty(this.PageLink))
                    {
                        page = this.GetPage(this.PageLink);
                    }
                    
                    if (HeaderTemplate != null)
                    {
                        Control container = new PageTemplateContainer(page);
                        HeaderTemplate.InstantiateIn(container);
                        this.Controls.Add(container);
                    }
                    
                    this.PreparePagingControls(pages);

                    for (int i = 0; i < pages.Count; i++)
                    {
                        Control control2 = new PageTemplateContainer(pages[i]);

                        ITemplate template = GetTemplateForPageData(pages[i]);
                        template.InstantiateIn(control2);

                        this.Controls.Add(control2);
                    }
                    
                    if (FooterTemplate != null)
                    {
                        Control control3 = new PageTemplateContainer(page);
                        FooterTemplate.InstantiateIn(control3);
                        this.Controls.Add(control3);
                    }

                    this.CreatePagingControls(pages);
                }
            }
        }

        protected ITemplate GetTemplateForPageData(PageData pd)
        {
            var template = PageTemplates.SingleOrDefault(t => t.PageTypeId == pd.PageTypeID);

            if (template == null)
            {
                template = PageTemplates.SingleOrDefault(t => StringComparer.OrdinalIgnoreCase.Compare(t.PageTypeName, pd.PageTypeName) == 0);

                if (template == null)
                {
                    return ItemTemplate;
                }
            }

            return template.ItemTemplate;
        }
    }

    [DefaultProperty("ItemTemplate"), ParseChildren(true)]
    public class PageTypeTemplateContainer
    {
        public int PageTypeId { get; set; }

        public string PageTypeName { get; set; }

        [TemplateContainer(typeof(PageTemplateContainer)), PersistenceMode(PersistenceMode.InnerProperty)]
        public ITemplate ItemTemplate { get; set; }
    }

    public class PageTypeTemplateCollection : List<PageTypeTemplateContainer>
    {
    }
}

With will be used as follows in the aspx:

<Custom:PageTypePageList runat="server">
    <HeaderTemplate>
        <div class="searchResults"> 
    </HeaderTemplate>
    <ItemTemplate>
        <div class="item"> 
            <h2><EPiServer:Property runat="server" PropertyName="PageLink" /></h2> 
            <p><EPiServer:Property runat="server" PropertyName="MainIntro" /></p>
        </div> 
    </ItemTemplate>
    <PageTemplates>
        <Custom:PageTypeTemplateContainer PageTypeName="[Public]Article">
            <ItemTemplate>
                <div class="item" style="border: solid 1px red;"> 
                    <h2><EPiServer:Property runat="server" PropertyName="PageLink" /></h2> 
                    <p><EPiServer:Property runat="server" PropertyName="MainIntro" /></p>
                    <p>Publisert: <%# ((EPiServer.Core.PageData)Container.DataItem).Created.ToString("dd.MM.yyyy") %></p>
                </div> 
            </ItemTemplate>
        </Custom:PageTypeTemplateContainer>
        <Custom:PageTypeTemplateContainer PageTypeId="11">
            <ItemTemplate>
                <div class="item" style="border: solid 1px blue;"> 
                    <h2><EPiServer:Property runat="server" PropertyName="PageLink" /></h2> 
                    <p><EPiServer:Property runat="server" PropertyName="MainIntro" /></p>
                    <p>Publisert: <%# ((EPiServer.Core.PageData)Container.DataItem).Created.ToString("dd.MM.yyyy") %></p>
                </div> 
            </ItemTemplate>
        </Custom:PageTypeTemplateContainer>
    </PageTemplates>
    <FooterTemplate>
        </div>
    </FooterTemplate>
</Custom:PageTypePageList>

It is admittedly a bit heavy on the control nesting.

Bookmark and Share

Tags:

c# | episerver

RedirectRouteHandler

by aanund 12. February 2011 01:34

Continuing in the same topic as the languagehandler, this RouteHandler allows you to define ‘shortcuts’ outside of the Routing system (for instance in a database). To use it, you add a catch-all route with this RoutHandler (preferrably in conjunction with a special controller to handle 404’s).

IShortCutProvider shortCutProvider = ...;

Route possible404 = new Route(
    "*",
    new RouteValueDictionary(
        new { controller = "fault", action = "404" }
    ),
    new RedirectRouteHandler(shortCutProvider)
);

routes.Add(possible404);

Uses a simple interface to check for available shortcuts.

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace austrheim
{
    public class RedirectRouteHandler : MvcRouteHandler
    {
        private IShortCutProvider _shortCutProvider;

        public RedirectRouteHandler(IShortCutProvider shortCutProvider)
        {
            _shortCutProvider = shortCutProvider;
        }

        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            string newUrl;

            if (_shortCutProvider.TryGetShortCut(requestContext.HttpContext.Request.Url, out newUrl))
            {
                return new RedirectHandler(newUrl);
            }

            return base.GetHttpHandler(requestContext);
        }
    }

    public interface IShortCutProvider
    {
        bool TryGetShortCut(Uri requestUri, out string newUrl);
    }

    public class RedirectHandler : IHttpHandler
    {
        private string newUrl;

        public RedirectHandler(string newUrl)
        {
            this.newUrl = newUrl;
        }

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext httpContext)
        {
            httpContext.Response.StatusCode = 301;
            httpContext.Response.RedirectLocation = newUrl;
        }
    }
}

When a url is entered that does not match any routes, it will trickle down to the catch-all route.

The catch-all route then checks if a shortcut is found, and the viewer will be redirected to the shortcuts destination.

Bookmark and Share

Tags:

mvc | c#

Forms login and friendly url

by aanund 30. January 2011 01:33

Sometimes (often) you need to switch the default EPiServer login page (~/util/login.aspx) with one of your own. And using EPiServer, sometimes you would like to use an EPiServer page (friendly url and all) as the login page. This can pose something of a problem.

This is caused by a combination of the Login control and the AuthenticationConfig (internal static class) which contains a method, that will do a string comparison on FormsAuthentication.LoginUrl  and Context.Request.Path (which will be the filename of the page).

To overcome this, you can for instance do…

<asp:Login ID="LoginControl" runat="server" OnLoggedIn="LoggedIn" />

And then in codebehind…

protected void LoggedIn(object sender, EventArgs e)
{
    Response.Redirect(GetRedirectUrl(), true);
}

private string GetRedirectUrl()
{
    string returnUrl = FormsAuthentication.GetRedirectUrl(string.Empty, false);

    if (!string.IsNullOrEmpty(returnUrl))
    {
        return returnUrl;
    }

    string str2 = LoginControl.DestinationPageUrl;

    if (!string.IsNullOrEmpty(str2))
    {
        return base.ResolveClientUrl(str2);
    }

    return FormsAuthentication.DefaultUrl;
}

Now your page will beautifylly redirect.

Bookmark and Share

Tags:

c# | episerver

About me

I work for EDB Consulting Group in Oslo, Norway.

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010