WCF (Windows Communication Foundation) is a .NET framework for building service-oriented applications that send data between endpoints — including SOAP web services. Deploying your computational logic as a WCF SOAP service lets multiple Dynamo users share a single powerful back-end: the calculation runs on the server and only the result is returned to the graph.
Creating the WCF Service
Create a new WCF Service Application project. Define a serializable data model with [DataContract] (Dynamo's own Point type is not serializable, so wrap it):
// Serializable point for the SOAP service — Dynamo's Point is not serializable
[DataContract]
public class SvcPoint
{
[DataMember] public double X { get; set; }
[DataMember] public double Y { get; set; }
[DataMember] public double Z { get; set; }
public SvcPoint(double x, double y, double z)
{
X = x; Y = y; Z = z;
}
}The service contract declares the operations:
// Service contract — defines the operations the service exposes
[ServiceContract]
public interface IService
{
[OperationContract]
double Sum(double value1, double value2);
[OperationContract]
SvcPoint Add(SvcPoint pt1, SvcPoint pt2);
}// Service implementation
public class Service : IService
{
public double Sum(double value1, double value2)
=> value1 + value2;
public SvcPoint Add(SvcPoint pt1, SvcPoint pt2)
=> new SvcPoint(pt1.X + pt2.X, pt1.Y + pt2.Y, pt1.Z + pt2.Z);
}Testing the Service
Press F5 to start the service host, then add a Service Reference from a console project pointing at the running URL. You can then call the operations through the generated proxy:
// Console client — add Service Reference pointing at the running service URL
class Program
{
static void Main(string[] args)
{
IService service = new ServiceClient();
Console.WriteLine(service.Sum(2, 3)); // 5
}
}Consuming the Service in Dynamo
Dynamo cannot use the generated ServiceClient proxy directly because it cannot resolve the endpoint configuration in its hosting context. Instead, build the channel programmatically with ChannelFactory<T>. Keep this BLL class in a separate project that references the service, and reference that project (not the service directly) from your Dynamo package — otherwise the service's interface methods will appear as unwanted nodes in Dynamo's UI:
// BLL layer — creates the WCF channel programmatically (required for Dynamo)
// Dynamo cannot use the generated ServiceClient proxy class directly because
// the endpoint configuration cannot be resolved in the host application context.
public static class ServiceMethods
{
private static readonly object _lock = new object();
private static ChannelFactory<IService> _channelFactory;
private static ChannelFactory<IService> SvcChannelFactory
{
get
{
lock (_lock)
{
if (_channelFactory == null)
{
var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress("http://localhost:59024/Service.svc");
_channelFactory = new ChannelFactory<IService>(binding, endpoint);
}
}
return _channelFactory;
}
}
private static IService _serviceRef;
private static IService ServiceRef
=> _serviceRef ?? (_serviceRef = SvcChannelFactory.CreateChannel());
public static double BllSum(double v1, double v2)
{
double result = ServiceRef.Sum(v1, v2);
((ICommunicationObject)ServiceRef).Close();
return result;
}
public static Point BllAddPoints(Point p1, Point p2)
{
SvcPoint sp1 = new SvcPoint { X = p1.X, Y = p1.Y, Z = p1.Z };
SvcPoint sp2 = new SvcPoint { X = p2.X, Y = p2.Y, Z = p2.Z };
SvcPoint sum = ServiceRef.Add(sp1, sp2);
((ICommunicationObject)ServiceRef).Close();
return Point.ByCoordinates(sum.X, sum.Y, sum.Z);
}
}Dynamo Nodes
Expose the BLL methods as ZeroTouch static methods in a separate package project:
// Dynamo node layer — wraps BLL methods in ZeroTouch static methods
public static class ServicePkg
{
[MultiReturn(new[] { "Result" })]
public static Dictionary<string, double> SumFromService(double value1, double value2)
{
return new Dictionary<string, double>
{
{ "Result", BLL.ServiceMethods.BllSum(value1, value2) }
};
}
[MultiReturn(new[] { "Result" })]
public static Dictionary<string, Point> AddPoints(Point p1, Point p2)
{
return new Dictionary<string, Point>
{
{ "Result", BLL.ServiceMethods.BllAddPoints(p1, p2) }
};
}
}