My blog has moved

I moved my blog to http://linqto.net/blog

Posted in Uncategorized | Leave a comment

Keep WCF Client Configuration in a Class Library app.config

When building a WCF client with Visual Studio with the simple “Add Service Reference” feature, you get your client configuration (system.serviceModel section) in your app.config file. If the project that holds the config file is an application (Winform, WPF, ASP.NET etc.) then probably you’re just in the demo phase. Usually you have several projects that need to call the service, and you don’t want to add the service references in each. Also, you don’t want to bind all other project to the WCF technology, so you want them to call a library that communicates with the WCF service.

After creating you class library with the service references and app.config file, you can create a layer over the service calls like that:

// Service code
[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}

// Client code
public class Service1Agent
{
    public static int GetData(string value)
    {
        using (var client = new Service1Client())
        {
            return client.GetData(value);
        }
    }
}

Now any call to the WCF service is unaware of the WCF technology:

var result = Service1Agent.GetData(5);

When running this simple and “obviously should work” code, you’ll get the following famous exception:

Could not find default endpoint element that references contract ‘Service1.IService1′ in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.

The reason for that is simple. Class libraries don’t have a configuration file of their own in run-time and they rely on the configuration file of the app they run within. You end up copying the system.serviceModel section to the app.config or web.config of your application and also to your tests project (as said here and here). Although you might accept the duty to do it every time your class library config file gets updated (adding service reference, changing address, changing security etc.), there are scenarios this is not acceptable, for example when you develop your ServiceAgent project for an existing product that you’re not allowed to edit its application config file.

Although this is a very famous issue, there are not many solutions for that (except to copy). Possible solution to the problem you can find here, however the code that generates the client is very complicated. A better solution can be found here, but it assumes that you know the endpoint name and it is hard-coded.

My solution is based on the latter, but is dynamic. Microsoft added a new class in .NET 4 called ConfigurationChannelFactory. This class allows you to create a channel with custom configuration source, for example:

var channelFactory = new ConfigurationChannelFactory<IService1Channel>(endpointName, configuration, null);
var client = channelFactory.CreateChannel();

var result = client.GetData(5);

For the above code to work, you need to load your configuration and know the endpoint name. Loading the configuration from file is easy with the ConfigurationManager.OpenMappedExeConfiguration method:

var configuration = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = "app.config" }, ConfigurationUserLevel.None);

The app.config file is the class library config file. You can have it copied to the application output directory by setting “Copy To Output Directory” to “Copy always” in the file properties.

As for the endpoint name, in order not to make a switch-case for all service referenceד you got, you need to find it in the config file. In the config file the endpoint may appear like that:

<endpoint address="http://localhost:12345/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="Service1.IService1" name="BasicHttpBinding_IService1" />

Knowing the contract name can help you find the endpoint name. The interface hierarchy in the generated client code is:

With an instance of IService1Channel you can call the service and close connection since it is IDisposable, so this is the type you should pass as the generic T parameter to the ConfigurationChannelFactory constructor.

The interface IService1 has an attribute with the ConfigurationName that corresponds to the contract attribute value in the config file:

[System.ServiceModel.ServiceContractAttribute(ConfigurationName="Service1.IService1")]
public interface IService1
{
}

In order to find this attribute we can find the interface that IService1Channel inherits from and find the attribute with GetCustomAttributes:

var channelType = typeof(T);
var contractType = channelType.GetInterfaces().First(i => i.Namespace == channelType.Namespace);
// We compare the namespace because the inteface inherits also from System.ServiceModel.IClientChannel
var contractAttribute = contractType.GetCustomAttributes(typeof(ServiceContractAttribute), false).First() as ServiceContractAttribute;

With the configuration and the contract name you can find the endpoint:

var serviceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(configuration);
var endpoint = serviceModelSectionGroup.Client.Endpoints.OfType<ChannelEndpointElement>().First(e => e.Contract == contractAttribute.ConfigurationName);

All above code is making the complete client generation helper method:

public static T GetClient<T>() where T : IClientChannel
{
    var channelType = typeof(T);
    var contractType = channelType.GetInterfaces().First(i => i.Namespace == channelType.Namespace);
    var contractAttribute = contractType.GetCustomAttributes(typeof(ServiceContractAttribute), false).First() as ServiceContractAttribute;

    var configuration = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = "app.config" }, ConfigurationUserLevel.None);
    var serviceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(configuration);
    var endpoint = serviceModelSectionGroup.Client.Endpoints.OfType<ChannelEndpointElement>().First(e => e.Contract == contractAttribute.ConfigurationName);

    var channelFactory = new ConfigurationChannelFactory<T>(endpoint.Name, configuration, null);
    var client = channelFactory.CreateChannel();

    return client;
}

