Monday, October 26, 2009

Windows 7 x64 and Citix Access Gateway

A long needed reinstall on my work laptop. I previously had Vista, but downgraded to XP unwillingly cause support wouldn’t let me struggle anymore.

The fresh installation of Windows 7 x64 gave me no problems. The installation of Visual Studio 2008 Team System and Sql Server 2008 Developer had the usual problems, which is solved by googling, and installing VS2008 sp1. Should probably installed Sql first, I think that would have made it easier.

The biggest obstacle I ran into was the VPN, which I totally depend on to get my work done. Luckily I found that Citix had launched a new version for Win x64 the very same day, https://www.citrix.com/English/ss/downloads/details.asp?downloadId=1859596&productId=15005. Company policy requires F-Secure to be installed, and it is installed once logging on to the domain. The firewall is default on, which must be turned off. Use another firewall. Else I only accessed the intranet over http, but everything else was hidden. No warning, no nothing. But the solution was simple, F-Secure’s firewall, Citrix Access Gateway and Windows 7 was not best pals together.

Saturday, September 05, 2009

Installing Windows 7 Starter on Asus Eee 901

BIOS

First update your Bios to the latest version. I don’t know of any known problems if you don’t. But I did update bios before installing, better safe than sorry. I found that the current latest BIOS for Asus Eee 901 was 2103, found here.

Come one Asus…your site, sitemap, search and navigation are rubbish, confusing and slow.

Unzip the downloaded bios, put the “901-ASUS-2103.ROM” file (or whatever newer version) on a usb drive and rename it to “901.ROM”. With the power of, put the usb stick in the Eee and power on. Press ALT+F2. This will start the bios update, searching for .ROM-files on any usb drive since Eee doesn’t have any cdrom or floppy disk.
If problems reading the thumb drive try format it as FAT.

Upgrading bios is risky and could possibly leave your computer in a useless state. Until you get a new bios properly installed. 

SSD Memory Card, Replacing the Hard Drive

There is no traditional hard disk in the 901, only a SSD which functions as the hard drive. I don’t fully trust that Windows 7 will be problem free, and quite happy with the Linux installed. Therefore I initially wanted to keep the Linux that were shipped installed on my Eee as I bought it. And replace the existing SSD with a new, keeping the old SSD in a drawer somewhere. This way I will always have a fallback on returning to the old and working operating system just by refit the old “hard drive”. But it seemed to be a bit hazardous to replace, and a bit expensive to buy another SSD, probably just leaving it in the drawer never to use it again.

Therefore plan b was to backup the existing (Xandros) Linux Operating System. But I am not familiar with Linux, and after some googling and blog reading, I gave up. By by Xandros with no safety net .

Shrink Windows 7 (vLite)

This step was probably a bit tedious since my first attempt to install on the 4GB drive wasn’t a big success. Ending up with installing on the other drive, which has 16GB, space is not an issue any way. On the 4GB it installed ok, but left between 180 and 500 MB free. Which made the pc act in strange manners, often with the message “out of memory”. But the step-by-step guide for vLite was found here, http://forum.eeeuser.com/viewtopic.php?id=57434.

Preparing USB install media

The Asus Eee 901 doesn’t have a cdrom to install from, and since the newly inserted hard drive is empty, I need to prepare a usb media to be my bootable install media. Some blogs warned against using a media larger than 4GB, but my 8GB TDK thumb drive was no problem for me.

This will work from another PC with Vista installed, from XP you will a workaround to see the usb drive. Do the following steps:

Diskpart (from command prompt) 
List Disk (in the window that opened in 1) 
Select Disk n (Replace n with number reflecting your usb drive) 
Clean (remember, this will wipe out any content on the usb drive) 
Create Partition Primary 
Active 
Format fs=fat32 quick 
Assign (gives the usb stick a drive letter)

Copy the content of the dvd to the usb media. My version of Windows 7 is a shrinked .iso file, which I unzip to a temporary location and copy from there.

Installing

