ServiceStack - how to host multiple versioned endpoints in one service? - c#

Where I was
I'm trying to convert some WCF services to use ServiceStack instead. For the most part it's achieving what I want but there's definitely differences. eg with WCF I had something like:
interface IMethod1{ ResultDTO Method1(InputDTO input); }
interface IMethod2{ ResultDTO Method2(InputDTO input); }
interface IMethod3{ ResultDTO Method3(InputDTO input); }
interface IMyService : IMethod1, IMethod2, IMethod3
then implement with:
public class MyService : ServiceBase, IMyService { /* ... */ }
Where I'm at
With ServiceStack it's more like:
public class Method1{
// parameters for method as properties
}
public class Method2{
// parameters for method as properties
}
public class Method3{
// parameters for method as properties
}
I've tried various thing and the latest dead-end I've hit was with:
public class MyServiceHost<T> : AppHostBase
{
public MyServiceHost(string version)
: base("My Service v" + version, typeof(T).Assembly)
{ }
public override void Configure(Funq.Container container){
Routes.AddFromAssembly(typeof(T).Assembly);
}
}
protected void Application_Start(object sender, EventArgs e) {
new MyServiceHost<Foo.Bar.V0101.MyService>("1.1").Init();
new MyServiceHost<Foo.Bar.V0102.MyService>("1.2").Init();
new MyServiceHost<Foo.Bar.V0201.MyService>("2.1").Init();
}
where it complains that AppHost has already been initialised.
Where I want to be
I want to expose something like this:
http://www.sandwich.com/example/v0101/sandwichservice.wsdl
http://www.sandwich.com/example/v0102/sandwichservice.wsdl
http://www.sandwich.com/example/v0201/sandwichservice.wsdl
or
http://www.sandwich.com/example/sandwich_v0101.wsdl
http://www.sandwich.com/example/sandwich_v0102.wsdl
http://www.sandwich.com/example/sandwich_v0201.wsdl
ideally hosted in the same service process.
So is there a simple answer I'm missing or am I approaching the whole thing fundamentally wrong? Or in a nutshell: using ServiceStack, is it possible to and how can I expose multiple endpoints and WSDLs for versioned web services in the same host service?

See this answer for recommended versioning strategies with ServiceStack.
You can't expose multiple versions of SOAP/WSDL's in ServiceStack, you're encouraged to evolve the same DTO's which means there are no previous type versions to create an older version of the WSDL. You would need to host older versions of ServiceStack project for the auto-generated WSDL to match up with older types.
You could also take a snapshot of a WSDL and host it statically, but whether a new SOAP endpoint accepts a client sending an old SOAP version is up to .NET's WCF Message class doing the parsing. But as SOAP is a brittle format, YMMV.

Related

Find all references with WCF OperationContract and DataContracts

I'm trying to figure out if there's a way to "Find all references" (using the VS feature, as opposed to Control+F entire solution). when it comes to WCF Data and OperationContracts. In case that is unclear:
namespace WcfTestReferences
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello world");
DoStuff();
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
var results = client.GetData(42);
Console.WriteLine(results);
}
static void DoStuff() { }
}
}
namespace WcfTestReferences.WCFApp
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
}
Solution looks like this:
Now, if I look at DoStuff() with code lens, I can see that it in fact has a reference to it:
But the same does not hold true for the methods being called in the wcf service:
In the above, the only references to the interface/method is the interface/method. I understand that the reference that I was hoping would be there (from the main method):
var results = client.GetData(42);
is not there, because the client is generated, and is not actually my Service1 implementation... but is there a way to change this?
In the real world, we have a WCF layer with thousands of methods, many of which are not used - but I cannot rely on Code Lens/Find all references to make this determination. Is there any way to change this behavior?
because the client is generated, and is not actually my Service1
implementation
This is the root of the problem.
You are correct - there is no way for your code analyser to determine that the GetData() call you are making from your client is semantically the same thing as the GetDate() service operation you have defined on your interface, because from a binary perspective they are defined in two completely different types.
The root of this is that you're using a service reference. WCF provides service references as the default way of connecting to a service, but in my opinion service references are problematic and should be avoided.
Luckily, WCF provides another way of consuming and calling a service via the user of ChannelFactory<T>. One of the many benefits you will get when using this instead of a service reference is that your client will have use of the service interface via a binary reference to the assembly containing your service definition.
This will allow tools like code lens to resolve references to your interface methods directly to your consuming clients.