With this helper method you can write your ServiceAgent like that:

public static string GetData(int value)
{
    using (var client = ClientHelper.GetClient<IService1Channel>())
    {
        return client.GetData(value);
    }
}

With this code you have achieved abstraction over the WCF technology and you no longer need to inject XML into the application config file as long as you library app.config is in the application bin folder.

Posted in Configuration, WCF | Tagged , , , | 3 Comments

Namespace for Extension Methods

Recently We had a discussion about what namespace would you give to an extension method. Most answers to this question say you should put it in something like “Extensions” or “YourCompany.Technology.Extensions” (like here and here).

The problem with that is probably known to any developer. Since Visual Studio 97 where IntelliSense was added, you learn about the class functionality from the Intellisense list, but the extension method won’t appear in the list until you add the extension method namespace in your using list. Sure it happened to you when you wrote something like “myControl.Nodes.” and you were surprised to see there is no “Where” method. You must have asked yourself “Did they forget to implement IEnumerable<T> when .NET 2.0 was out?”, and after that you try to find the “OfType” method but you don’t find it either. A quick look will show you that the “using System.Linq;” statement is missing.

This namespace is not there because of possible two reasons:

  1. This file was created before .NET 3.5 where Microsoft added this namespace to any C# file template.
  2. You used the “Remove Unused Usings” feature when no IEnumerable<T> was in use in that file. (Use CodeMaid to do that. It has a white list for that, among many other great features). BTW, unused usings don’t have any effect on run time, only design and compile time. Look here and here.

Same goes for any extension method you write. If your colleague won’t remember the method you wrote (and probably you either won’t remember it after a while), he won’t have any clue about its existence. Even if you add this namespace to any C# template in your organization (Try to change the namespace after that!), it could be deleted.

So why won’t we go back to the days of the big Utils class?

I think we should name extension method namespace after the first parameter (the one with “this“) type namespace. For example, if you’re extending DataObjects.Person, give your extension method the DataObjects namespace. Most times when you use a class in your code you have its namespace inside a using statement (unless you got the instance from somewhere else).

namespace DataObjects
{
    public static class PersonExtensions
    {
        public static string GetFullName(this Person p)
        {
            return p.FirstName + " " + p.LastName;
        }
    }
}

Now what if you want to extend System.String. Someone might think that writing your extension method in System namespace is not allowed / won’t compile / not possible. Well, it is possible and won’t cause you any problem (I’m not an attorney, though).

Think of an extension method as a method you want to inject into the class being extended, so why not inject it into its namespace also?

MSDN namespace naming guidelines say:

You should make every effort to avoid name collisions with types in the core namespaces

As for extension methods, this is not going to cause any collision at all. The thing your should be aware of, is that if Microsoft will ever write a method with the same name and parameters in the class you’ve extended, all your method calls will now go to their code, ignoring your extension method without any compile error or warning. However, it doesn’t matter what is the namespace you have chosen, or which using statement you added.

You just need to find a class name and a method that won’t collide with the core types ever. “iPhoneGoogleFacebook” might be a good prefix. They are not going to buy all of them, don’t they?

Posted in Extension Method | Tagged , , , | 2 Comments

Entity Framework 5 and Enum support

Starting from EF 5 (currently RC, available as a NuGet package), you can use enums in your data model. In older versions, you always needed to use casting if you wanted to compare a property value against an enum value.
In the following code, Student.StatusID is an FK column with a constraint to the StatusID column in the StudentStatusType lookup table that has another column StatusName (nvarchar).

from s in db.Students
where s.StatusID == (int)StudentStatusEnum.Graduate
select s;

For the above query to work right, you had to hold an enum with values that follow the values in the StudentStatusType table, which was a little risky if for some reason you had to change your data in the StudentStatus table.

With EF 5, you can set a property to be of type enum. To do that, right click on the property in the model designer, and select “Convert to Enum”. After establishing your enum, you have to set both sides of the relation to be of type enum, since like in sql, both sides of a relation must be of the same type.

Now with this enum support you can write:

from s in db.Students
where s.StatusID == StudentStatusEnum.Graduate
select s;

Although your code will look nicer, this feature lacks the ability to generate the enum from the lookup table, so you still need to copy the lookup table to your code.

