Brothers In Code

...a serious misallocation of .net resources

Moving a "Simplified Configuration" WCF Service From IIS Host to a Self Host

WCF configuration files can get pretty big pretty fast, so the new Simplified Configuration in .Net 4.0 definately interested me.   However there are a couple of errors that make perfect sense but might catch you off guard if you're not reading the fine print.

Error: Service has zero application (non-infrastructure) endpoints

The simple configuration is supposed to create one end point for each base address / contract combination.  So what happend here?  This can be explained by one simple line in the above linked document:

Services hosted under Internet Information Services (IIS) or Windows Process Activation Service (WAS) use the virtual directory as their base address.

Services NOT hosted in one of these environments assume nothing which is a good thing.  It wouldn't make a lot of sense if some console.exe program just randomly grabbed a port to use.  So you are required to specify a base address:


    <services>
      <service name="MyApp.MyService">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:51234"/>
          </baseAddresses>
        </host>
      </service>
    </services>

Error: The HttpGetEnabled property of ServiceMetadataBehavior is set to true and the HttpGetUrl property is a relative address, but there is no http base address.

This is due to the following line:


  <serviceMetadata httpGetEnabled="true"/>

You're basically saying that you want the metadata to be exposed via http, but you've provided no http endpoint.  One fix is to set it to false.  Another is to add a second base address:


          <baseAddresses>
            <add baseAddress="net.tcp://localhost:51234"/>
            <add baseAddress="http://localhost:50080"/>
          </baseAddresses>


No rocket science here, but I wanted to post this because the answers I found weren't very specific.
 

Simple Custom Configuration

A lot of these posts are merely for my own quick reference.  The upside of that is that you'll get a taste for the way I actually do something rather than just a rehash of a reference page.

For simpler projects I just create a class with some static properties that just pull from AppConfig variables.  At least from there I have intellisense to help me remember all of my configuration variables.  But the appSettings section app.config or web.config can get messy pretty fast so creating a custom section isn't that much work to clean it up.

First I'll create a ConfigurationSections folder (which creates an automatic namespace) and an AppConfig class:

 

The GeneralConfigurationSectionClass looks like this:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;

namespace MyCust.MyProj.ConfigurationSections
{
  public class GeneralConfigurationSection : ConfigurationSection
  {
    [ConfigurationProperty("TestKey")]
    public String TestKey
    {
      get { return (String)this["TestKey"]; }
      set { this["TestKey"] = value; }
    }

    [ConfigurationProperty("ConnectionString")]
    public String ConnectionString
    {
      get { return (String)this["ConnectionString"]; }
      set { this["ConnectionString"] = value; }
    }
  }
}

 

Then I'll create a property that pulls the config data and returns this class in the AppConfig.cs

  public class AppConfig
  {
    public static GeneralConfigurationSection General
    {
      get
      {
        return (GeneralConfigurationSection)ConfigurationManager.GetSection("MyCust.MyProj/General");
      }
    }

  }

And last add the new section to the app/web.config.  First add the section group:

<configSections>
  <sectionGroup name="MyCust.MyProj.WebServices">
    <section name="General" type="MyCust.MyProj.WebServices.ConfigurationSections.GeneralConfigurationSection, MyCust.MyProj.WebServices" allowLocation="true" allowDefinition="Everywhere"/>
  </sectionGroup>
</configSections>

And then add the section itself into the configuration element:

<MyCust.MyProj.WebServices>
  <General
    TestKey="32AAAC4-8DB2-4059-852A-73BBBBBB9698"
    ConnectionString="Data Source=SqlServer;User Id=sa_app;Password=pwd;"
  />
</MyCust.MyProj.WebServices>

Usage is then a nice and clean line:

AppConfig.General.ConnectionString

B