2011-05-23

IIS AppPool and ApplicationPoolIdentity

When you create a new web site in IIS 7.5, an Application Pool is created by default with the same name as the web site.

After Windows Server 2008 SP2, you may select “ApplicationPoolIdentity” as the account to run the app pool with.

ApplicationPoolIdentity is an account on the local machine with the same name as the Application Pool.

If you want to give your web application access to files or other resources outside your web root directory, perform these steps:

  • Right Click the file or folder (or registry key?) you want to give access to, and select Properties from the dropdown.
  • Go to the Security Tab, click the “Edit…” button.
  • Click “Add…”.
  • Click “Locations…” and select the local machine.
  • Under “Enter the object names to select…”, type IIS AppPool\<ApplicationPoolIdentity>, where <ApplicationPoolIdentity> is the same as the Application Pool name.
  • Give rights as needed, click OK as many times as it takes, etc.

I think this should be enough to get you started.

Source: http://learn.iis.net/page.aspx/624/application-pool-identities/

2011-04-15

Setting up Oracle Instantclient Basic

I have been working on setting up an oracle instant client basic connection, using the following article:

http://www.dbatoolz.com/t/installing-oracle-instantclient-basic-and-instantclient-sqlplus-on-win32.html

Ran into one problem which took me a little time to figure out. The article says to add an environment variable as a “User Variable”. Since I am running a web site that has an application pool running on the NETWORK SERVICE account, and it is not possible to log on using that account and set the User Variables, they will not be available to my web app.

The solution is to add all variables as System Variables (using the lower part of the Environment variables window).

Just to be safe, I also added a variable for “ORA_HOME” with the same value as the TNS_ADMIN environment variable, namely the path to the instantclient (in my case “instantclient_11_2”) folder.

2011-04-11

System.Security.Cryptography.CryptographicException: Key not valid for use in specified state

I got this message after I created a new user profile on my virtual machine (VMWare), and tried to compile my ORM project (using Telerik OpenAccess ORM). The error was wrapped as: OpenAccess Error: Key not valid for use in specified state.

This is not a problem for OpenAccess only though. I’ve seen that it also may be a problem for other applications, like SQL Server Reporting Services.

The solution:

  1. Go into the folder (Windows XP) at:
    <drive>:\Documents and Settings\<your windows user account name>\Application Data\Microsoft\Crypto\DSS\<your machine SID>\
  2. Delete the file there. It should have some cryptic name (like a GUID).
  3. Restart IIS (IISRESET).
  4. Recompile. It worked for me.

 

References:

2011-03-29

My experiences from installing EPiServer CMS 5 on Windows XP

Installing EPiServer CMS 5 on a Windows XP developer VM turned out to be a bit of hazzle, maybe because XP is not a “supported” OS any more?

Ok, so first installed the EPiServer CMS5 5.2 R2 application files to the default location. No problem so far.

Since I am working on an existing web site, I created a folder on disk and got latest version from TFS.

I then copied the EPiServer binaries into my bin-folder (XCOPY-deployment), and attempted to browse the website. I got this message:

Could not load type 'EPiServer.UI.WebControls.ControlAdapters.HtmlHeadAdapter'.

This error message originated from the App_Browsers / AdapterMappings.browser file.

I then went into my web.config file and verified that my VPP paths were mapped correctly to files in the Program Files\EPiServer\CMS\5.2.375.236\Application folder.

So my next thought was to open the edit/admin mode. Alas, it looked all messed up, missing both styles and graphics.

This gave me my next clue, because in EPiServer 4.x you had to remap the 404 http error status to /utils/NotFound.aspx to make the admin/edit modes look as they should, as I described in my previous posting: http://stgaup.blogspot.com/2009/10/styles-missing-in-episerver-editadmin.html.