Fortunately, EF code generation can be customized with T4 templates, and you can start with a template from Visual Studio Gallery. The template that can be used to generate code exactly like the Visual Studio does is still not available for EF 5, but you can use the DbContext generator meanwhile.

The idea is to create the enum as above in the edmx designer, but to query the database in the T4 template.

The original code to generate enums in the template is:

<#=Accessibility.ForType(enumType)#> enum <#=code.Escape(enumType)#> : <#=code.Escape(enumType.UnderlyingType.ClrEquivalentType, fullyQualifySystemTypes: false)#>
{
<#
 foreach (EnumMember member in enumType.Members)
 {
#>
 <#=code.Escape(member)#> = <#=member.Value#>,
<#
 }

...

I replaced the foreach loop with:

IServiceProvider hostServiceProvider = (IServiceProvider)this.Host;
SettingsManager config = new SettingsManager(hostServiceProvider);

EntityContainer container = ItemCollection.GetItems<EntityContainer>().FirstOrDefault();
var connectionString = config.ConnectionStrings[container.Name].ConnectionString;

if (connectionString.Contains("|DataDirectory|"))
{
    DTE dte = (DTE)hostServiceProvider.GetService(typeof(DTE));
    Project project = dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject;
    connectionString = connectionString.Replace("|DataDirectory|",System.IO.Path.GetDirectoryName(project.FileName)+"\\App_Data");
}

var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = connectionString;
connectionString = builder["provider connection string"].ToString();

var primaryKeyProperty = code.GetItemsToGenerate<EntityType>(ItemCollection).SelectMany(e => e.KeyMembers).FirstOrDefault(km => km.TypeUsage.EdmType == enumType);
var tableName = primaryKeyProperty.DeclaringType.Name;

using (var con = new SqlConnection(connectionString))
{
    var cmd = new SqlCommand("Select * From " + tableName, con);
    con.Open();
    using (var reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
#>
    <#=reader[1]#> = <#=reader[0]#>,
<#
        }
    }
}

Explanation:

First we need to find the project config file and load it. This is not so simple since the T4 template code is not running in the context of your project and regular config code won’t work here. For this I used the SettingsManager class available here. Note: Although this code works you can’t debug it in Visual Studio 2012 because it fails iterating ProjectItems collection.


IServiceProvider hostServiceProvider = (IServiceProvider)this.Host;
SettingsManager config = new SettingsManager(hostServiceProvider);

Now you need to get the connection string. The connection string key can be found with the container name. The container is initialized in the template used to generate the DbContext code and you can copy it from there.

EntityContainer container = ItemCollection.GetItems<EntityContainer>().FirstOrDefault();
var connectionString = config.ConnectionStrings[container.Name].ConnectionString;

In case your database is in your app_data folder, you need to resolve the “|DataDirectory|” macro by yourself since this macro will lead you inside Visual Studio installation folders.

if (connectionString.Contains("|DataDirectory|"))
{
    DTE dte = (DTE)hostServiceProvider.GetService(typeof(DTE));
    Project project = dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject;
    connectionString = connectionString.Replace("|DataDirectory|",System.IO.Path.GetDirectoryName(project.FileName)+"\\App_Data");
}

Now before using the connection string, you need to extract just the connection string itself without the metadata info since SqlConnection doesn’t like it.

var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = connectionString;
connectionString = builder["provider connection string"].ToString();

Now that we got the connection string, we are ready to “select * from”, but we still need to know the table name. So we need to find the entity type that represents the lookup table. Because we set earlier its primary key to be of the enum type, it’s very easy:

var primaryKeyProperty = code.GetItemsToGenerate<EntityType>(ItemCollection).SelectMany(e => e.KeyMembers).FirstOrDefault(km => km.TypeUsage.EdmType == enumType);
var tableName = primaryKeyProperty.DeclaringType.Name;

The entity type name won’t always be identical to the table name. There is no built-in way to get that, but there is a tricky way. I just assumed that the entity name is the table name. If you want you can use the trick.

It’s time to get the data!!!

using (var con = new SqlConnection(connectionString))
{
 var cmd = new SqlCommand("Select * From " + tableName, con);
 con.Open();
 using (var reader = cmd.ExecuteReader())
 {
 while (reader.Read())
 {
#>
 <#=reader[1]#> = <#=reader[0]#>,
<#
 }
 }
}

I assumed the first column is the primary key and the second is the name, and I didn’t deal with whitespaces and capitalization. You can improve that code like in here.

Well this was quite an ugly code. I hope MS will add a capability to set the lookup table name when you create the enum type.

Posted in Entity Framework | Tagged , , , | 1 Comment