Advanced Language Manipulation Tool for EPiServer

Have you ever (or have your customers) created and edited a page in one language only to realize that their selected locale was wrong? Have you ever wished you could delete a master language branch of a page  after creating its localized counterpart but you could only delete the newly created slave language instead? Have a customer ever requested that they could copy a whole branch and you convert it to another language so that they could then translate in-place?

Well I have… and I’m sure I will. And so did Fredrikj on the our #epicode IRC channel ;).

Basically I had the tool that would convert from one language to another, but Fredrikj requested something that would switch master language of a page from one to another. Since I’ve already had some of the work done, I’ve updated the stored procedure I’ve written some time ago and slapped a nice GUI up on it. Here’s the result:

 

AndvancedLanguageTool

What the tool allows you to do is perform either language conversion or master branch switching on a selected page and all of its children (if you choose so).

The stored procedure have been updated to work on CMS5 R2 (will no longer work on R1 – but if you need that functionality, comment here or give me a shout and I’ll create a compatible version for you).

A word of caution though – I take no guarantee whatsoever about its operation. Especially, if you wreck your client’s database with it. I did what I could to prevent some of the obvious problems (like switching to a non existing master or converting to an existing one) but I will not be responsible if it won’t work for you. make a database backup and experiment there before you do any changes on the real data. That said – it works for me, so I think it should also work for you.

You can download the archive containing the tool here. unzip it to your EPiServer web application folder keeping the folder structure or the plugin reference will be wrong. Include the *.aspx and the *.cs files in your project and apply the SQL file to your database (The manipulation is performed by a stored procedure located in the file).

Also if you’re performing the change in a load balanced environment, you may need to restart the other servers once you do the changes. I reset the DataFactory cache, but I am not sure it propagates through to other servers.

Once you’ll update the framework to the extended one, you will immediately notice that… nothing has changed. Hmm… did something go wrong?

Well, not really. By default the framework will be run in the “legacy mode”. Thanks to an old article by our own Marek Blotny, I’ve learned how to build Plugin settings which are just perfect for the purpose!

So to configure and enable the new features you need to open your admin UI and in the “Config” click on the “Plugin Manager” item and select our framework plugin as shown in the picture

WebPartFrameworkPluginSettings1

The available options are:

Read the rest of this article »

Back in the day when we started designing our last project we’ve been presented with a following problem – a big number of templates with slightly different sidebars.

Hmm…

Is sidebar a part of content? No, rather not. We don’t want the editors to have to setup the sidebar for every article they write (and the site has a few dozens of articles created on it every day).

Is sidebar more of a template thing? Well… more like it, but still… we have articles all over the site with different sidebar elements when the articles are in different parts of the site (ok so we could add rules what controls display in which part of the site). But wait! There’s more! The sidebar will be different for every language (region). Now we’re talking a dozen of templates or a rules engine just to make the sidebar different. Customising the template with properties isn’t ideal either as it makes EPiServer UI very cluttered. Additionally we want to change sidebars across many templates so the whole branch/section of the site will be able to share the same sidebar.

To a degree this is an academic discussion as we’ve been through it with the previous version of the site and we already knew that integrating this stuff into templates just won’t work and we will be in a world of pain just changing the templates over and over adding little tweaks and changes while the customer ads promotions and performs ad campaigns. Well, we can do it, of course, but it’s not a work a programmer will enjoy, and we all want to do new and more exciting things, don’t we?

We have an internally developed  module to make something like that, that is fully home-grown by another internal team (we now have 3 “squads” capable or making incredible things with EPiServer and we tend to share a lot of technologies and try to rotate people around to adopt the good habits and experiences) and I was (and still am) VERY impressed by it. The technology uses EPiServer pages for defining every module (which are located somewhere outside the site root branch. and then you can mix and match them either declaratively in the code) or by handpicking them in the UI. It’s really cool, though, during the discussions it turned out that we might have to add big chunks of functionality and might end up with separate branches of module-pages for different languages/regions, but… frankly… about that time an article by Ted Nyberg reminded me about a technology I have read about quite a while ago in an article by Stein-Viggo Grenersen and ooohhhhhh… I got seduced. I really wanted to try if for a long time and Ted’s article made it a snap to try and get convinced, and more important… convince Stu ;) that it’s the right way to explore.

So I started to dig.

Read the rest of this article »

The configuration of the module is a descendant of any EPiServer Virtual Path Provider configuration. This aspect is fairly well described on EPiServer pages.

A sample configuration for the TextImageVirtualPathProvider can look as follows