That trick does not seem to work on CMS 5 (only works on EPiServer 4.x). Now in stead you need to do something a bit different:

  1. Open the “Properties” for your web site in the IIS manager.
  2. On the “Home Directory” tab, click the “Configuration…” button.
  3. On the “Mappings” tab, click the “Add” button.
  4. Click the “Browse” button next to the “Executable” text box.
  5. Navigate to the Windows/Microsoft.NET/Framework/v2.0.50727 folder.
  6. Select “Dynamic Link Libraries” in the “Files of type” dropdown.
  7. Select the “aspnet_isapi.dll” file, and click the “Open” button.
  8. Fill in the “Extension” as “.*” (dot-star).
  9. TRICK: There’s a bug in Windows XP that has never been fixed, that causes the “OK” button to remain disabled. Click in the “Executable” text box again and then voila, the “OK” button is enabled.
  10. Click OK as many times as it takes to get back to the “Internet Information Services” application.

Now try to reload your admin/edit mode. It should work.

Some good links:

2011-03-04

Themed CheckBox check mark

Themes for ASP.NET applications came probably in 2005 with .NET 2.0, so it’s been around for a while.

I am creating different themes to adapt my web appliction to different clients.

So the problem I came across with the ASP CheckBox control is that setting the size of the control does not change the size of the check mark. Neither does it have any properties for setting the size.

Also, I want to be able to theme my control, so the control needs to have some kind of property that could be set in the skin file, and there is no such property on the standard asp CheckBox. It does have a method for setting properties on the inner input control, however, but as I said, I need a property.

The CheckBox control is rendered inside a span tag, like this:

<span class="checkbox">
  <input id="ContentPlaceHolder1_chkPersistLogin"
         type="checkbox"
         name="ctl00$ContentPlaceHolder1$chkPersistLogin" />
  <label for="ContentPlaceHolder1_chkPersistLogin">
Remember me</label>
</span>

Now, as you can see, if you set the CssClass property of the control to something, then it will be applied to the span, not to the inner controls directly.

So, as I mentioned, the CheckBox control does have a way of accessing the inner input control. It is by using the InputAttributes propertys methods. For example, the following code will add a “class” attribute to the <input type=”checkbox” /> tag:

MyCheckBox.InputAttributes.Add("class", “MyCheckBoxCssClass”);

If I want to set the class on my inner input control, then I could create my own custom control that inherits from the asp CheckBox control. Here’s my CheckBoxPlus class:

using System;
using System.Web;
using System.Web.UI.WebControls;

namespace MyWebApp.WebUI.Common.CustomControls
{
    public class CheckBoxPlus : CheckBox
    {
        private string _inputCssClass;

        public string InputCssClass
        {
            get { return _inputCssClass; }
            set
            {
                _inputCssClass = value;
                this.InputAttributes.Add("class", _inputCssClass);
            }
        }
    }
}

To be able to use my custom control in a page, I need to add a directive to the web forms where I want to use it:

<%@ Register TagPrefix="custom" Assembly="MyWebApp.WebUI" Namespace="MyWebApp.WebUI.Common.CustomControls" %>

Now I can use the control im my page, and set the new property:

<custom:CheckBoxPlus ID="chkPersistLogin" runat="server" Text="Remember me" CssClass="checkbox" />

The last part is to enable theming/skins for the control. The only thing you need to do is to add the same Register directive at the top of the skin file, and then you can create a template for you control in the usual way. Here’s an example skin file:

<%@ Register TagPrefix="cd" Assembly="MyWebApp.WebUI" Namespace="MyWebApp.WebUI.Common.CustomControls" %>
<asp:Button runat="server" />
<asp:TextBox runat="server" />
<asp:Label runat="server" />
<asp:Panel runat="server" HorizontalAlign="Center" />
<cd:CheckBoxPlus InputCssClass="checkboxplus" runat="server" />

When I load my page now, the rendered HTML looks like this:

<span class="checkbox">
  <input id="ContentPlaceHolder1_chkPersistLogin"
         type="checkbox"
         name="ctl00$ContentPlaceHolder1$chkPersistLogin"
         class="checkboxplus" />
  <label for="ContentPlaceHolder1_chkPersistLogin">Remember me</label>
</span>

As you can see, the theme sets the InputCssClass, and thus I am able to control the size of the check mark of the CheckBox control.

2011-02-11

Installing Windows Phone 7 CTP on Windows XP

Source: http://social.msdn.microsoft.com/Forums/en-US/windowsphone7series/thread/6657c1ff-45a6-466a-b20d-f5640e3f0c1f/

Thanks to Oran Dennison for this solution.

Please be awear that Microsoft does not support running the Windows Phone 7 CTP Tools on Windows XP. I found this solution, and I am using it at my own risk, as should you.

Workaround for installing Windows Phone 7 CTP on Windows XP:

1.Download the Windows Phone Developer Tools CTP Refresh from here: developer.windowsphone.com 
2.Extract the contents of the setup package by running vm_web.exe /x and choosing a path to extract to
3.Go to the folder you extracted to in step 2 and open the file baseline.dat in notepad
4.Look for the section named [gencomp7788]
5.Change the value InstallOnLHS from 1 to 0
6.Change the value InstallOnWinXP from 1 to 0
7.Save and close baseline.dat
8.Run setup.exe /web from the folder you extracted to in step 2

2011-01-14

Windows x64 knowledge

I have learned about Windows 64-bit:

  • On a 64-bit Windows machine, there are two different locations for programs to be installed:
    • Programs
      • For 64-bit programs
    • Programs (x86)
      • For 32-bit programs
  • There are two different ODBC managers:
    • the 64-bit version is accessed from Control Panel / Administrative Tools
    • the 32-bit version may be found under [SysDrive]:\Windows\SysWOW64
  • Oracle 10g had a problem with the parentheses in the “Programs (x86)” folder name, for which there were released a patch.
  • The BI Development Studio (VS2008) which comes with SQL Server 2008 is 32-bit, and does not have easy access to 64-bit drivers. This goes also for the SSIS Package Designer.
    • If you build for “Any CPU” it might still work.
    • Or you could install both, and define ODBC connections with the same names using both of the ODBC managers.
  • (more info coming soon…. maybe)

64-bit Windows 2008 vs Oracle x64

Ok, so finally after exploring several ways to run a query on Oracle x64, I have succeeded.

First step is to install a 64-bit Oracle Client on the W2k8 server. For me it works with the Oracle 11g InstantClient v. 11.2, connecting to an Oracle 10.x.. database.

I am using a 32-bit developer machine, using the System.Data.OracleClient classes, and everything seems to work.

My connection string is like this:
<connectionStrings>
    <add name=”oracle” 
            connectionString=”Data Source=TNSNAME;UserId=uid;Password=pwd;” />
</connectionStrings>

So everything works nicely, until I move my compiled code to the x64 server.
I now get this error:

Attempt to load Oracle client libraries threw BadImageFormatException.  This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.

Solution:
Before compiling, go into the project properties and set the “Platform target” property to “Any CPU”.
Compile, then copy your assemblies to the server. Looks like an extra DLL-file has been added to my bin-folder (Oracle.DataAccess.dll).

2010-12-16

SoapExceptionWrapper

I wrote this code quite a while ago, but since it’s quite reusable (and very simple) here it is:

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Services.Protocols;
using System.Xml;

namespace SupportLibrary.ExceptionHandling
{

    /// <summary>
    /// Wrapper Class for Soap Exception from JBoss.
    /// Parses the XML in the Detail XML Node, exposing StatusCode and StatusDescription as properties.
    /// </summary>
    /// <example>
    /// int errorCode = -1;
    /// try
    /// {
    ///     WebService.DoSomething();
    /// }
    /// catch(SoapException soapex)
    /// {
    ///     SoapExceptionWrapper wrapper = new SoapExceptionWrapper(soapex);
    ///     int errorCode = wrapper.StatusCode;
    ///     string errorDescription = wrapper.StatusDescription;
    /// }  
    /// </example>
    public class SoapExceptionWrapper
    {
        private SoapException _ex;

