Secret plans

Andrey stumbled upon my secret factory in Rotebro, plans for world domination foiled once again! I will get you yet Zhukov!

Posted in crazy stuff | Leave a comment

Visual Studio copy, paste & freeze

The problem

After I installed Visual Studio 2010 I started experiencing that the IDE would freeze for 20+ seconds after I pasted a code snipped in markup edit mode. I had the same issue on my home computer also running Visual Studio 2010.

As you may suspect this became a bit frustrating quite fast.

Fumbling in the dark

I found some MS post suggesting re-installing Visual Studio / Windows or whatever but really, who would do that, really?

Also some MS people suggested that the issue may be not enough RAM for the copy paste operation. Since I have 4GB on both computers and monitoring the memory usage during copy paste at ~2GB it did not really feel like the culprit in this case.

I did find some promising theories out there, like add an exception to your antivirus not to scan your project files – did not work.

Maybe uninstalling Microsoft Visual Studio Web Authoring Component? Seemed like a good idea in general since its just some Frontpage crap – but didn’t help much.

I did find a hotfix from Microsoft with the description (Patch Available for Cut or Copy displaying “insufficient memory” error in VS 2010) not quite my scenario but hey, they seemed related so I installed it, took a long time - did nothing.

The solution

By this time I was quite fed up with this shit, I could not get any real work done with Visual Studio behaving like this. So I started looking at warnings and stuff and did find that there was a typo in the web.config in a sectiongroup.

<configuration>
  <configSections>
    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScrpingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
       ...
      </sectionGroup>
    </sectionGroup>
  </configSections>
</configuration>

The sectionGroup “scripting” had a typo in in its type attribute, “ScrpingSectionGroup” instead of “ScriptingSectionGroup”.

After I had corrected this everything worked fine.

I had no idea that a typo in web.config could screw up the IDE so bad. Keep in mind that even that web.config had this typo, the project compiled and ran just fine.

Sigh

Posted in Programming, development | Tagged | Leave a comment

PyBlocks

Some time ago I had the need to generate order confirmation emails using templates populated with order data such as ordered items, pricing and customer information.

One way is of course to serialize the order to XML and transform it via XSL but I had an urge to try something new.

So I decided to use IronPython and parse templates with {py py} blocks.

You can download the example PyBlocks solution here

Example PyBlocks template

Hello {py Console.Write(customer.Givenname+ ' ' + customer.Surname) py}!

The package will be sent to the following adress

  {py
  Console.WriteLine(customer.Street + ' ' + customer.StreetNumber)
  Console.WriteLine(customer.ZipCode + ' ' + customer.City)
  py}
Regards
//Some online store

Rendering the template

var engine = Python.CreateEngine(AppDomain.CurrentDomain);
var scope = new ScriptScope(engine, new Scope()).Engine.GetClrModule();

scope.SetVariable("customer", new Customer
                                  {
                                      City = "Stockholm",
                                      Givenname = "Steve",
                                      Street = "AppleRow",
                                      StreetNumber = "23",
                                      Surname = "Mobs",
                                      ZipCode = "14565"
                                  });

Console.WriteLine(PyBlocksRenderer.Render(engine, scope, template));

Output

Hello Steve Mobs!

The package will be sent to the following adress

  AppleRow 23
  14565 Stockholm

Regards
//Some online store

PyBlocksRenderer.cs

    public class PyBlocksRenderer
    {

        /// <summary>
        /// Renders the template using the specified engine and scope.
        /// </summary>
        /// <param name="pythonEngine">The python engine.</param>
        /// <param name="scriptScope">The script scope.</param>
        /// <param name="template">The template.</param>
        /// <returns></returns>
        public static string Render(ScriptEngine pythonEngine, ScriptScope scriptScope, string template)
        {
            //Replace tabs with 4 spaces using a string extension method
            template = template.ReplaceTabsWithSpaces();

            //Fetch a MatchCollection using a string extension method
            var pythonBlocksMatchCollection = template.GetPythonBlockMatches();

            //contains the matching {py..py} block as a key and the result as value
            var pyBlockMatchResults = new List<KeyValuePair<string, string>>();

            foreach (Match pythonBlockMatch in pythonBlocksMatchCollection)
            {
                //Fetch matching code block code and normalize indentation using a string extension method
                var pythonCode = pythonBlockMatch.Groups["code"].Value.NormalizeIndentations();

                //Add import to enable writing to the console from within the pythonCode
                pythonCode = string.Format("from System import Console{0}{1}", Environment.NewLine, pythonCode);

                //Execute script
                var pyResult = ExecuteScript(pythonEngine, scriptScope, pythonCode);

                //Fix result indentations
                var line = template.GetLineAt(pythonBlockMatch.Index);
                if (string.IsNullOrEmpty(line.Trim()))
                {
                    var indentation = line.GetIndentation();
                    var pyLines = pyResult.GetLines().ToList();
                    var lines = from l in pyLines select pyLines.IndexOf(l) > 0 ? l.Prepend(" ", indentation) : l;
                    pyResult = string.Join(Environment.NewLine, lines.ToArray());
                }

                //Add the result of this execution to the list
                pyBlockMatchResults.Add(new KeyValuePair<string, string>(pythonBlockMatch.Value, pyResult));
            }

            //find / replace template py blocks with results
            foreach (var replace in pyBlockMatchResults)
                template = template.Replace(replace.Key, replace.Value);

            return template;
        }

        /// <summary>
        /// Executes the script.
        /// </summary>
        /// <param name="engine">The engine.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="code">The code.</param>
        /// <returns>code output</returns>
        public static string ExecuteScript(ScriptEngine engine, ScriptScope scope, string code)
        {
            //save reference to standard Console out
            var stdOut = Console.Out;

            //1: redirect the console to write to a stringwriter
            //2: execute the script
            //3: return the contents of the stringbuilder
            //4: reset Console out to the saved reference above
            //Exception: return the exception message
            try
            {
                var sb = new StringBuilder();
                Console.SetOut(new StringWriter(sb));
                engine.Execute<string>(code, scope);
                return sb.ToString();
            }
            catch (Exception ex)
            {
                return string.Format("#! {0}", ex.Message);
            }
            finally
            {
                Console.SetOut(stdOut);
            }
        }
    }