<configuration> <episerver> <virtualPath <providers> <add showInFileManager="false" virtualName="Text Images" virtualPath="~/TextImages/" bypassAccessCheck="false" name="TextImages" type="Cognifide.ImageVirtualPathProvider.TextImageVirtualPathProvider,Cognifide.ImageVirtualPathProvider" physicalPath="C:\temp\TextImages" allowedReferers="(localhost)" allowNullReferrer="false" replacementStrings="$colon$,:,$gt$,>,$dot$,.,$quot$,&quot;,$amp$,&amp;,$star$,*,$eol$,&#10;,"/> </providers> </virtualPath> </episerver> </configuration>

 

where:

  • physicalPath is where the cached version of images will be stored
  • shownInFileManager is “false” as there is nothing to present for the user in the file manager.
  • allowedReferrers is the regular expression containing the filter for sites that are allowed to access the path provider and get images. This has been added so that your server does not turn into the internet’s text-image open service :)
  • allowNullReferrer should be set to false in production environment but allows for testing by directly creating URL’s without using a page to fill in the referrer.
  • replacementStrings – this one actually turned out to be very useful since some characters are invalid and not even reaching the VPP if EPiServer or ASP detects them. so to allow for characters like colon or < or even a dot (which would make it hard to form regular expression if it was explicitly available) or * you need to create an escape token for them. The string is a coma separated list of token,value,token,value,…
  • virtualPath is something you need to change if you want your VPP to serve images under a different root level folder. (e.g. if you have a page with that name already)

 

Additionally for IIS6 (most common scenario) you need to add <location> node to configuration for the VPP to work.

<configuration>
  <location path=TextImages>
    <system.web>
      <!– Setup the StaticFileHandler for the wildcard mapping to work in IIS6–>
      <httpHandlers>
        <add path=* verb=GET,HEAD type=System.Web.StaticFileHandler validate=true />
      </httpHandlers>
    </system.web>
    <staticFile expirationTime=-1.0:0:0 />
  </location>
</configuration>


Unless you want to change the location of the virtual path provider can be found under, there is nothing you need to change here.

The code is accessible on EPiCode, but you can also download a compiled binary here. All you need to do then is to unzip the archive to the “bin” folder within your site and set the web.config values to your preference.

CogniScale – virtual hosting made easy

We’ve not been talking much about it and that’s partially my fault as well (busy with other projects), but Cognifide has a really cool initiative called Cognifide Labs that we intend to grow over time. The plan is to devote up to 10% company time into side projects that help us grow expertise and allow our devs to dwell into interesting technologies, methodologies and languages and develop their skills.

One of the first projects (that I took part in) is CogniScale – an app that allows FlexiScale users to manage their servers. Here’s the story…

Being the agile company taking part in many EPiServer projects we never seem to have enough environments to test our web-apps and software in general in various scenarios. We find ourselves constantly reinstalling and trying to keep our servers in a state that can can at least remotely be called as stable. After all how many deployments and tearing down of various EPiServer, CruiseControl, TeamCity, SQL Server and other "I need to have" apps can a server take before slowing down to a crawl or collapsing all together (that said I bow before our faithful THOTH for taking all the abuse it does). We definitely needed more servers! And we needed them now!

Early this year we’ve started to talk to the guys at XCalibre that came up with a great idea. What if you could have an unlimited amount of servers available for you at any given time? I mean really what if you could have 0 servers one day and the next day have a rich farm of servers for literally no cost, paying only when you power them up and not paying a bit if you take them down.  This turned out to be quite a project for them that turned to materialize as FlexiScale. (you can read more about it here). Looking at all that I’ve mentioned before while eliminating the cost of maintaining the servers locally we decided to give FlexiScale a spin.

Read the rest of this article »

Google Maps control (property) for EPiServer

Since my effort towards making this control final has been somewhat limited lately, I’ve decided to simply release the code at its current stage so that others can play with it and perhaps we can have something decent done together. The control operation is described in my previous article therefore I will not be going much into it any longer. the deployment of it is something worth mention though…

Download the control form here. Extract the contents of the zip file to a folder and attach the project to your solution, make sure you have the proper EPiServer libraries referenced form the project or it may complain about the references being broken.

Once you have it compiling, copy the GoogleMapEditor.ascx, GoogleMapViewer.ascx and the contents of the resources folder to a folder named GoogleMap within your project folder. Also copy the contents of the lang folder to the lang folder of your site.

The controls the property instantiate try to be smart about resolving the location of its files, but the property does not know its location thus if you decide to place the scripts in a folder other than just GoogleMaps in the app main folder, you need to add to your web.config the following:

<add key="CogGoogleMapControlLocation" value="\GoogleMaps\" />

And in web.config you define the API keys for all the addresses the control will be available from as “CogGoogleMapApiKey_%HOSTNAME%” values.

e.g. set for my machine localhost (for me) & dune(for access from other computers within our network):

<add key="CogGoogleMapApiKey_localhost" value="A value generated for 'localhost'" />
<add key="CogGoogleMapApiKey_dune" value="A value generated for 'dune'" />

The controls determine by themselves which key to use based on the http request so that the Google API does not complain about the key being improper.

Other than this the control should be self registering and all you need to do is to add it to your Page Type in the Admin section of the site and add:

<EPiServer:Property ID="GoogleMapData" runat="server" PropertyName="GoogleMapData" />

to the template you want to use it with.

The control really needs an improved support for translation the stuff currently there is used for learning more that than to actually be useful. Should we decide to go further with it, it definitely will be extended.

The scripts used for the DOPE editing are released under GPL (the scripts were originally released with the MediaWiki GoogleMaps editor under the same license). Those scripts although modified slightly are also released under GPL and are NOT a part of the control – they just happen to be used by it. I am still trying to decide what license use with the rest of the control, so be aware that this is still a subject to be changed, for now just feel free to use the code and should you make any changes to it, please feed them back so that I can improve the control further. The control will most probably end up as a part of Epicode, as soon as I get a response on the epicode forums from Steve on how to add them.

To finalize my mini series on the object store I’d like to put a simple page comments library. The library takes care of everything that is required for you to post and retrieve a list of comments. It does not (so far) offer any moderation functionality or even facilitates any comments removal. It’s something that I will most probably be added in the process.

I am in the process of figuring out how I can contribute it through the Community EpiCode effort on CodeResort. As soon as I get some answers from Steve, I’ll get it uploaded there. In the mean time let me document how to start using it.

For the time being you can get the code here or the compiled library with the intellisense help form here.

Posting comments

the posting is somewhat manual in terms of not having a pre-made control for it. Which if you look at the code does not have much sense to have.

All you need to do is put two edit boxes on a page and a submit button, and then bind the action of the submit button to a code looking somewhat like:

protected void SubmitComment(object sender, System.EventArgs e)
{
    IPageComment newComment =
        PageCommentFactory.createInstance(Guid.Empty,
        string.Format("CommentForPage{0}", CurrentPage.PageLink.ID),
        CurrentPage.PageLink.ID,
        SubjectTextBox.Text, ContentTextBox.Text, DateTime.Now, false, true, false);
    newComment.Save();
}

I honestly don’t feel like making a custom control for creating those would be worthwhile since no one would end up using it anyway.

The listing of comments however…

The comments can be accessed in a number of ways.

Probably the easiest one would be by using the templated control I’ve written in the library, which is a simple descendant of the ASP.NET repeater. The page could would look something like:

...

<%@ Register TagPrefix="CognifideControls"
    Namespace="Cognifide.EPiServerControls.PageComments.Controls"
    Assembly="Cognifide.EPiServerControls.PageComments" %>

...


<CognifideControls:PageCommentsList ID="CommentControl" runat="server"
    PageLinkIdProperty="<%# CurrentPage.PageLink.ID %>">
    <ItemTemplate> 
        <b><%# CommentControl.CurrentComment.Title %></b> - 
        <%# CommentControl.CurrentComment.SubmitDate.ToString() %><br />
        <%# CommentControl.CurrentComment.Content%><br /><br />
    </ItemTemplate>
</CognifideControls:PageCommentsList>

I’ve chose this way since that’s pretty much the standard way of adding controls that are defined in Episerver and just generally ASP.Net.

But nothing stops you from accessing the comments directly,  and then filling in the data for the repeater yourself like:

<asp:Repeater ID="CurrentComments" runat="server" 
    OnItemDataBound="CurrentComments_ItemDataBound"> 
    <ItemTemplate>
        <b><asp:Label ID="CommentSubjectLabel" runat="server"></asp:Label></b><br />
        <asp:Label ID="CommentContentLabel" runat="server"></asp:Label><br /><br />
    </ItemTemplate>
</asp:Repeater>

And then in the code-behind

protected void Page_Load(object sender, EventArgs e)
{
    List<IPageComment> comments =
        PageCommentFactory.GetCommentsForPage(CurrentPage.PageLink.ID, 
        DateTime.MinValue, DateTime.MaxValue, true);
    CurrentComments.DataSource = comments;
    CurrentComments.DataBind();
}