        /// <summary>
        /// The XmlNode containing the Detail information about the error.
        /// </summary>
        public XmlNode DetailXml
        {
            get
            {
                return _ex.Detail.FirstChild;
            }
        }

        /// <summary>
        /// Status code from SoapException Detail XML.
        /// </summary>
        public int StatusCode
        {
            get
            {
                string codeStr = "-1";
                if(DetailXml != null && DetailXml.ChildNodes.Count > 0)
                    codeStr = DetailXml.SelectSingleNode("StatusCode").InnerText;
                int codeInt = -1;
                int.TryParse(codeStr, out codeInt);
                return codeInt;
            }
        }

        /// <summary>
        /// Status description from SoapException Detail XML.
        /// </summary>
        public string StatusDescription
        {
            get
            {
                if (DetailXml != null && DetailXml.ChildNodes.Count > 0 && DetailXml.SelectSingleNode("StatusDescription") != null && DetailXml.SelectSingleNode("StatusDescription").InnerText != "")
                {
                    return DetailXml.SelectSingleNode("StatusDescription").InnerText;
                }
                return _ex.Message;
            }
        }

        /// <summary>
        /// Constructor using default values.
        /// </summary>
        /// <param name="soapex"></param>
        public SoapExceptionWrapper(SoapException soapex)
        {
            _ex = soapex;
        }
    }
}

2010-09-27

Generic cache manager

The following class is a generic cache manager. It requires a reference to System.Web.

public static class CacheManager
{
    public static T GetObject<T>(string key)
    {
        if (System.Web.HttpRuntime.Cache.Get(key) != null) return (T)System.Web.HttpRuntime.Cache.Get(key);
        return default(T);
    }

    public static void AddObject<T>(T customObject, string key, TimeSpan duration)
    {
        if (System.Web.HttpRuntime.Cache.Get(key) == null)
            System.Web.HttpRuntime.Cache.Insert(key, customObject, null, System.Web.Caching.Cache.NoAbsoluteExpiration, duration);
    }
}

2010-09-23

SQL Server 2008: No connection could be made because the target machine actively refused it

An old problem which still causes me some trouble now and again.

So I got the following error:

No connection could be made because the target machine actively refused it. Microsoft SQL Server Error 10061

So first thing to check is wether or not the server is set up to accept remote connections.

  1. Open up SQL Server Management Studio (SSMS).
  2. Right-click on the server instance, select Properties…
  3. Click on the “Connections” option on the left side.
  4. Verify that the “Allow remote connections to this server” option is checked.

If it was not enabled, you might try to restart the sql server service by running “NET STOP mssqlserver” and “NET START mssqlserver” in a command window. You need to restart the service for any configuration changes to take effect.

Second thing you might check is if the server has enabled TCP/IP.

  1. Open SQL Server Configuration Manager.
  2. Expand the SQL Server Network Configuration node.
  3. Make sure that TCP/IP is enabled.

Remember again that you must restart Sql Server for changes to be effective.

Final thing is to go into the Surface Area configuration and enable the functionality you need. This used to be a separate configuration tool in SQL Server 2005, but now it is integrated into SSMS.

  1. Open up SQL Server Management Studio (SSMS).
  2. Right-click on the server instance, select Facets…
  3. Select the “Surface Area Configuration” facet from the dropdown at the top.
  4. You may at least want to set the “AdHocRemoteQueriesEnabled” to true, and maybe some of the other options as well.

Remember to restart SQL Server.

2010-09-13

Pregnancy Ticker Screen Saver

I have created a HTML page to be used with the HTML Screen Saver from http://myweb.tiscali.co.uk/djmclean/htmlscreensaver.html.

The actual screen saver must first be installed from the link above.