Start the Asus Eee with the USB media inserted. Press [Esc] repeatedly while the pc is starting. A dialog with the preferred booting device is shown. The first two are the installed SSD-drives. The third one was my  usb drive. The windows was starting up. Choose the clean install, not upgrade. I then deleted all partitions on both disk 1 and 2, and formatted both drives. My first attempt to install on the 4GB drive succeeded, but the drive was so full it kept giving me error messages and warnings about the low space available. I repeated this step and installed on the 16GB drive. Where it now runs successfully. 

Comments and wishes on this will result in a more step-by-step guide with screen shots.

Tuesday, August 25, 2009

Cannot start Microsoft Office Outlook. Cannot open the Outlook window.

Today Outlook doesn't start. It gives me the error message "Cannot start Microsoft Office Outlook. Cannot open the Outlook window.". Probably from the crash my computer had yesterday.

Trying scanpst.exe to repair. But it wasnt the problem this time.

Theese magic lines from command prompt solved the problem:
Outlook.exe /resetnavpane

Then the day can begin.

Monday, August 17, 2009

Automated Integration Testing WCF Services

Automated testing, both unit and integration, is the holy grail these days. I’m all up for the concept, and I’ve done a fair part of testing myself already. I realized at one point that my unit test were really integration test. But started with stubs and mocks, making my unit tests happy and green. But we all have to start somewhere, right?

But there are pitfalls, a lot of them. I’ve had a few projects in row now where we have used WCF Services as ordinary Web Services. Cause we are communication with “others”. Fairly simple, just add basicHttpBinding on your endpoints.

Exception logging
I want exception logging to happened on all my public methods. I prefer doing this with a [ErrorHandlerBehavior] described in another article here on my blog. This works fine, I am kind a liking that some magic happens on my service class, with logging the exception and throws it again.

Application Initialization
But then I realize I need a Application Start, to make some global configuration and settings run. This might be NHibernate etc. Now if I presume my WCF Service would always run inside IIS, I could use Global.asax in my service. Just add this file to the project, and hook up like this:
This is supposed to be a ordinary Web Service, so there is no problems with that. Except for my automated tests. When my test project launches, the service is hosted in the WCF Service Host. Which isn’t IIS. Obviously. Now I have to make my own Service Host, which triggers something like application start.

I fooled around with the AppInitialize method: public static void AppInitialize();
Which supposedly can be put in any type that is defined in a C# file in the application’s \App_Code directory. When the AppDomain is started, ASP.NET checks whether there is a type that has such as method (exact name and signature) and invokes it. I’m not sure if this could have work with an WCF Service, but I couldn’t make this work.

Self Hosting
So I made my WCF Service self hosted when tests are ran, but “normal” IIS hosted when run in production and test environment.

I used the SelfHosting.cs and the test script would look something like this:

[TestMethod]
[ExpectedException(typeof(FaultException<string>))]
[DeploymentItem(@"C:\\Code\\Foo\\Bin\\")]
public void OrderService_MyException_FaultExceptionWithMyArgumentExceptionAsString()
{
using (var host = new SelfHosting())
{
host.Start();
using (var client = new OrderServiceClient())
{
try
{
client.MyException();
}
catch (FaultException<string> ex)
{
Assert.AreEqual("System.ArgumentException", ex.Message);
Assert.AreEqual("MyException", ex.Detail);
throw;
}
}
}
//there should have been done some error logging by now.
}

Friday, August 14, 2009

Lotus Notes ODBC Driver Connecting to UNC Path

I’ve previously made a WebService that encapsulates calls to a Lotus Notes database. From this database I extract meeting rooms and today’s meetings for each room. This information is used by others to show on monitors beside each meeting room. They just call my service, and get their xml back. All the “ugly” communication with Lotus Notes is completely hidden from them.

The service hasn’t been all that stable, not my service fault though, but since the service hides all the Notes problems – it is easy to blame the messenger. I was not initially allowed to read directly from the master database file (database.nsf). That is placed behind firewalls on another server. The workaround for this was setting up a replication. This worked very well, as long as someone is logged on the console, on the server. See the problem… Sometimes the service shows old data that is displayed beside the meeting rooms. Causing confusion about who has reserved the room or not. I’m not a Notes-kind of guy, so this might have been set up more robust or elegant.

