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.
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.
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.