After it has been installed, create a HTML Page and paste the following markup into it, and then save it somewhere (preferably in a dedicated new directory).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body bgcolor="#0080C0" topmargin="0" leftmargin="0" rightmargin="0" bottommargin="0" scroll="no">
<div id="tickerDiv" style="width:1600px;height:1000px; background-image:url('scrback.jpg'); background-repeat: no-repeat; background-position:center center; border-width: 0; margin: 0 0 0 0;" >
<table id="kwsTickerLayoutTable" border="0" cellspacing="2" cellpadding="1" style="background-color:#FFEEFF;text-align:left;position:absolute;">
<tr><td rowspan="3" style="background-color:green;"><a id="kwsTickerCountdownUrl" href="" style="border:0;"><img id="kwsTickerCountdownImage" width="100px" alt="" src="" style="border: 1px solid #EEDDEE;" /></a></td><td style="font-style:normal; font-family: Arial; font-size: x-large; font-weight: bold; font-variant: normal; color: #008080;"><label id="kwsTickerCountdownText1">test</label></td></tr>
<tr><td style="font-style:normal; font-family: Arial; font-size: x-large; font-weight: bold; font-variant: normal; color: #008080;"><label id="kwsTickerCountdownText2">test</label></td></tr>
<tr><td style="font-style:normal; font-family: Arial; font-size: x-large; font-weight: bold; font-variant: normal; color: #008080;"><label id="kwsTickerCountdownText3">test</label></td></tr>
</table>
</div>
</body>
<script language="javascript" type="text/javascript">
    var now = new Date(); //today
    var dob = new Date(2011, 2, 9); //date of birth
    var doc = new Date(2010, 5, 1); //start date of pregnancy
    var one_day = 1000 * 60 * 60 * 24; //milliseconds in one day
    var days_total = Math.ceil((dob.getTime() - now.getTime()) / (one_day)); //number of days left
    var weeks = Math.floor(days_total / 7); //number of weeks left
    var days = days_total % 7; //number of days in addition to the weeks left
    var days_gone_total = Math.ceil((now.getTime() - doc.getTime()) / one_day); //number of days gone
    var weeks_gone = Math.floor(days_gone_total / 7); //number of weeks gone
    var days_gone = days_gone_total % 7; //number of days in addition to the weeks gone
    var lab1 = document.getElementById('kwsTickerCountdownText1'); //get label 1
    var lab2 = document.getElementById('kwsTickerCountdownText2'); //get label 2
    var lab3 = document.getElementById('kwsTickerCountdownText3'); //get label 3
    var img = document.getElementById('kwsTickerCountdownImage'); //get image element
    var url = document.getElementById('kwsTickerCountdownUrl'); // get url element of image element
    lab1.innerHTML = (weeks_gone + 1) + 'th week';
    if (days_gone > 0) { lab2.innerHTML = weeks_gone + ' weeks and ' + days_gone + ' days on the way.'; } else { lab2.innerHTML = weeks_gone + ' weeks on the way.'; }
    if (days > 0) { lab3.innerHTML = 'Only ' + weeks + ' weeks and ' + days + ' days left!'; } else { lab3.innerHTML = 'Only ' + weeks + ' weeks left!'; }
    img.setAttribute('src', 'http://images.3dpregnancy.com/en/2D/200/' + weeks_gone + '-weeks-pregnant.jpg');
    url.setAttribute('href', 'http://3dpregnancy.parentsconnect.com/calendar/' + weeks_gone + '-weeks-pregnant.html');

    var tickerDiv = document.getElementById('tickerDiv');
    tickerDiv.style.width = screen.width;
    tickerDiv.style.height = screen.height;

    window.setTimeout("Tick()", 500, "javascript");