But now I am given a hole in the firewall, to a network file share, directly to the master database file. Which in Lotus Notes is an nsf file. The service can now access the file, no longer to the replica C:\Program Files\IBM\Lotus\Domino\Data\FooCopy.nsf, but directly to the \\fooserver\notes\Foo.nsf. The file share is protected with access only to a given user. Accessing UNC Path is supported with the Lotus Notes ODBC Driver. But I ran into some problems with the UNC Path logon.

Previously I’ve used impersonation when accessing the UNC Path. So I tried this first. Impersonation & IDisposable worked seemingly very well. But the ODBC driver was still not happy. I fooled around quite a bit with the Win32API Impersonation, changing the dwLogonType and more. But it would not work. The service could now see the file, and read from the file. But the ODBC driver gave me errors:

ERROR [S1000] [Lotus][ODBC Lotus Notes]Access to data denied.
ERROR [IM006] [Microsoft][ODBC Driver Manager] Driver's SQLSetConnectAttr failed
ERROR [01000] [Microsoft][ODBC Driver Manager] The driver doesn't support the version of ODBC behavior that the application requested (see SQLSetEnvAttr).

Then I thought of mapping the share with letter would be the simplest and easiest solution. Why not do this programmatically. I used a Win32 API called WNetUseConnection to connect to a UNC path with authentication. This will allow you to connect to a remote machine, even if it is not on the same domain, and a given username and password. I found this thread, with this code sample. It worked smoothly. The service could both see the file, and the ODBC driver didn’t object anymore. Problem solved!

Code sample is quoted here:

public class PinvokeWindowsNetworking
{
#region Consts
const int RESOURCE_CONNECTED = 0x00000001;
const int RESOURCE_GLOBALNET = 0x00000002;
const int RESOURCE_REMEMBERED = 0x00000003;

const int RESOURCETYPE_ANY = 0x00000000;
const int RESOURCETYPE_DISK = 0x00000001;
const int RESOURCETYPE_PRINT = 0x00000002;

const int RESOURCEDISPLAYTYPE_GENERIC = 0x00000000;
const int RESOURCEDISPLAYTYPE_DOMAIN = 0x00000001;
const int RESOURCEDISPLAYTYPE_SERVER = 0x00000002;
const int RESOURCEDISPLAYTYPE_SHARE = 0x00000003;
const int RESOURCEDISPLAYTYPE_FILE = 0x00000004;
const int RESOURCEDISPLAYTYPE_GROUP = 0x00000005;

const int RESOURCEUSAGE_CONNECTABLE = 0x00000001;
const int RESOURCEUSAGE_CONTAINER = 0x00000002;


const int CONNECT_INTERACTIVE = 0x00000008;
const int CONNECT_PROMPT = 0x00000010;
const int CONNECT_REDIRECT = 0x00000080;
const int CONNECT_UPDATE_PROFILE = 0x00000001;
const int CONNECT_COMMANDLINE = 0x00000800;
const int CONNECT_CMD_SAVECRED = 0x00001000;

const int CONNECT_LOCALDRIVE = 0x00000100;
#endregion

#region Errors
const int NO_ERROR = 0;

const int ERROR_ACCESS_DENIED = 5;
const int ERROR_ALREADY_ASSIGNED = 85;
const int ERROR_BAD_DEVICE = 1200;
const int ERROR_BAD_NET_NAME = 67;
const int ERROR_BAD_PROVIDER = 1204;
const int ERROR_CANCELLED = 1223;
const int ERROR_EXTENDED_ERROR = 1208;
const int ERROR_INVALID_ADDRESS = 487;
const int ERROR_INVALID_PARAMETER = 87;
const int ERROR_INVALID_PASSWORD = 1216;
const int ERROR_MORE_DATA = 234;
const int ERROR_NO_MORE_ITEMS = 259;
const int ERROR_NO_NET_OR_BAD_PATH = 1203;
const int ERROR_NO_NETWORK = 1222;

const int ERROR_BAD_PROFILE = 1206;
const int ERROR_CANNOT_OPEN_PROFILE = 1205;
const int ERROR_DEVICE_IN_USE = 2404;
const int ERROR_NOT_CONNECTED = 2250;
const int ERROR_OPEN_FILES = 2401;

private struct ErrorClass
{
public int num;
public string message;
public ErrorClass(int num, string message)
{
this.num = num;
this.message = message;
}
}


// Created with excel formula:
// ="new ErrorClass("&A1&", """&PROPER(SUBSTITUTE(MID(A1,7,LEN(A1)-6), "_", " "))&"""), "
private static ErrorClass[] ERROR_LIST = new ErrorClass[] {
new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"),
new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"),
new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"),
new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"),
new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"),
new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"),
new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"),
new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"),
new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"),
new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"),
new ErrorClass(ERROR_MORE_DATA, "Error: More Data"),
new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"),
new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"),
new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"),
new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"),
new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"),
new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"),
new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"),
new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"),
new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"),
};

private static string GetErrorForNumber(int errNum)
{
foreach (ErrorClass er in ERROR_LIST)
{
if (er.num == errNum) return er.message;
}
return "Error: Unknown, " + errNum;
}
#endregion

[DllImport("Mpr.dll")]
private static extern int WNetUseConnection(
IntPtr hwndOwner,
NETRESOURCE lpNetResource,
string lpPassword,
string lpUserID,
int dwFlags,
string lpAccessName,
string lpBufferSize,
string lpResult
);

[DllImport("Mpr.dll")]
private static extern int WNetCancelConnection2(
string lpName,
int dwFlags,
bool fForce
);

[StructLayout(LayoutKind.Sequential)]
private class NETRESOURCE
{
public int dwScope = 0;
public int dwType = 0;
public int dwDisplayType = 0;
public int dwUsage = 0;
public string lpLocalName = "";
public string lpRemoteName = "";
public string lpComment = "";
public string lpProvider = "";
}


public static string ConnectToRemote(string remoteUNC, string username, string password)
{
return ConnectToRemote(remoteUNC, username, password, false);
}

public static string ConnectToRemote(string remoteUNC, string userName, string password, bool promptUser)
{
NETRESOURCE nr = new NETRESOURCE();
nr.dwType = RESOURCETYPE_DISK;
nr.lpRemoteName = remoteUNC;

int ret;
if (promptUser)
ret = WNetUseConnection(IntPtr.Zero, nr, "", "", CONNECT_INTERACTIVE | CONNECT_PROMPT, null, null, null);
else
ret = WNetUseConnection(IntPtr.Zero, nr, password, userName, 0, null, null, null);

if (ret == NO_ERROR) return null;
return GetErrorForNumber(ret);
}

public static string DisconnectRemote(string remoteUNC)
{
int ret = WNetCancelConnection2(remoteUNC, CONNECT_UPDATE_PROFILE, false);
if (ret == NO_ERROR) return null;
return GetErrorForNumber(ret);
}
}

Saturday, August 01, 2009

Hotfix KB 971092 for Visual Studio 2008 SP1 install problems

Hotfix KB 971092 for Visual Studio 2008 SP1 install problems. I found this workaround and it did the trick for me.

Applies to:
Security Update for Microsoft Visual Studio 2008 Service Pack 1 (KB971092)

Symptoms:
The update installs successfully and but will be offered again by Windows Update as a new update. This can be repeated indefinitely.
or
the standalone installer tells you that this update "does not apply, or is blocked by another condition on your system".

Workaround (found here):
1. Download the stand-alone version of VS90SP1-KB971092-x86.exe.
2. Start the installation VS90SP1-KB971092-x86.exe
3. Wait for the error message to come up – do not close the window
4. Copy the temp. (ex C:\4e9d64946a9fc8a7e9c1c82f02d964) folder where the patch has been unpacked to a new folder, for example onto your desktop.
5. Close VS90SP1-KB971092-x86.exe that you started in step 2.
6. Navigate to {Program Files}\Microsoft Visual Studio 9.0\Common7\Tools and find vsvars32.bat.
7. Change the permissions on the file to allow everyone to edit it.
8. Start VS90SP1-KB971092-x86.msp from within the saved folder and the process should complete.
9. You may want to reset permissions that you gave in step 7.

