Configuring Peer Channel: With/Without App.config

So now that we know what the NetPeerTcpBinding is how you can end up using Peer Channel in your standard WCF application, let's take a look at how to configure peer channel. We follow the standard WCF (.NET really) pattern of allowing configuration through an App.config file for your application or imperatively within the code itself. Which way you choose to go really depends on your needs - if you expect your endpoints/configuration to change a lot and want that aspect flexible etc(eg you use a customResolver for discovery and expect to move it around etc) you'd want to minimize code changes and prefer to change these settings in your config file directly. On the other hand, if you dont really expect to modify your source code that often and dont really want an App.config file, you can opt to just configure everything in code itself. Peer Channel (NetPeerTcpbinding) supports both, to provide a programming model consistent with the rest of WCF.

Using App.config:

The following example attempts to configure a Peer Channel endpoint, with endpointAddress = "net.p2p://ChatMesh/chat"; other endpoint information also is added to the endpoint section of the config file, including fully qualified contract type that is associated with the endpoint, name of config file section that configures the specific binding used, and of course also the type of the binding being used.

All binding configuration (in our case, peer channel (NetPeerTcpbinding)-specific ) settings are in the configuration section corresponding to the one specified in the endpoint section above. (Note: Just in case you are wondering, Visual Studio 8 comes preconfigured with xml information for ServiceModel so intellisense would work and you dont really have to know before hand all the various properties etc.. a quick way to confirm is to check your schema file from the VS install here: C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas\DotNetConfig.xsd and search for serviceModel definitions..)

In the bindings section of serviceModel configuration, we specify settings for NetPeerTcpBinding as i show below.

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<system.serviceModel>

<client>

<!-- chat instance participating in the mesh -->

<endpoint name="PeerEndpoint"

address="net.p2p://ChatMesh/chat"

binding="netPeerTcpBinding"

bindingConfiguration="PeerBinding"

contract="Microsoft.ServiceModel.Samples.IChat">

</endpoint>

</client>

<bindings>

<netPeerTcpBinding>

<binding name="PeerBinding" port="0">

<resolver mode="Auto"/>

<security mode="None" />

        </binding>

      </netPeerTcpBinding>

    </bindings>

 

  </system.serviceModel>

</configuration>

It all comes together when in the code, you specify the endpoint name from the config file to the CreateChannel constructor, like so:

// Construct InstanceContext to handle messages on callback interface.

// An instance of ChatApp is created and passed to the InstanceContext.

InstanceContext site =

new InstanceContext(new ChatApp());

// Create the participant with the given endpoint configuration. Each participant opens a duplex channel to the mesh. Participant is an instance of the chat application that has opened a channel to the mesh

ChannelFactory<IChatChannel> factory = new DuplexChannelFactory<IChatChannel>(site, "PeerEndpoint");

Note: Notice that the above example assumes that you are creating a duplexChannel for your application and the client itself is the sender/receiver. You can certainly choose to configure your application such that instead of a duplex channel, you have 1 separate sender and multiple clients (receivers). Check out the Default sample for an idea on how to configure the service/client separately in such a case.

 

Imperative configuration (Via code and not through the App.config file):

 

The same configuration above can be achieved through setting the properties on NetPeerTcpbinding programmatically. So programmatically, the settings above would look as under:

  

InstanceContext site = new InstanceContext(new ChatApp());

NetPeerTcpBinding peerBinding = new NetPeerTcpBinding();

peerBinding.Security.Mode = SecurityMode.None;

ChannelFactory<IChatChannel> factory = new DuplexChannelFactory<IChatChannel>(site, peerBinding);    

 

That's all there is to it :)- (unless of course you would like to use the default custom resolver, in which case check out the scenario sample on msdn on what properties to configure). Hopefully this will help answer some common questions around configuration and also how to convert your app from using App.config to pure code.

 

As always, feedback welcome and appreciated :)..

 

-shalini.

