Run WCF ServiceHost with multiple contracts - wcf

Running a ServiceHost with a single contract is working fine like this:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.Open();
Now I'd like to add a second (3rd, 4th, ...) contract. My first guess would be to just add more endpoints like this:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
But of course this does not work, since in the creation of ServiceHost I can either pass MyService1 as parameter or MyService2 - so I can add a lot of endpoints to my service, but all have to use the same contract, since I only can provide one implementation?
I got the feeling I'm missing the point, here. Sure there must be some way to provide an implementation for every endpoint-contract I add, or not?

You need to implement both services (interfaces) in the same class.
servicehost = new ServiceHost(typeof(WcfEntryPoint));
servicehost.Open();
public class WcfEntryPoint : IMyService1, IMyService2
{
#region IMyService1
#endregion
#region IMyService2
#endregion
}
FYI: I frequently use partial classes to make my host class code easier to read:
// WcfEntryPoint.IMyService1.cs
public partial class WcfEntryPoint : IMyService1
{
// IMyService1 methods
}
// WcfEntryPoint.IMyService2.cs
public partial class WcfEntryPoint : IMyService2
{
// IMyService2 methods
}

I'm currently faced with the same problem, and have decided to go with the implementation below. I'm not sure if there are any performance issues with having this many service contracts, but in my final implementation I will probably have about 10 - 15 service contracts, thus about 10-15 ServiceHosts.
I am hosting all my WCF services inside a single Windows Service.
private void PublishWcfEndpoints()
{
var mappings = new Dictionary<Type, Type>
{
{typeof (IAuthenticationService), typeof (AuthenticationService)},
{typeof(IUserService), typeof(UserService)},
{typeof(IClientService), typeof(ClientService)}
};
foreach (var type in mappings)
{
Type contractType = type.Key;
Type implementationType = type.Value;
ServiceHost serviceHost = new ServiceHost(implementationType);
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(contractType, ServiceHelper.GetDefaultBinding(),
Properties.Settings.Default.ServiceUrl + "/" + contractType.Name);
endpoint.Behaviors.Add(new ServerSessionBehavior());
ServiceDebugBehavior serviceDebugBehaviour =
serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
serviceDebugBehaviour.IncludeExceptionDetailInFaults = true;
log.DebugFormat("Published Service endpoint: {0}", Properties.Settings.Default.ServiceUrl);
serviceHost.Open();
serviceHosts.Add(serviceHost);
}
}
Feel free to comment on this type of set up, and if there are any issues with it, especially performance-related.

This answer is a further response to the comment in the accepted answer from chilltemp.
Sam, You really should determine why you need 10-50 contracts and try to find another solution. I looked over Juval Lowy's WCF Coding Standards (found on http://www.idesign.net/) and found the following references:
3 Service Contracts
[...]
Avoid contracts with one member.
Strive to have three to five members per service contract.
Do not have more than twenty members per service contract. Twelve is probably the practical limit.
He doesn't mention a limit on contract implementations (that I can find) but I can't imagine him viewing 50 contracts on a service as anything resembling a best practice. One solution I have found that works well is to use member sharing for similar functions.
For instance, if you are using the WCF service to perform mathematics on 2 values you might have 4 members on the service side: Add(x,y), Subtract(x,y), Multiply(x,y), Divide(x,y). If you combine these into a more generic member and use an object to pass the needed data you can easily reduce your member count and increase scalability. Example: PeformCalculation(obj) where obj has x, y, and action (add, subtract, multiply, divide) properties.
Hope this helps.

I found another solution to for this issue by using a the RoutingService class. Each contract must still be hosted in it's own ServiceHost, but there can be a RoutingService sitting on top of all of them - and presenting them over an unified "endpoint". I've also written a codeproject article about it. The example code is also available on Bitbucket.

chili's answer will work if you are ok with the contracts being shared by the service. If you want them to be separated try this:
host1 = new ServiceHost(typeof(MyService1));
host2 = new ServiceHost(typeof(MyService2));
host1.Open();
host2.Open();
public class MyService1 : IMyService1
{
#region IMyService1
#endregion
}
public class MyService2 : IMyService2
{
#region IMyService2
#endregion
}
Edit: As Matt posted, this would require multiple endpoints for each service/contract