Wednesday, July 08, 2009

Exporting GridView or ListView to Excel

A handy and simple way of exporting the content of your GridView og ListView to Excel.

protected void ExportExcelButton_OnClick(object sender, EventArgs e)
{
    Response.Clear();
    Response.Buffer = true;
    Response.AddHeader("content-disposition", "attachment;filename=Contacts.xls");
    Response.ContentType = "application/vnd.ms-excel";
    Response.Charset = "";
    EnableViewState = false;
    var stringWriter = new StringWriter();
    var htmlTextWriter = new HtmlTextWriter(stringWriter);
    userListView.RenderControl(htmlTextWriter);
    Response.Write(stringWriter.ToString());
    Response.End();
}

Thursday, July 02, 2009

Error consuming a WSDL in Visual Studio

Symtons
Adding a WCF “Service Reference” in Visual Studio 2008, pointing at http://localhost/FooMessage?wsdl. All the different files are added in Solution Explorer. But investigation the Reference.cs beneath Service References –> ServiceReference1 –> Reference.svcmap –> Reference.cs (found if “Show All Files” is clicked in Solution Explorer) reveals that no code has been generated. No warnings, no nothing. The app.config doesn’t contain no endpoints or binding either.

Cause
I’ve tried to validate the wsdl with the step by step procedure found here http://webservices20.blogspot.com/2008/10/how-to-validate-your-wsdl.html. But the wsdl is “passed” as a legal wsdl. Using svcutil.exe gives me errors though:

C:\>svcutil http://localhost/FooMessage?wsdl
Microsoft (R) Service Model Metadata Tool
[Microsoft (R) Windows (R) Communication Foundation, Version 3.0.4506.2152]
Copyright (c) Microsoft Corporation.  All rights reserved.

Attempting to download metadata from 'http://localhost/FooMessage?wsdl' using WS-Metadata Exchange or DISCO.
Error: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: Object reference not set to an instance of an object.
XPath to Error Source: //wsdl:definitions[@targetNamespace='
http://foo.facade.com/']/wsdl:portType[@name='SendFooMessage']

Error: Cannot import wsdl:binding
Detail: There was an error importing a wsdl:portType that the wsdl:binding is dependent on.
XPath to wsdl:portType: //wsdl:definitions[@targetNamespace='
http://foo.facade.com/']/wsdl:portType[@name='SendFooMessage']
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://foo.facade.com/']/wsdl:binding[@name='SendFooMessagePortBinding']

Error: Cannot import wsdl:port
Detail: There was an error importing a wsdl:binding that the wsdl:port is dependent on.
XPath to wsdl:binding: //wsdl:definitions[@targetNamespace='
http://foo.facade.com/']/wsdl:binding[@name='SendFooMessagePortBinding']
XPath to Error Source: //wsdl:definitions[@targetNamespace='http://foo.facade.com/']/wsdl:service[@name='SendFooMessage']/wsdl:port[@name='SendFooMessagePort']

Generating files...
Warning: No code was generated.
If you were trying to generate a client, this could be because the metadata documents did not contain any valid contracts or services
or because all contracts/services were discovered to exist in /reference assemblies. Verify that you passed all the metadata documents to the tool.

Warning: If you would like to generate data contracts from schemas make sure to use the /dataContractOnly option.

Here follows a days effort in trying to make adjustments to the wsdl. Which by the way isn’t mine. Trying to narrow done the different possibilities.

Workaround
To narrow the story down. It turned out to be the differences between XmlSerializer and XmlFormatter. If you use XmlSerializer (use SvcUtil option /serializer:XmlSerializer), it should work fine. Use a tool, svcutil with a switch, to generate the needed code.
svcutil http://localhost/FooMessage?wsdl /serializer:XmlSerializer
This generates two files for you, the SendFooMessage.cs og output.config.

Tuesday, June 30, 2009

Consuming a Web Service with an error in WSDL

In one of my projects I am consuming a third party Web Services, written in I don’t know what. I have WCF Service References to them.