WCF service generated by WSCF.blue Service Error "implementation type is an interface or abstract class and no implementation object was provided"

I am using C# Visual Studio 2012 to create a wcf service.
I had the WSCF.blue tool generate the wsdl from the xsd-s. Then I generated the web service code using the same tool. WSCF.blue does not create a Service Contract and a Data Contract. It creates an interface and a .svc file that contains a class that implements the interface.
When generating the web service code I selected the option to create the abstract classes because I want to be able to keep the implementation of these classes in a separate file.
The abstract class looks like this:
[KnownType(typeof(WebMobileImplementation))]
public abstract class WebMobile : IWebMobile
{
public abstract PutLocationsResponse PutLocations(PutLocationsRequest request);
}
The implementing class (in a different file) looks like this (for now):
public class WebMobileImplementation : WebMobile
{
public override PutLocationsResponse PutLocations(PutLocationsRequest request)
{
PutLocationsResponse response = new PutLocationsResponse();
return response;
}
}
When trying to browse the service I get the message: "Service implementation type is an interface or abstract class and no implementation object was provided"
I thought that adding the knowntype to the implementing class will do the trick but it seems that the implementation is not 'seen' when running the service. What else can I do to 'connect' them?
In WCF 4.0, you can define virtual service activation endpoints that map to your service types in Web.config. This makes it possible to activate WCF services without having to maintain physical .svc files.
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="WebMobile.svc"
service="WebMobileNamespace.WebMobileImplementation"/>
</serviceActivations>
</serviceHostingEnvironment>

ServiceStack - Unit of work and structure map

I am making a rest service using ServiceStack (http://www.servicestack.net). I'm using the unit of work pattern for my data access layer. I am using StructureMap to connect all my services and the unit of work together.
What I need to do is to create a single unit of work for each individual request that I receive and then dispose of it after.
I have a WCF Service which is using the mechanism here, http://andreasohlund.net/2009/04/27/unitofwork-in-wcf-using-structuremap.
Essentially resulting in something like this
ObjectFactory.Initialize(x =>
{
x.Scan(a =>
{
a.AssemblyContainingType<IUnitOfWork>();
a.WithDefaultConventions();
});
x.For<IUnitOfWork>().LifeCycleIs(new WcfOperationLifecycle());
}
I am looking for a similar 'Lifecycle' for ServiceStack.
[Solution]
The solution is in the comments of the accepted answer.
a) Set the StructureMap lifecycle to HttpContext
x.For<IUnitOfWork>().LifecycleIs(Lifecycles.GetLifecycle(InstanceScope.HttpContext));
b) Updated the structure map IOC adapter to extend the IRelease interface
class StructureMapContainerAdapter : IContainerAdapter, IRelease
{
public T Resolve<T>()
{
return ObjectFactory.GetInstance<T>();
}
public T TryResolve<T>()
{
return ObjectFactory.TryGetInstance<T>();
}
public void Release(object instance)
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
}
Sounds like you just want Request Scope?
Also check out the concrete Service base class on how you can use Lazy loading + Dispose() to get this behaviour.
As well as in ServiceStack's new API you can override your services OnBeforeExecute() OnAfterExecute() event hooks by using your own ServiceRunner (in the older API you would need to provide a custom service base class).

Is it possible to use generic DataContract's from the client end?