</script>
<script language="javascript" type="text/javascript">
    function Tick() {
        var tabl = document.getElementById('kwsTickerLayoutTable');
        var x = Math.floor(Math.random() * (screen.width - tabl.offsetWidth)) + 'px';
        tabl.style.left = x;
        var y = Math.floor(Math.random() * (screen.height - tabl.offsetHeight)) + 'px';
        tabl.style.top = y;
        window.setTimeout("Tick()", 2000, "javascript");
    }
</script>
</html>

If you want to have a background image, save a JPG-file called “scrback.jpg” into the same directory. If you don’t want a background image (if you are concerned about burn-in etc.), you may need to remove the following text: background-image:url('scrback.jpg') from the markup above.

Lastly, go into the screen saver options on your computer and configure the HTML file you created as the one you want your HTML screen saver to use.

Pregnancy ticker

The following HTML is a pregnancy ticker. The HTML fetches an image from http://www.3dpregnancyticker.com. Click on the image to go to the web site. To put in your own due date you will need to change the values for the “dob” and “doc” variables. It may be used as a desktop item on Windows. I have also used it on a HTML Screen Saver.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
<div style="height:100%;width:100%;vertical-align:middle;text-align:center;background-color:MidnightBlue;">
<table id="kwsTickerLayoutTable" border="0" cellspacing="2" cellpadding="1" style="background-color:#FFEEFF;text-align:left;">
<tr><td rowspan="3" style="background-color:green;"><a id="kwsTickerCountdownUrl" href="" style="border:0;"><img id="kwsTickerCountdownImage" width="100px" alt="" src="" style="border: 1px solid #EEDDEE;" /></a></td><td style="font-style:normal; font-family: Arial; font-size: x-large; font-weight: bold; font-variant: normal; color: #008080;"><label id="kwsTickerCountdownText1">test</label></td></tr>
<tr><td style="font-style:normal; font-family: Arial; font-size: x-large; font-weight: bold; font-variant: normal; color: #008080;"><label id="kwsTickerCountdownText2">test</label></td></tr>
<tr><td style="font-style:normal; font-family: Arial; font-size: x-large; font-weight: bold; font-variant: normal; color: #008080;"><label id="kwsTickerCountdownText3">test</label></td></tr>
</table>
</div>
</body>
<script language="javascript" type="text/javascript">
    var now = new Date(); //today
    var dob = new Date(2011, 2, 9); //date of birth
    var doc = new Date(2010, 5, 1); //start date of pregnancy
    var one_day = 1000 * 60 * 60 * 24; //milliseconds in one day
    var days_total = Math.ceil((dob.getTime() - now.getTime()) / (one_day)); //number of days left
    var weeks = Math.floor(days_total / 7); //number of weeks left
    var days = days_total % 7; //number of days in addition to the weeks left
    var days_gone_total = Math.ceil((now.getTime() - doc.getTime()) / one_day); //number of days gone
    var weeks_gone = Math.floor(days_gone_total / 7); //number of weeks gone
    var days_gone = days_gone_total % 7; //number of days in addition to the weeks gone
    var lab1 = document.getElementById('kwsTickerCountdownText1'); //get label 1
    var lab2 = document.getElementById('kwsTickerCountdownText2'); //get label 2
    var lab3 = document.getElementById('kwsTickerCountdownText3'); //get label 3
    var img = document.getElementById('kwsTickerCountdownImage'); //get image element
    var url = document.getElementById('kwsTickerCountdownUrl'); // get url element of image element
    lab1.innerHTML = (weeks_gone + 1) + 'th week';
    lab2.innerHTML = weeks_gone + ' weeks and ' + days_gone + ' days on the way.';
    if (days > 0) { lab3.innerHTML = 'Only ' + weeks + ' weeks and ' + days + ' days left!'; }
    else { lab3.innerHTML = 'Only ' + weeks + ' weeks left!'; }
    img.setAttribute('src', 'http://images.3dpregnancy.com/en/2D/200/' + weeks_gone + '-weeks-pregnant.jpg');
    url.setAttribute('href', 'http://3dpregnancy.parentsconnect.com/calendar/' + weeks_gone + '-weeks-pregnant.html');