They launces new versions of their services  quit often, so I was fairly sure something was wrong this time. Updating or even deleting and adding references somehow didn’t work right. I could see the service in the browser, after logging on two times (this is normal). Adding or updating  the reference itself also works fine. I’m happy. Started updating all five references, and cleaned up the mess in app.config. Done this many times before. Building.

Error    4    Custom tool error: Failed to generate code for the service reference 'TheService'.  Please check other error and warning messages for details.    D:\temp\ConsoleApplication2\ConsoleApplication2\Service References\TheService\Reference.svcmap    1    1    ConsoleApplication2

What? Expanding all solution files, to investigate the code behind Service Reference/TheService/Reference.svcmap/Reference.cs. Empty!

Running wsdl.exe and svcutil.exe on the downloaded wsdl to investigate more. Finally something to understand: The complexType SomeClass has a property with a blank space in the name attribute. Not allowed. It looked something like this: 

<xs:element name="statusCode " type="foons:StatusCode "/> 




Luckily the vendor was quick to fix this when told. But I really would like Visual Studio to be more robust, either telling me what the problem is when adding a reference to a none valid WSDL or even maybe just remove the whitespace. Like IE does when watching the WSDL file….

Publishing the code samples in Blogspot

I’ve swapped from writing articles inside blogger.com to try out Live Writer. Mainly cause of the hell will copy and pasting in code samples or xml samples. Dave Haynes’s blogged about it here, and I’ll try it out.

Friday, June 26, 2009

WcfService that acts like a WebService

This article is meant as a tutorial for using a logging tool for a WcfServices that looks to the outside world as an old WebService. (Pardon the namespaces, they have been changed to protect the innocent.)

WcfService that acts like a WebService
What I’ve used to do in the past is just add a WCF Service Library to the solution, and make sure binding="basicHttpBinding" is done. This way other platforms and applications could access the service like add web reference that looks something like http://localhost/WebService/WebService.OrderService.svc?wsdl. Why you want to do this? You want to take advantage of what you get in WCF, but still are able to act like a WebService to others that can’t implement WCF Service Reference. Everything else is like standard WCF, [ServiceContract], [OperationContract], [DataContract] and [DataMember] etc.

WcfService that acts like a WebService, but really is a Web Application
Another way of doing this is add a Web Application, strip out all that you don’t need. Like delete Default.aspx*.But instead of adding a new WCF Service, add an ordinary class, and then rename to whatever.svc. And remove all content, and replace it with these few lines:
<%@ ServiceHost Service="Services.OrderService" %>
This service reference should of course map to a class in your solution, probably the business layer. Make sure you add a reference. The business layer would then need a reference to System.Servicemodel to be able to add the needed attributes:

[ServiceBehavior(Namespace = "http://brembo.name/namespace/workorder")]
public class OrderService : IOrderService

[ServiceContract(Name = "OrderService", Namespace = "http://brembo.name/namespace/workorder")]
public interface IOrderService



The web.config would only need these lines (remove everything else):



<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="Services.OrderService" behaviorConfiguration="DebuggingBehaviour">
<endpoint address="" binding="basicHttpBinding" bindingNamespace="http://schema.brembo.name/" contract="Services.IOrderService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DebuggingBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<appSettings/>
<connectionStrings/>
</configuration>



The Web Application contains by default many no longer needed references. These are the only one needed: System, System.Core, System.Data, System.Runtime.Serialization, System.ServiceModel. Also add your business layer.




If you like to remove the App_Data folder which isn’t needed, unload project, edit project file and remove these lines:



<itemgroup>
<folder include="App_Data\">
</itemgroup>



This should now run as a wcf service, reachable from ordinary WebService clients.

Monday, June 22, 2009

Project References and Copy Local

In our new project we use both NHibernate. The solution consists of the normal layers; data, business, presentation and common.

The data tier has references to NHibernate, and in hibernate.cfg.xml a need for NHibernate.ByteCode.LinFu is configured. The reference to NHibernate is set to copy local, and NHibernate doesn't exist in the GAC. Which otherways could interfere with the copy local. Ok, everything fine so far. Also a need for a reference to NHibernate.ByteCode.LinFu with copy local is needed, since this assembly is needed run-time. Added a reference with copy local, to get this assembly in the runtime folder. I'm not to happy with this reference, but I can leave with it. What I'd really like is NHibernate self to handle this, and get hold of its needed assemblies. But there is a dynamic reference here.

