31.03.2009 г.

Loading a custom config file instead of app.config

Today happily I found a solution for the problem explained in a yesterday post in my blog.
The solution is to implement a class that changes the configuration file, associated with the project. Here is some working code doing that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace OmeksOfficeTools
{
public class ConfigurationFileChanger : IDisposable
{
private string currentConfigFilePath;
private string newConfigFilePath = @"YourLibraryPathHere";

public ConfigurationFileChanger()
{
currentConfigFilePath = AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString();
ChangeConfigFile(newConfigFilePath);
}
protected void ChangeConfigFile(string newConfigFilePath)
{
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", newConfigFilePath);
FieldInfo[] fiStateValues = null;

Type initStateType = typeof(System.Configuration.ConfigurationManager).GetNestedType("InitState", BindingFlags.NonPublic);
if (initStateType != null)
{
fiStateValues = initStateType.GetFields();
}
FieldInfo fiInit = typeof(System.Configuration.ConfigurationManager).GetField("s_initState", BindingFlags.NonPublic | BindingFlags.Static);
FieldInfo fiSystem = typeof(System.Configuration.ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
if (fiInit != null && fiSystem != null && null != fiStateValues)
{
fiInit.SetValue(null, fiStateValues[1].GetValue(null));
fiSystem.SetValue(null, null);
}
}

public void Dispose()
{
ChangeConfigFile(currentConfigFilePath);
}
}
}


This really worked for me. I use .Net Framework 3.5 sp1 but I think this will work for .Net Framework 2.0 and above.
The idea is that this code sets the value for app.config path that the framework is going to use and then forces it to reload its configuration by setting 's_initState' to false and 's_configSystem' to null.
The class implements IDisposable to be able to revert to the old configuration file.
So it is good to use the using pattern as follows:
using (ConfigurationFileChanger cfch = new ConfigurationFileChanger())
{
SecurityServiceClient client = new SecurityServiceClient();
//Do your service operation calls here...
}

Where SecurityServiceClient is my service client proxy.

Enjoy :)

P.S. I of course didn't came to that solution while dreaming tonight, so I should give my thanks to the author of THIS article (see also comments under the article).

30.03.2009 г.

Consuming WCF Service in a library

To be able to consume a WCF service you have to create a service proxy client that is used to call service operations. It is not something different than consuming an ASP.NET web service.
You can get a proxy client using 4 different approaches:
1) Generate it using Visual Studio
2) Generate it using the command line tool svcutil.exe
3) Manually defining a proxy class
4) Using ChannelFactory class

However only 1) and 2) are good for me because in 3) and 4) you need to know the type of the service contract prior to creation.
In 1) and 2) the service metadata is used instead for generating the service contract, datacontract and so on on the client side. Btw 1) and 2) are practically equivalent because Visual Studio is using svcutil.exe to create the service reference. Svcutil just gives us some other options.

So let me step in a problem I ran into today.
Because I like the approach with configuring a service client in a configuration file rather than doing this in code, I was surprised to find today that there is no straightforward way of consuming a WCF service from a project that compiles in a dll.
That is very strange. The reason is that when creating an instance of the proxy client class without passing a Binding and EndpointAddress in the constructor (using the parameterless ctor) these are read from the app.config file. And in a library project this is impossible for the WCF framework.
You will get error like :
"Could not find default endpoint element that references contract ...


I should say that I didn't have any problems creating a service reference in the library project and also service client configuration was added to my app.config file. But what for if this configuration can not be read.
Some will probably say why not creating a Binding and EndpointAddress objects in code and then pass them to the ctor for the proxy client. Answer is that I don't want to change my code every time I change something in my service configuration. I just want to update the reference and have all the necessary configuration generated for me in the configuration file.
This problem is important when you design VSTO MS Office Add-ins, because these add-ins compile to a dll, not executable. So I'm curious how can I consume WCF services in a VSTO Add-in with still configuring my service client in a configuration file.

I read lots of forum threads today trying to find the solution and found out that there are other developers experiencing the same problem. The only solution I consider good is to create a parser for a custom configuration file and to load the library configuration and extract it.

HERE is a example of this approach, but the posted class needs to be extended to parse at least binding customizations in the configuration file that it opens.

However I think Microsoft should have thought about this more when designing WCF.

Important when using MessageContract as parameter in an operation

Today, while trying to create a reference to a WCF service I got the following exception:
The operation 'xxxxxxxx' could not be loaded because it has a parameter or return type of type System.ServiceModel.Channels.Message or a type that has MessageContractAttribute and other parameters of different types. When using System.ServiceModel.Channels.Message or types with MessageContractAttribute, the method must not use any other types of parameters.