No-one documented enpoints. Whe used more than one (as a group, from common url, for example http) must use the same binding instance (not more), i.e.
Your sample:
servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
should be only one new Binding(), I tested over http.
servicehost = new ServiceHost(typeof(MyService1));
BasicHttpBinding binding = new BasicHttpBinding();
servicehost.AddServiceEndpoint(typeof(IMyService1),binding , "http://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), binding, "http://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();
I agree totally with partial class implementing few contracts in few files.

What about splitting it up with a base address and multiple services/contracts below it?
I am not behind a developmachine right now but something like:
http://myserver/myservices/serviceA
http://myserver/myservices/serviceB
http://myserver/myservices/serviceC
Each service implementing its own ServiceContract.
You can change
public class WcfEntryPoint : IMyService1, IMyService2
to
public partial class WcfEntryPoint : IMyService1
public partial class WcfEntryPoint : IMyService2
Example

Did I miss something, or is the simplest solution not mentioned here? The simplest solution is this: Don't use multiple interfaces for the Web Service.
But that doesn't mean you can still have your interfaces separated. This is why we have Interface inheritance.
[ServiceContract]
public interface IMetaSomeObjectService : ISomeObjectService1, ISomeObjectService2
{
}
The Meta interface inherits from all the other interfaces.
[ServiceContract]
public interface ISomeOjectService1
{
[OperationContract]
List<SomeOject> GetSomeObjects();
}
[ServiceContract]
public interface ISomeOjectService2
{
[OperationContract]
void DoSomethingElse();
}
Then the service just has the Meta interface.
public class SomeObjectService : IMetaSomeObjectService
{
public List<SomeOject> GetSomeObjects()
{
// code here
}
public void DoSomethingElse()
{
// code here
}
}

Related

trying to expose my Service layer as WCF

I have my service layer, entities and DTOS in a separeted assembly called CCL.Data
The problem:
All My application is referencing the service layer directly using interfaces and IoC.
For example, I have an interface in my CCL.Data assembly called ICustomerService it depends on ICustomerRepository that depends on MyContext. All my application is referencing ICustomerService to call its methods....... so far no problem.
So I created a WCF Project.... referencing CCL.Data in this project....
I create a new Service, but int this case below, I would need to change all points in my application that call ICustomerService to WCFCustomerServiceClient, does exists a better way without cause a big impact in my project?
[ServiceContract]
public interface IWCFCustomerService
{
[OperationContract]
CustomerDTO GetCustomerById(int id);
}
public class WCFCustomerService : IWCFCustomerService
{
ICustomerService _customerService;
public WCFCustomerService()
{
MyContext context = new MyContext();
ICustomerRepository customerRep = new CustomerRepository(context);
_customerService = new CustomerService(customerRep);
}
public CustomerDTO GetCustomerById(int id)
{
return _customerService.GetCustomerById(id);
}
}
Tks,
William
Do you need to redefine IWCFCustomerService in place of ICustomerService? Is it not possible just to add ServiceContract attributes to your original ICustomerService interface (they will just get ignored by non WCF code)? (Its true that this does give you a dependancy on ServiceModel - but I cant see a way out of that).
Note also that if you use a ServiceRefernce to generate proxy code then the code generated will include a your service interface in different namespace for use clientside. Its worth noting that your not abliged to use that version of the interface (which could be annoying if you have a proxy and not proxy implimentation) but can still use the org interface definition either from a dll or compiled into your client.

WCF Versioning : Update Attribute Namespaces and Support Previous Namespaces

I have three WCF services (.svc) which generate .wsdl references for SOAP messages.
Given that part of the namespace needs to change for all ServiceContract, OperationContract, DataContract attributes, for example
[DataContract(Namespace = "http://old.com.au/types/")]
to
[DataContract(Namespace = "http://new.com.au/types/")]
How is it that I can still support clients which have the old service reference (without them needing to update, because maybe they wont have time to update immediately) and allow clients getting a new service reference to get the new namespace? None of the service is changing, just the namespace.
So far I have read a lot of stuff but the following article suggests it is possible to change the service type from the ServiceHostFactory : http://blog.ranamauro.com/2008/07/hosting-wcf-service-on-iis-site-with_25.html
Which would mean creating two of every contract (putting as much of the implementation as possible in one place), and figuring out at runtime which serivce type to use. This would create some mess in my scenario.
Q. Is there an alternative, nice way to accomplish this or is it expected that this kind of thing should not be done and the client made to update to the new namespace.
(If there is a namespace mismatch from the client I get the error : The message with Action "..." cannot be processed at the receiver, due to a ContractFilter mismatch)
IMO, you need to host old services for your previous clients at (preferably) old end points and have new services at new end points. You can take out old services when all your old clients migrate to newer version.
Perhaps, you can use inheritance to reduce your efforts, for example
[DataContract(OldNameSpace)]
ClassA {
...
}
[DataContract(NewNameSpace)]
ClassB : ClassA {
}
Similarly, create new service contract from inheriting from new one. Service implementation need not change expect it needs to implement new contract. Now you have to configure two end point - one for old contract and another for new contract.
Edit: Put sample interfaces and implementation
Let's say your old contract was something like
public interface IOldContract
{
ClassA GetFoo();
void DoBar(ClassA a);
}
Now you can choose the new contract either as
public interface INewContract
{
ClassB GetFoo();
void DoBar(ClassB b);
ClassB GetMix(ClassB a);
}
or as
public interface INewContract2 : IOldContract
{
ClassB GetFoo2();
void DoBar2(ClassB b);
ClassB GetMix2(ClassB b);
}
I tend to go with later variation (as new contract remains compatible with old one). But in your case, you can choose former as you will be anyway exposing two endpoints.
Now you need modify service implementation as follows:
public class ServiceImplementation : INewContract2
{
#region INewContract2 Members
public ClassB GetFoo2()
{
// Your old implementation goes here
}
public void DoBar2(ClassB b)
{
DoBar(b);
}
public ClassB GetMix2(ClassB b)
{
return GetMixHelper(b);
}
#endregion
#region IOldContract Members
public ClassA GetFoo()
{
return GetFoo2();
}
public void DoBar(ClassA a)
{
// You old implementation goes here
}
public ClassA GetMix(ClassA a)
{
return GetMixHelper(a);
}
#endregion
private ClassB GetMixHelper(ClassA a)
{
// Your old implementation goes here
}
}
I hope that you get the idea. Even here also you have multiple choices of code organization. You can have two skeleton service implementation classes - one for old contract and another for new contract. Both will delegate actually functionality to a helper class (which is your current implementation).

WCF client proxy exception - "Type cannot be added to list of known types"

I am having problems creating WCF client proxy for service code like in this example:
// data classes
[KnownType(typeof(ClassA))]
[KnownType(typeof(ClassB))]
public abstract class BaseClass : Dictionary<string, ITest>
{
}
public class ClassA : BaseClass
{
}
public class ClassB : BaseClass
{
}
public interface ITest
{
}
// service
[ServiceContract]
public interface IService1
{
[OperationContract]
BaseClass Method();
}
public class Service1 : IService1
{
public BaseClass Method()
{
...
}
}
Whenever I try to create a WCF proxy using "Add Service Reference" in VS it fails and trace log says
Type 'WcfProxyTest.ClassA' cannot be added to list of known types since another type 'WcfProxyTest.ClassB' with the same data contract name 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:ArrayOfKeyValueOfstringanyType' is already present. If there are different collections of a particular type - for example, List<Test> and Test[], they cannot both be added as known types. Consider specifying only one of these types for addition to the known types list.
I can see what the error message is saying, but is there any other way around this (other than refactoring the classes). I am dealing with a legacy system which has classes written in the same manner as in my example and rewriting them is not an option as this stuff sits in the very core of the system :S
Any ideas? Thanks!
I decided to refactor the code in such a way that I don't have to provide two KnownTypes which gets me around the problem. About 300 syntax errors later that worked. I would be interested in any other ways of doing it though...
Try adding:
[KnownType(typeof(Dictionary<string, ITest>))]

Configuring the timeout for a WCF RIA Services call from a Silverlight 3 client

I'm using the WCF RIA Services Beta with Silverlight 3.0 and I want to be able to configure the timeout from the client. I know that the underlying technology is WCF and the default timeout seems to be 60 seconds as I would expect.
Is there an easy way to control this and other WCF settings?
My first thought is to try the DomainContext OnCreated hook point which was mentioned in the RIA Services Overview pdf file that was available prior to RIA Services going beta. The MSDN documentation for the DomainContext object no longer mentions the method although it is still there? I'm not sure if this is a case of the documentation lagging behind or an indication that I shouldn't use this extensibility point.
namespace Example.UI.Web.Services
{
public sealed partial class CustomDomainContext
{
partial void OnCreated()
{
// Try and get hold of the WCF config from here
}
}
}
http://blogs.objectsharp.com/CS/blogs/dan/archive/2010/03/22/changing-timeouts-in-wcf-ria-services-rc.aspx
Either one line after domain context creation:
((WebDomainClient<LibraryDomainContext.ILibraryDomainServiceContract>)this.DomainClient).ChannelFactory.Endpoint.Binding.SendTimeout = new TimeSpan(0, 5, 0);
or a partial class
public partial class LibraryDomainContext
{
partial void OnCreated()
{
if(DesignerProperties.GetIsInDesignMode(App.Current.RootVisual))
((WebDomainClient<LibraryDomainContext.ILibraryDomainServiceContract>)this.DomainClient).ChannelFactory.Endpoint.Binding.SendTimeout = new TimeSpan(0, 5, 0);
}
}
For reference the code below nearly works but you can't access a private member using reflection in Silverlight. Wouldn't have been happy with this hack though anyway. Interesting to note that there is a WebDomainClient contructor that takes a Binding parameter private WebDomainClient(Uri serviceUri, bool usesHttps, Binding binding) but the XML Comment for this states Private constructor. Should be made public once we have an end-to-end extensibility story on top of WCF. Looks like I'll have to wait a while before they get to exposing this kind of configuration to us.
public sealed partial class AppDomainContext
{
partial void OnCreated()
{
var webDomainClient = ((WebDomainClient<AppDomainContext.IAppDomainServiceContract>)this.DomainClient);
// Can I use reflection here to get hold of the Binding
var bindingField = webDomainClient.GetType().GetField("_binding", BindingFlags.NonPublic | BindingFlags.Instance);
// In Silverlight, the value of a private field cannot be access by using reflection so the GetValue call throws an exception
// http://msdn.microsoft.com/en-us/library/4ek9c21e%28VS.95%29.aspx
var binding = bindingField.GetValue(webDomainClient) as System.ServiceModel.Channels.Binding;
// So near yet so far!!
binding.SendTimeout = new TimeSpan(0,0,1);
}
}

How do I export metadata for a single contract with svcutil.exe?

I have two ServiceContracts implemented as interfaces. I want to export the metadata for only one of them. The trick is that both interfaces are implemented by the same class. Therefore, I don't think that I can use /excludeTypes. Please include example syntax when answering. Thanks!
EDIT: A co-worker recently asked me why this is necessary. The reason why is that the first ServiceContract is for a REST service, which it doesn't make sense to export metadata for. So I get two wsdl and xsd files generated, distinguishable only because the second filename is appended with "1". This makes tooling difficult, and adds more clutter to the output directory.
I've added a bounty to try and generate interest in this question.
I created a Service Contract class implementing 2 Interfaces like you described.
namespace NS
{
[ServiceContract]
public interface IREST
{
[OperationContract]
string WorldHello(string name);
}
[ServiceContract]
public interface IInterface
{
[OperationContract]
string HelloWorld(string name);
}
public class CI2 : IREST, IInterface
{
public string WorldHello(string name)
{
return "World Hello: " + name;
}
public string HelloWorld(string name)
{
return "Hello World: " + name;
}
}
}
when running svcutil normally, I get a wsdl with methods from the 2 interfaces
when I run svcutil with /excludeType:IREST for example, I get only IInterface methods.
svcutil /excludeType:NS.IREST ci2service.exe
are you using the same configuration? In that case /excludeType works.