I know when you create a service you can create a generic DataContract:
[DataContract(Name = "Get{0}Request")
public sealed class GetItemRequest<T>
where T : class, new() { ... }
[DataContract(Name = "Get{0}Response")
public sealed class GetItemResponse<T>
where T : class, new() { ... }
[ServiceContract]
public void MyService : IMyService
{
[OperationContract]
GetItemResponse<Foo> GetItem(GetItemRequest<Foo> request);
}
This generates a GetFooRequest and GetFooResponse definition for my WSDL. Now, what I'm curious about is if it is possible to go in the other direction?
Is it possible to create a client that uses the Generic DataContracts and pass those to the server as a concrete object? I attempted this after adding a Service Reference and it didn't really work out so well. So this is more of me wondering if there is any way (even if it means not adding a Service Reference) to do this?
Ultimately, WCF is going to look at the contract class. If that is generated from WSDL/MEX it won't have this (since this isn't how it is expressed in the metadata) - but if your client has the code as above, then sure it should work fine.
If you add a library reference (i.e. a dll / project reference) to your DTO dll from the client, and ensure WCF has shared-assemblies enabled, it should work. If it still baulks, then cheat: use a service reference just to get the config data. Then delete the service reference but keep the configuration (those config files are a pain otherwise). Then it should locate the type from the library.

WCF service returning another service (service factory?)

We are using WCF for communication between a client and a server application. The client application has many features that requires communication to the server - and we have chosen to implement this in multiple classes (seperation of responsability)
For the time, we are creating new WCF endpoints and service contracts for each object - Invoicing, Accounting, Content Management, etc. This causes a lot of endpoint configuration both on the client and server (with potential misconfiguration problems when moving into the test and production platforms).
I would like to know if I can define a single WCF endpoint that can deliver multiple service contact implementations. Our configuration files would then contain a single endpoint (to the service factory) and I can request different services by specifying the interface of the service I am interested in.
e.g.
using (IServiceClientFactory serviceClientFactory = new RealProxyServiceClientFactory())
{
// This is normal WCF proxy object creation.
IServiceFactory serviceFactory = serviceClientFactory.CreateInstance<IServiceFactory>("");
// This is what we would like to do
IInvoiceService invoiceService = serviceFactory.getService(typeof(IInvoiceService));
invoiceService.executeOperation(data);
}
The clue being a single endpoint configuration per client/server pair, instead of an endpoint configuration per service contact I would like to make available.
Is this possible?
I'm not 100% clear on what you're trying to do, but if you just want to be able to host different contracts on the same address with the implementation inside one service class, this is completely possible. To share an endpoint address, you must ensure that you use the same binding instance for each service endpoint.
Here is a complete sample which defines 3 contracts, 1 service class which implements all of them, and a ServiceHost with the 3 contract endpoints at the exact same address:
using System;
using System.ServiceModel;
[ServiceContract]
interface IContractA
{
[OperationContract]
void A();
}
[ServiceContract]
interface IContractB
{
[OperationContract]
void B();
}
[ServiceContract]
interface IContractC
{
[OperationContract]
void C();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
class Service : IContractA, IContractB, IContractC
{
public Service()
{
}
public void A()
{
Console.WriteLine("A");
}
public void B()
{
Console.WriteLine("B");
}
public void C()
{
Console.WriteLine("C");
}
}
class Program
{
public static void Main(string[] args)
{
Uri address = new Uri("net.pipe://localhost/Service/");
ServiceHost host = new ServiceHost(new Service(), address);
NetNamedPipeBinding binding = new NetNamedPipeBinding();
host.AddServiceEndpoint(typeof(IContractA), binding, string.Empty);
host.AddServiceEndpoint(typeof(IContractB), binding, string.Empty);
host.AddServiceEndpoint(typeof(IContractC), binding, string.Empty);
host.Open();
IContractA proxyA = ChannelFactory<IContractA>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));
proxyA.A();
((IClientChannel)proxyA).Close();
IContractB proxyB = ChannelFactory<IContractB>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));
proxyB.B();
((IClientChannel)proxyB).Close();
IContractC proxyC = ChannelFactory<IContractC>.CreateChannel(new NetNamedPipeBinding(), new EndpointAddress(address));
proxyC.C();
((IClientChannel)proxyC).Close();
host.Close();
}
}
I doubt that this would work. Xml serialization might be the biggest problem here.
Also I don't think you actually need it. If I was in your shoes I would try and abstract my communication with the service. Basically you would always send a "Message" to the service, which has a "Target" being one of the classes you wanted to access. The service would always reply with a "Response", of which the contents would be filled by the class the "Message" was send to.
Another approach would be to route all these messages trough a service that would echo the request to the appropriate service. This way you keep scalability up, but it does still have a large configuration burden.
HTH.
Sounds like you want to keep your seperate services but have some kind of bus that routes is throught. MSMQ maybe, then you can have one services that takes every message pops it onto a specific queue and then a dedicated service can read that off that particular queue.
Not really a WCF based solution though admittedly.
The notion of a single interface(read as ServiceContract) implemented by multiple classes wont work. So you'd need one 'monster' service that implements all and routes through to the correct service. Facade pattern springs to mind.

Categories