StringExtensions.cs

    public static class StringExtensions
    {
        /// <summary>
        /// Replaces the tabs with spaces.
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <returns></returns>
        public static string ReplaceTabsWithSpaces(this string str)
        {
            return str.Replace("\t", "    ");
        }

        /// <summary>
        /// Gets the python blocks.
        /// </summary>
        /// <param name="template">The template.</param>
        /// <returns></returns>
        public static MatchCollection GetPythonBlockMatches(this string template)
        {
            return Regex.Matches(template, "{py(?<code>.*?)py}", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        }

        /// <summary>
        /// Normalizes the indentations.
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <returns></returns>
        public static string NormalizeIndentations(this string str)
        {
            str = str.ReplaceTabsWithSpaces();
            var lines = from line in str.GetLines() where !string.IsNullOrEmpty(line.Trim()) select line;
            var minimumIndent = lines.GetMinimumIndentation();
            return string.Join(Environment.NewLine, (from line in lines select line.Substring(minimumIndent)).ToArray());
        }

        /// <summary>
        /// Gets the lines.
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <returns></returns>
        public static string[] GetLines(this string str)
        {
            return Regex.Split(str, "\\r?\\n");
        }

        /// <summary>
        /// Gets the minimum indentation.
        /// </summary>
        /// <param name="lines">The lines.</param>
        /// <returns></returns>
        private static int GetMinimumIndentation(this IEnumerable<string> lines)
        {
            var minimumIndent = int.MinValue;

            foreach (var line in lines)
            {
                var indent = line.GetIndentation();
                minimumIndent = minimumIndent > indent || minimumIndent == int.MinValue ? indent : minimumIndent;
            }

            return minimumIndent > int.MinValue ? minimumIndent : 0;
        }

        /// <summary>
        /// Gets the indentation.
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <returns></returns>
        public static int GetIndentation(this string str)
        {
            return Regex.Match(str, "^\\s+").Value.Length;
        }

        /// <summary>
        /// Gets the line at.
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <param name="index">The index.</param>
        /// <returns></returns>
        public static string GetLineAt(this string str, int index)
        {
            return str.Substring(0, index).GetLines().LastOrDefault() ?? string.Empty;
        }

        /// <summary>
        /// Prepends the specified STR with value n times.
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <param name="value">The value.</param>
        /// <param name="times">The times.</param>
        /// <returns></returns>
        public static string Prepend(this string str, string value, int times)
        {
            for (var i = 0; i < times; i++)
                str = value + str;

            return str;
        }
    }
Posted in C#, IronPython, Programming | Tagged , , , | 1 Comment

Setting up a EPiServer 6 project from scratch

Prerequisites

  1. Microsoft Visual Studio 2008
  2. EPiServer 6.0 CMS (Download and install from here)
  3. MS SQL Server Express (Download and install from here)

Prepping a EPiServer database

Start EPiServer Deployment Center and choose “Install SQL Server Database” > run

Setting up the EPiServer 6 project in Visual Studio

Create a new EPiServer 6 project in Visual Studio,  File > New > Project > C# > EPiServer

ConnectionStrings.config

Alter the ConnectionStrings section to match your database setup

Properties > Web

In Visual Studio, right click your website project and choose “properties”

In the “Web” tab, clear the Virtual Path.

I had problems accessing the site with the default port 6666 so I changed it to 5859

EPiServer.config

Change the “siteUrl” of your site to “http://localhost:5859″

Launch

Now you should be able to launch the project and login at http://localhost:5859/EPiServer/CMS/Edit/

Create a simple page template

Visual Studio – /Templates/Pages/SimplePage.aspx

In your EPiServer project, create a Templates folder and a Pages folder beneath that one (you can structure/name this however you want)

In the pages folder create a new Web Form, name it SimplePage and change the base class to EPiServer.TemplatePage

EPiServer

Launch your project and navigate to http://localhost:5859/EPiServer/CMS/Admin/

Choose the “Page Type” tab and click “Create New Page Type”

Type a name for your new Page Type and set the File Name to “/Templates/Pages/SimplePage.aspx”

Click the save button and you are done

Posted in EPiServer | Tagged , , | 1 Comment

Google Wave – Reversi game

This is the classic board game Reversi as a Google Wave Gadget. Players takes turns placing white/black stones on the grid. Stones are only allowed to be placed to an allready existing stone on the board, if a stone is surrounded on either sides by stones of oposing color that stone will change to that color. the player with the most his/hers colors on the board when the board is full Wins.

Insert this gadget into a wave by creating a new blip/response, click the green puzzle icon, type/paste the url below and click Add.

http://www.creamdog.se/googlewave/go/go.xml

If you are interested you can download the source code here

Posted in Games | Tagged , , , | Leave a comment