protected void CurrentComments_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    IPageComment comment = (e.Item.DataItem as IPageComment);
    Label commentSubjectLabel = (Label)e.Item.FindControl("CommentSubjectLabel");
    if (comment != null)
    {
        commentSubjectLabel.Text = comment.Title;
    }
 
    Label commentContentLabel = (Label)e.Item.FindControl("CommentContentLabel");
    if (comment != null)
    {
        commentContentLabel.Text = comment.Content;
    }
}

That’s pretty much what my implementation does anyway.

I hope to be able to put it up on CodeResort soon so that we can see what else could be done. Additionally my library allows for replacing the persistence provider, which we will probably have implemented using nHibernate to test its speed versus the ObjectStore. Should you be interested in providing some help with this, or adding come moderation code to the admin side of the site on top of the interface, it would definitely be greatly appreciated.

I have started implementing the Property based on the code so that it can be easily displayed on the editor’s page, but for now, I’ll have to delay it since we’ve got some other stuff to do related to the project I’m currently working on.

Posted in ASP.NET, C#, Downloadable, EPiServer, Software Development, Web applications
1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 3.67 out of 5)
Loading...
| Leave a Comment »

Skype GeoLocation Tool

Download source files – 103 Kb
Download the Skype Geo Location tool – 52 Kb

Application GUI

Introduction

It’s a real joy to work in a international company, the problem we face are hardly ever matched by some locally based endeavours…

As some of our friends here at work, you may choose to reveal your current location to your skype buddies. This is nice and easy since you can just put it in your name or description and everyone will see where you are.This poses a problem should you really travel frequently, it is more likely than not, that your location tag will be out of sync.

As this is a something that happens for them once in a while I found it an interesting concept, fun enough to be worth solving it :)

So how does one establish his location? Short of installing a GPS on your machine, I would suggest checking your IP address and translating it based on one of the available databases.

The thought process goes as follows… [Read about the technical guts of the application in my article at Code Project]

The Convergence – The Application

The application helps you maintain your location tag in your name so that whenever you travel to a different town your skype name/description will reflect it.

Disclaimer: The application uses GeoIPTool as its source of IP and geo-location. Visit GeoIPTool for a wide variety of web based geo-location tools.

It does not contain either any kind of tracking abilities other than it letting you to maintain your location tag. The application will not even change your location tag by itself but rather it will notify you that your location has changed and will allow you to change your tag with a simple press of a button.

Usage
In your skype account set your name or description so that it has [] in it or press “Add location tab to…” in the application. Whenever the application will find those it will check if the text in the parenthesis matches your current location., if it does not it will suggest a new one and will highlight the relevant field red. You may set for this operation to be performed on every boot, you will however only be notified when/if your location actually changed.

Most of us here use Pandora for the listening to the music with their headphones.

The keyboards we have at the office do not have any sound volume adjusting keys.

It’s mildly annoying that you need to take off your headphones every time someone talks to you or click the system tray every time the musinc is too quiet or too loud. But hey! What do we have CodeProject and Visual Studio for?

Quick investigation on CP allows to determine that there is a way for a DotNet app to both control the system volume and hook the keyboard events fairly easily.

Half an hour later…

We have a little tray application for adjusting the system volume control

The only visual indication of the app running is a tray icon. While it is running you can:

  • Ctrl + Alt + Up Arrow – Volume up
  • Ctrl + Alt + Down Arrow – Volume down
  • Ctrl + Alt + Scroll Lock – Mute / Unmute
  • Click the icon to het a baloon tooltim with those hints
  • Right click the tray icon to close the app.

The icon has been taken from the Dementæcon icon pack by MindlessPuppet.

Posted in .Net Framework, C#, Downloadable
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...
| Leave a Comment »

UpTime.Net

PerformanceCounter pc = new PerformanceCounter(“System”,
    “System Up Time”);

 

//Normally starts with zero. do Next Value always.

pc.NextValue();

TimeSpan ts = TimeSpan.FromSeconds(pc.NextValue());

MessageBox.Show(Environment.MachineName +

    ” has been up for \n\n” +

    (ts.Days < 1 ? “” : ts.Days + ” days, “) +

    (ts.Hours < 1 ? “” : ts.Hours + ” hours, “) +

    (ts.Minutes < 1 ? “” : ts.Minutes + ” minutes “) +

    ” and “ + ts.Seconds + ” seconds.”);

Nice, neat and simple.

Get a compiled executable here

Posted in .Net Framework, C#, Downloadable
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...
| Leave a Comment »