</script>
</html>

2010-06-14

SQL Server 2008 Client Tools Install Pain

In this blog post http://nomisit.wordpress.com/2009/04/21/installing-sql-server-2008-client-tools-what-a-pain/ it is described how you need to upgrade Visual Studio 2008 to SP1 if you are installing any of these…

  • BIDS
  • Management tools (Basic or Full version)
  • Integration Services
  • … and you have previously installed VS2008, then you will need to upgrade it to SP1.

    I did install a trial version of VS2008 but now I have uninstalled everything, but still getting the same failed requirement.

    So now I am trying to install SP1, even if I don’t know what products it could be upgrading since I removed them all. Perhaps it is something like a C++ runtime or something that was left behind by the uninstaller?

    The SP1 installer seemed to be stuck on “WebDesignerCore_KB950278”. But proceeded after quite a while (20 minutes, maybe more).

    Then it took a long time to install “VS90sp1-KB945140-X86-ENU”.

    I got a Fatal Error at the end of the install, so now I don’t know what was installed or not. So either try to reinstall SP1 or try to install the client tools?

    Tried to install client tools, and to my surprise it succeeded!

    2010-05-19

    Wrapping Web Service Proxy objects to Common Cargos using Serialization

    In my previous post I described a way to wrap web service proxy objects to common cargo objects using reflection. This method works only for objects with only value type properties.

    Update: The performance of this code may not be the best.

    internal U wrapToCargoBySerialization<T, U>(T source, U target)
    {
        UTF8Encoding encoding = new UTF8Encoding(true);

        XmlRootAttribute rootAttribute = new XmlRootAttribute();
        XmlSerializer xmlSerializerSource = new XmlSerializer(typeof(T), rootAttribute);
        MemoryStream stream = new MemoryStream();
        xmlSerializerSource.Serialize(stream, source);
        string xml = encoding.GetString(stream.ToArray());
        xml = xml.Replace("<?xml version=\"1.0\"?>", string.Empty);

        MemoryStream ms = new MemoryStream(encoding.GetBytes(xml));

        XmlSerializer xmlSerializerTarget = new XmlSerializer(typeof(U),rootAttribute);

        return (U)xmlSerializerTarget.Deserialize(ms);
    }

    Usage example:
    CommonObjects.Customer cust;
    cust = wrapToCargoBySerialization(wsCustomer, cust);

    Note that I had to remove the <?xml … /> declaration before deserializing.

    A prerequisite for using this method is that the objects have the same structure. To achieve this I simply copy the web service objects from the web reference to a common cargo project. The common objects are used for passing information between layers in the application.

    2010-04-29

    Windows Installer Cleanup Utility

    Freeing up space on your hard disks is an ever ongoing battle for some people, for instance if you at some point decided on a too small system partition (“10 Gigs must surely be enough?”).

    So in the Windows directory (on Windows XP at least) there is a folder called “Installer” where many install files will be found. It may be tempting to just delete all files here, freeing up many gigs of space, but that could cause problems later, for instance if you want to upgrade some program that needs the old version to be uninstalled first.

    So this is where the Windows Installer Cleanup Utility comes into play. Read this excellent blog post on where to get it and how to use it: http://blogs.msdn.com/heaths/archive/2007/01/31/how-to-safely-delete-orphaned-patches.aspx

    Essentially after installing the utility, you may run a command that will delete orphaned installation files, that is install files for programs that are no longer on your system.

    I managed to free up enough space to install MS VS 2008 Professional… :)

    2010-04-13

    Syncroniziong files with FreeCommander and Compare It!

    Up until now I have mostly used SourceSafe and TFS for comparing files. Recently I had a situation where I had to do a so called “Baseless Merge” in TFS. This worked quite well for most files. Then there were some files that were not as easy to merge. So a manual merge was required. Not being quite happy with the file comparing offered by VS, I searched and found a nice option:

    • Use FreeCommander to find all files that have differences.
    • Use Compare It! to compare and syncronize the contents of files.

    To be able to use the “Compare left and right sides” option in FreeCommander, you need to go into Extras –> Settings in FreeCommander, in the Programs section, and set “Compare files” to “C:\Program Files\Compare It!\wincmp3.exe” assuming that’s where Compare It! is installed.

    FreeCommander may be found at http://www.freecommander.com.

    Compare It! may be found at http://www.grigsoft.com.

    I think using these two great tools together is synergy in action!

    2010-04-09

    Chinese comments

    I have been getting some comments, I am guessing they are in Chinese. This may seem unnecessary to point out, but anyway here goes:

    I DON’T UNDERSTAND CHINESE!

    So please stop commenting in any languages except English, or in some rare cases where I have blogged in Norwegian where this language may be used (I also understand Swedish and Danish and a bit of German).

    2010-02-26

    Common Table Expression for Database Structure

    When copying data from one database to another, breaking constraints is always a problem. If you do not insert data in a certain sequence, you will get foreign key violations. So I tried to work out a CTE that starts with all tables that have no foreign keys, then the tables referencing them, then the once referencing them again, and so on… So came up with this:

    WITH CTE (name,object_id, lvl)
    AS
    (
        select name, object_id, 0 AS lvl from sys.tables
        where object_id NOT IN (select parent_object_id from sys.foreign_keys)
       
    UNION ALL

        select tbls.name, tbls.object_id , lvl + 1 from sys.tables tbls
        join sys.foreign_keys keys on tbls.object_id = keys.parent_object_id
        join CTE on CTE.object_id =  keys.referenced_object_id
    )
    SELECT * FROM CTE
    OPTION (MAXRECURSION 10000)

    Note that this will not work if you have self-referencing tables, ie. tables that have a foreign key pointing to its own primary key. Also the same tables may appear many times because they reference the same tables. And also if the same table have many foreign keys it will appear many times.

    The conclusion is that this does not solve my problem, but it was fun to create the CTE anyway.

    2010-02-16

    Experiences on upgrading EPiServer 4.51 to 4.62B part 2

    Ok, so the upgrade has been done, but will the project compile?

    Sadly the answer is no.

    I got the exact same problems described here: http://world.episerver.com/templates/forum/pages/thread.aspx?id=19575&epslanguage=en. It took some time for me to understand the answer to the part they did give an answer to. They didn’t answer the second question at all.

    Problem 1: WsrpHelper doesn’t exist any more

    My solution, which saves me from having to go through 8-10 places and correct the code, was to create a new class inside the WsrpPortal.aspx.cs file:

    class WsrpHelper
    {
        public static IConsumerEnvironment ConsumerEnvironment
        {
            get { return ElektroPost.Wsrp.Consumer.ConsumerContext.ConsumerEnvironment; }
            set { ElektroPost.Wsrp.Consumer.ConsumerContext.ConsumerEnvironment = value; }
        }

        public static void EnsureConsumerEnvironment()
        {
            if (ElektroPost.Wsrp.Consumer.ConsumerContext.ConsumerEnvironment == null)
            {
                ElektroPost.Wsrp.Consumer.ConsumerContext.ConsumerEnvironment = ConsumerFactory.ConsumerEnvironmentInstance();
            }
        }
    }

    Problem 2: LanguageManager.GetContextLanguage() is obsolete

    It says in the error message that you should use LanguageContext.Current as a replacement, but that would create a type conversion exception.

    I am guessing that you can to use LanguageContext.Current.CurrentUILanguageID as a replacement for GetContextLanguage() (please do correct me if I’m wrong).

    DISCLAIMER:
    I haven’t been able to test my solution, since the webs I am working on don’t actually use the portal framework. My code compiles now, so the web is up and running, and I am happy for the time being. If anyone finds any flaw in my solutions please don’t hesistate to leave a comment.