24

I'm writing a client to a WCF service. This is a single app in a larger system that includes modules written in C#, C++, VB, and Java. All of the apps share common configuration and logging mechanisms, regardless of what language they were written in.

I'd like to figure out how to build the client application so that it will run without an app.config. Why? Because most of what is in the app.config is boilerplate that the sysadmins shouldn't be allowed to change, and what settings the sysadmins should be allowed to change should be in the system-wide configuration, and not in an app.config file sitting in the bin directory.

Case in point - the client's app.config currently looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="WSHttpBinding_ICourierService">
          <security defaultAlgorithmSuite="Default" authenticationMode="SecureConversation"
            ...
          </security>
          <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
            messageVersion="Default" writeEncoding="utf-8">
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
              maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          </textMessageEncoding>
          <httpTransport manualAddressing="false"
            ...
            useDefaultWebProxy="true" />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:57102/MyService.svc"
        ...
        >
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

It's a bunch of opaque boilerplate that the sysadmins shouldn't have to deal with. Most of it was inserted by Visual Studio. I've made one change in the file - I increased the max size in <readerQuotas/>. But that's a change that I don't want the sysadmins to mess with. And there's nothing else in the file I want the sysadmins to mess with except for <endpoint address=""/>.

And I'm pulling the endpoint address from the system-wide configuration, and setting it in code. There's nothing in this file that should be user-editable.

So, how do I configure things so that I don't need to have it present?

Can I embed it as a resource in the assembly, and hook into the app.config load process, the way I do with required DLLs?

Is the only choice to create code to configure things, the way I'm using code to set the endpoint address? Create the necessary bindings, etc., in code? How, then, do I know what code to write, given these chunks of opaque XML?

Johann Blais
  • 9,389
  • 6
  • 45
  • 65
Jeff Dege
  • 11,190
  • 22
  • 96
  • 165
  • There was me thinking SysAdmins should be able to change things like WCF service setttings, silly me. – ChrisBint Oct 07 '11 at 14:46
  • 1
    What kind of setting? URL? Certainly. Bindings? Why? I'm building a client to talk to a service running on IIS. There's no need to allow the sysadmins to change the binding to something other than HTTP. – Jeff Dege Oct 07 '11 at 14:49
  • How about hostnames and anything to do with actually talking to the service. – ChrisBint Oct 07 '11 at 14:51
  • 4
    If there is a setting we want the SysAdmins to be able to configure, we'll include it in our system-wide configuration mechanism, with the specific choices available listed and the consequences of each choice documented. We won't embed it in a couple of pages of opaque and undocumented XML. – Jeff Dege Oct 07 '11 at 15:04

2 Answers2

42

You can use the following code to creating the bindings which is what the config is doing. I am not sure whether that will let you remove the file altogether but the application won't use the config if this is the case. Put your own values in the timeouts, etc.

    var binding = new WSHttpBinding();
    binding.SendTimeout = new TimeSpan(0, 0, 0, 0, 100000);
    binding.OpenTimeout = new TimeSpan(0, 0, 0, 0, 100000);
    binding.MaxReceivedMessageSize = 10000;
    binding.ReaderQuotas.MaxStringContentLength = 10000;
    binding.ReaderQuotas.MaxDepth = 10000;
    binding.ReaderQuotas.MaxArrayLength = 10000;
    var endpoint = new EndpointAddress("http://localhost:57102/MyService.svc");
    var myClient = new WebServiceclient(binding, endpoint);
Graymatter
  • 6,529
  • 2
  • 30
  • 50
  • 1
    I'm trying that, but I'm getting an error: "Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'" – Jeff Dege Oct 07 '11 at 15:01
  • 4
    Try changing the binding create line to: var binding = new BasicHttpBinding(); – Graymatter Oct 07 '11 at 15:05
  • where would you put this code exactly, global.asax? unit test? – PositiveGuy Oct 21 '13 at 02:39
  • 1
    This answer is perfect. I am writing an add-in so I cannot edit the app.config file of the parent application. It appears that there is two solutions for this problem and you have explained how each solution works. Perfect. – LochnessLAM Dec 16 '15 at 05:57
  • I'm getting the "The content type text/html; charset=utf-8 of the response message does not match the content type of the binding..." error. Using "BasicHttpBinding" didn't help in my case. – Daniel Ryan Apr 05 '16 at 00:01
  • WebServiceClient doesn't exist in C#... in VS 2013 I can't find it – Piero Alberto Apr 21 '16 at 12:58
  • have I to add some reference? Which one? – Piero Alberto Apr 21 '16 at 13:08
  • @PieroAlberto You need to import the web service that you would like to connect to. – Graymatter Apr 21 '16 at 21:59
-1

WCF settings can be set in your code, with no need for an external configuration file. Addresses, bindings, endpoints, security, etc. can all be configured in code. This is the best way to be consistent across all of your WCF services and not allow users to tamper with these settings.

I suggest you expose the address (host name and port number) to users and allow them to configure this somehow because addresses are specific to where your WCF services are hosted.

Bernard
  • 7,908
  • 2
  • 36
  • 33
  • 3
    That they can be set in my code does not mean that it's easy to figure out how to set them in my code. – Jeff Dege Oct 07 '11 at 14:54
  • You have a few options to figure out how to set WCF settings in your code: (1) Browse through related MSDN pages. (2) Get a good book on WCF, such as _Programming WCF Services_. (3) See [this](http://stackoverflow.com/questions/54579/wcf-configuration-without-a-config-file) question for some guidance. – Bernard Oct 07 '11 at 15:07