Fine by now, everything ends up in the datalayer\bin\debug folder. Ahh, but then. I add a project reference in the business layer to the data layer. And from the web application there is added a project reference to the business layer. In the Web\bin folder there are missing some dll's after compiling. Everything that NHibernate needs are there (and all other assembly include their needed assemblies), except for NHibernate.ByteCode.LinFu, LinFu.DynamicProxy and hibernate.cfg.xml.

I don't want the client to know about all the different needs my data access has. So linking in files the client itself doesn't need is not a good option for me. Adding references to assembly not needed by the client the same.

So for now I uses post build events on my data project. Copies explicit the needed files to a temporary bin folder.
mkdir "$(SolutionDir)Bin"
xcopy "$(TargetDir)*LinFu*" "$(SolutionDir)Bin" /y
xcopy "$(TargetDir)hibernate.cfg.xml" "$(SolutionDir)Bin" /y

The client copies all files from this directory in the pre build event to the web\bin folder like this:




xcopy "$(SolutionDir)Bin" "$(TargetDir)*.*" /y

This way all the missing files are copied back and forth, ending up where they are needed.

Saturday, June 20, 2009

Toyota Way House

At the Norwegian Developers Conference 2009 I went to the track with Craig Larman, "Toyota Way House".

The Toyota Way 2001 was educational, and explained to me why some of our project had worked and some had not at all... As a developer by heart, I really enjoyed the bit about a manager should be a teacher and technical specialist in the craftmanship. I had to nod my head, wishfully...

http://en.wikipedia.org/wiki/The_Toyota_Way

Monday, June 01, 2009

My customization of blogger.com

Note to myself when I change template, or if others sees the need, this is my few customizations.

Favicon
Just belove the <head> add theese lines:
<link href='http://logica.com/favicon.ico' rel='shortcut icon'/>
<link href='http://logica.com/favicon.ico' rel='icon'/>

To remove the blogspot header, add this line just above the body tag:
#navbar-iframe { display: none !important;}

Thursday, January 01, 2009

SelfHosting.cs

public class SelfHosting : IDisposable
{
private static ServiceHost serviceHost;
private ApplicationController controller;

///
/// Starts this instance. From Test Projects only.
///

public void Start()
{
Debug.WriteLine("Entering SelfHosting Start");
if (serviceHost != null)
throw new AddressAlreadyInUseException("Selfhosting already started");
serviceHost = new ServiceHost(typeof(OrderService));
serviceHost.Open();
ApplicationStart();
}

///
/// Stops this instance.
///

public void Stop()
{
Debug.WriteLine("Entering SelfHosting Stop");
if (serviceHost != null)
serviceHost.Close();
serviceHost = null;
}

private void ApplicationStart()
{
Debug.WriteLine("Entering SelfHosting ApplicationStart");
try
{
controller = new ApplicationController();
controller.Initialize(Environment.CurrentDirectory);
}
catch (ApplicationInitializationException exception)
{
LoggerFactory.New().Fatal(exception);
throw;
}
}



#region Implementation of IDisposable

private bool disposed;
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// Implements to avoid when starting a
/// test after another one has failed leave a none clean state.
///

public void Dispose()
{
Debug.WriteLine("Entering SelfHosting Dispose");
if (!disposed)
{
Dispose(true);
GC.SuppressFinalize(this);
disposed = true;
}
}

///
/// Releases unmanaged and - optionally - managed resources
/// Set large fields to null
/// Free managed resources
///

/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
private void Dispose(bool disposing)
{
if (disposing)
{
controller.Dispose();
if (serviceHost != null)
serviceHost.Close();
serviceHost = null;
}
}

///
/// Releases unmanaged resources and performs other cleanup operations before the
/// is reclaimed by garbage collection.
///

~SelfHosting()
{
Dispose(false);
}

#endregion
}