Comments

  • Anonymous
    March 19, 2008
    Thank you so much for your information.  I would like to ask that the App.config NEVER be used in examples.   Here's why: If you taught golf you wouldn't teach people how to hit a golf ball by using a baseball bat.   Using that same logic you shouldn't teach people how to code to a new technology by using examples you would never use in production code.  For instance have you EVER seen the prefix "My" used in production code? Using the App.config file obfuscates the creation of WCF objects and makes learning how to do things in WCF on your own entirely too difficult.

  • Anonymous
    March 19, 2008
    Argh!  And here's a perfect example.  I just tried to implement your App.config file free version while using a custom resolver service.  Your example assumes we are using Vista so doesn't set the resolver so when I try to run the Chat instance (from the WCF examples) it tells me there is no resolver: "Resolver must be specified. The default resolver (PNRP) is not available. " I think this is the kind of problem people are running into as they try to learn WCF and is why people are saying how difficult learning WCF is. Anyway I do appreciate you taking your time to put up this info.

  • Anonymous
    March 19, 2008
    Hi there! Thanks for the colorful feedback :)

  • Believe it or not, but many of our industry partners and customers do like the concept of the config file..But actually I admit and do realize that it's really easier understanding concepts working with code- hence hte blog post :).
  • I have used "my" in one of hte variables above as a naming convenience- it is not used at all to teach any WCF/Peer Channel-related concept to readers and I certainly hope that readers will not copy-paste this code and not even fix variable names in production code! Hopefully the idea that I am trying to get through to readers is conveyed properly; but yes, that's not excuse to use sloppily named variables so I'll fix it up :) :).
  • If you have read the sample documentation for the custom resolver/Chat sample, you'll notice that the samples actually configure the binding to indicate some custom resolver related properties - you need those in case you are running on non-Vista platforms and do not have PNRP installed (Note: the blog posts are not meant to be a substitute for the msdn docs or samples- it compliments those docs - which by the way we are cleaning up currently and enhancing with all this good stuff :)). Configuring the binding to enable non-default (which means non-PNRP in the case of the resolver) scenarios are covered in the samples, I don't mention it specifically in this example.
  • I am going to add mroe examples on scenarios related to the custom resolver though, including how to secure communication between the resolver client and service etc and I'll make sure i demonstrate both the config and imperative versions :). Again, keep the feedback coming and thanks for using Peer Channnel. -shalini.
  • Anonymous
    March 20, 2008
    Thanks for your reply Shalini. Didn't mean to point you out specifically on the "My" prefix.  A lot of Microsoft examples use it and I've never understood why. I'm assuming it's something someone did a million years ago and it just kind of got institutionalized into Microsoft example writing culture. "...you'll notice that the samples actually configure the binding to indicate some custom resolver related properties..." Yeah, that's my problem, I'm trying to figure out how to do that programmatically.  I'm basically trying to figure out how to convert the custom resolver/chat sample from using config files to setting everything via code. Again, thank you for all your efforts getting this information out there and for your reply.

  • Anonymous
    March 20, 2008
    Hmm, if you go through another blog post under the Discovery tag, I show you how to extend the default custom resolver service. Towards the end, I actually show you how to configure the Client throught hte NetPeerTcpbinding (imperatively)..so you would do something like this: (really the properties in the config file and the ones we expose through code have almost a 1:1 mapping) To let Peer Channel know what the client configuration should look like (what do you know - I have a whole new blog post in this comment :) :): <snip> NetPeerTcpBinding binding = new NetPeerTcpBinding(); customResolverEpr = "net.tcp://" + customResolverHostName + ":" + CustomResolverServicePort.ToString() + "/DefaultResolverService"; binding.Resolver.Mode = PeerResolverMode.Custom; binding.Resolver.Custom.Address = new EndpointAddress(customResolverEpr); binding.Resolver.Custom.Binding = new NetTcpBinding(SecurityMode.None); </snip> To configure/start the default resolver service itself: (make sure you specify the same transport binding (eg NetTcpBinding here) & listening endpoint both places.. <snip> System.ServiceModel.PeerResolvers.CustomPeerResolverService crs = new System.ServiceModel.PeerResolvers.CustomPeerResolverService();            crs.CleanupInterval = TimeSpan.FromMinutes(cleanupMins);            crs.RefreshInterval = TimeSpan.FromMinutes(refreshInterval);            crs.ControlShape = controlShape;            Uri baseAddress = new Uri(customResolverEpr);            ServiceHost customResolver = new ServiceHost(crs);            customResolver.AddServiceEndpoint(typeof(System.ServiceModel.PeerResolvers.IPeerResolverContract), binding, baseAddress);            //Enabling propagation of service side errors to the client side            ServiceDebugBehavior sdb = customResolver.Description.Behaviors.Find<ServiceDebugBehavior>();            if (sdb != null)            {                sdb.IncludeExceptionDetailInFaults = true;            }            crs.Open();            customResolver.Open(); </snip>

  • Anonymous
    March 20, 2008
    Thanks.  I actually just figured it out and was coming here to post my code.  I was actually doing everything right except I forgot to set the security on the server to none.  Doh!            InstanceContext instanceContext = new InstanceContext(new ChatApp(member));            NetPeerTcpBinding chatBinding = new NetPeerTcpBinding(); Uri baseAddress = new Uri("net.tcp://localhost/servicemodelsamples/peerResolverService");            chatBinding.Security.Mode = SecurityMode.None;            chatBinding.Resolver.Mode = PeerResolverMode.Custom;            chatBinding.Resolver.Custom.Address = new EndpointAddress(baseAddress);            chatBinding.Resolver.Custom.Binding = new NetTcpBinding(SecurityMode.None);            DuplexChannelFactory<IChatChannel> factory = new DuplexChannelFactory<IChatChannel>(instanceContext, chatBinding, "net.p2p://chatMesh/ServiceModelSamples/Chat");            IChatChannel participant = factory.CreateChannel();

  • Anonymous
    March 20, 2008
    Cool!!

  • Anonymous
    March 20, 2008
    The comment has been removed

  • Anonymous
    March 20, 2008
    P.S. I keep forgetting to clarify my comments on the config file thing. I use the App.config file too via the Properties.Settings.Default deal and that's where I would set the peer channel configurations.  I was just saying I wouldn't "hardcode" into those files.  I would provide a UI to change and save those settings. Our user base, while very smart in their own fields, are not the most computer literate people. Anyway, thanks again for all your help.

  • Anonymous
    December 08, 2009
    Well, since these posts are old im starting to assume the WCF p2p is not alive and well. I am having the hardest time finding direct answers to simple questions.  Here are a few that maybe you could help me with. 1.) Can you use p2p over the Internet w/o using PNRP?  ie: custom resolver - all samples are net.tcp intranet (not the most useful p2p) 2.) Is MS continuing the development.  Is this technology worth looking in to?  I do a lot of WCF dev but really would love to have a p2p app that works over the Internet (w/o requiring clients to configure thier system - could you imagine if Skype or MSN required this) Thanks in advance.  I was so excited about this and im hoping to get that excitement back. 3.)  

  • Anonymous
    December 09, 2009
    The comment has been removed

  • Anonymous
    February 25, 2010
    can we create multiple meshes n multiple channels  at runtime?can 1 user participate in 2 different meshes at a same time?plzzz give some response..im waiting... Regards Mumtaz

  • Anonymous
    April 28, 2011
    I also have the same doubt. I want to communicate between multiple meshes at runtime. And i also want to create multiple mesh at runtime?? how to do both these thing. Please help me in detail. thank you....