It is quite obvious from the exception message what was wrong in my service, that was the obstacle in the creation of a service proxy.
In WCF there is a limitation that if you use a type that is marked with a MessageContract attribute as a return value or operation parameter, it is obligatory that all the parameters and return value(if present) should be types marked with that attribute too.

Also it is recommended as a good practice to encapsulate all operator parameters in a single message contract.

In my case the mistake was that I had an operation with a return type of 'bool' and taking a parameter that was tagged with a MessageContractAttribute attribute.

18.03.2009 г.

VSTO - Where to start?

You know it is quite usual for a developer to spend many many hard hours on a problem or a new technology and research everything on himself losing much of his nerves on that. And after getting some painful know-how on the problem, he/she comes across a post somewhere that explains everything he/she understood by himself with great details and also adding many other things.

So that was my case too. After coding 2 Microsoft Office Add-ins for Excel and Outlook, today I came across this interesting thread:
It includes many things you should consider when starting to deal with VSTO and developing Add-ins for MS Office products.

I myself have still much to learn, especially for the deployment part and some other hacks so this FAQ will be my priority for these days too.

Have fun :)

15.03.2009 г.

Configuring a wireless router for dummies ... like me :)

Not so far ago (one week) I purchased a wireless router for home usage, because I wanted to make my wife stop using my notebook, but her own PC. Her excuse till now was that her PC is not connected to the Internet. So for me the decision was clear. Before the introduction of the router I had a static IP address set on my notebook's ethernet adapter. With the router, this static IP address should be given to the router itself, and all other members of the network should be given dynamic IP addresses by router's DHCP server.



But first... the hardware. Except the router, some cables are needed too. You need a cable for each PC that doesn't have a wireless network adapter. This cable should not be a cross-over but a straight one. (see the scheme below)



After done that it is time to configure the router. You should do that from a computer that is wired to the router. Routers are accessed by their IP address. Different manufacturers give their routers different default IP address and you should contact check this before you start configuring. The main IP addresses that are used are as follows:
-192.168.0.1
-192.168.1.1
-192.168.2.1

After successfully accessing your router you will probably see its GUI configuration.
Configuration is straightforward even for a dummy like me :).
Let me divide configuration in 4 sections: LAN configuration, WAN configuration, Wireless configuration and Security configuration.

1) LAN configuration

You should give your router IP address, Gateway and Mask. This IP address is not the static one, but the one the router will use in our home network. For example 192.168.0.100.

There should be a section for configuring DHCP server settings.
First of all you should enable DHCP server. Then you should set the start IP address and the end IP address, Mask and Gateway. Gateway should be the IP of the router. DHCP server will now give other members of the network (wired or wireless) IP addresses in the range between start and end IP.

Reservations - This section is for reserving an IP address to a particular network adapter in the LAN. For example if you want your notebook to be known always as 192.168.0.23 in your private network you should reserve this IP address to your notebook's network adapter by associating it with network adapter's MAC address.
Reserving an IP for a MAC is vital for configuring port forwarding.

Port forwarding - this is a very helpful feature of most of the routers. By configuring a port forwarding you expose some LAN member port to the WAN. For me it is helpful because doing this I can still use a remote desktop connection to my PC, which doesn't need a static IP address.

EDIT: For using a remote desktop you need to forward 1723 and 3389 ports.

2) WAN configuration

If you want your private network to access Internet through the router you should enable WAN connection. Then you should choose the WAN connection type: Dynamic, Static IP, PPPoE, PPTP. First two doesn't need an explanation and for the other 2 you can read those:
PPPoE
PPTP
Choose Static IP and fill in the static IP, Mask and Gateway provided for you by your ISP.

3) Wireless configuration

Here you can give your wireless network a meaningful name, known as SSID. My advice is don't give your network name like Simsons (if your family name is Simson) cause if you do so everyone will know this network belongs to you. In my opinion it is a potential vulnerability. Also you should choose to broadcast your SSID.

4) Security configuration.

Firewall - enable it.
Router access password - you should have a default password for your router. Something like 'admin' or 'password'. My advice is to change this password.

Wireless Security Settings - this is the main part. Your main choices here are WEP or WPA.

I chose WEP for me even though WPA is newer and more secure.
Here important are the encryption strength and the pass phrase. You don't need to memorize your Pass phrase. It is needed just for generating the WEP key.
You should carefully write down your WEP key. It is used to connect to your wireless network.
Other important setting before generating the key is the encryption strength. If present you should choose 128 bits.

If you want your wireless network to be safer you may want to configure an Access control list (ACL) too. This list gives you the ability to allow wireless connections only from specific wireless network adapters, presented in the list by their MAC addresses.

That's all I managed to describe from my experience with my router's configuration.
Now I can use my notebook under the shower in my bathroom yoooohoooo :)