Do specific code depending on the WCF service behavior - wcf

Is it a good idea to get the current WCF behavior withing a WCF operation contract and do some stuff depending on the current behavior?
If no: Why not?
If yes: How can I do that?
For example something like this:
// Interface
[ServiceContract]
public interface IDataService
{
[OperationContract]
DataResponse GetData(DataRequest request);
}
// Implementation of the IDataService.GetData
public DataResponse GetData(DataRequest request)
{
// get current behavior
IBehavior currBevhavior = ...?
if (currBehavior.name = ""){
// custom code for this behavior
}
...
}
Edit: The same thing for the binding: Is it a good idea to do stuff in code depending on which binding the current request came in? How can I do that?

Related

WCF Polymorphism in service contract

I am trying to create a service that with an operation that accepts, as a parameter, an any object that implements a specific interface. I would have thought this would be easy to accomplish, but I am running into problems (what I am guessing to be serialization problems but I am not certain). I have the following contract:
//Unsustainable because I would need a method for each of the (currently)
//3 student types, plus I have 2 more root categories that have multiple subtypes
public interface IEmailTemplateAccess
{
[FaultContract(typeof(ValidationFault))]
[FaultContract(typeof(ErrorResponse))]
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
TemplateResponse GetStudentTemplate(ITemplateRequest request);
}
And this is what I would like it to look like:
public interface IEmailTemplateAccess
{
[FaultContract(typeof(ValidationFault))]
[FaultContract(typeof(ErrorResponse))]
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
TemplateResponse GetTemplate(ITemplateRequest request);
}
In my service I use an abstract factory to return the correct template based on the type of request that comes in. In addition, I have created concrete ITemplateRequests for the different kinds of templates that could be returned. For example, I have Template Request types A and B. Template Request Type A can have one of 3 sub types, SubType1, SubType2 and SubType3. I then created a SubType3 request that implemented the ITemplateRequest interface (SubType3Request).
I would hate to have to create a method for each request type I have (i.e. GetSubType1Template, GetSubType2Template, GetSubType3Template, GetTypeBTemplate, etc) as this would quickly become unwieldy as the types of templates I can get will be changing occasionally.
Is there a way to have a contract method accept anything that implements ITemplateRequest as a parameter and let my factory do the work of figuring out what type of template to get?
So far, I have the following methods in my service:
//Not a part of the contract right now although I would like it to be
public IEmailTemplate GetTemplate(ITemplateRequest request)
{
TemplateFactoryBuilder builder = new TemplateFactoryBuilder();
ITemplateFactory factory = builder.GetTemplateFactory(request.Type);
var template = factory.GetTemplate(request);
return template;
}
//contract method --This would be my Parent Request Type (RequestTypeA) from above.
//There are 3 subtypes of the Student type
public TemplateResponse GetStudentTemplate(StudentEmailTemplateRequest request)
{
var response = new TemplateResponse
{
RequiresProcessing = true
};
response.Template = (EmailMergeTemplate) GetTemplate(request);
return response;
}
Sorry for the link-ish answer, but it's pretty long.. What you're after (I think) is here: http://blogs.msdn.com/b/morgan/archive/2009/08/05/polymorphism-in-wcf.aspx
It boils down to using known types. Something like this;
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(CommandServiceHelper))]
public interface ICommandService

AutoFac WCF proxy with changing ClientCredentials

I'm writing a WCF service and am using the AutoFac WCF integration for DI. I have a slightly weird situation where I have a proxy to another service that requires credentials. The credentials will change based on some parameters coming in so I can't just set the values when I'm setting up the container and be done with it.
public class MyService : IMyService
{
private ISomeOtherService _client;
public MyService(ISomeOtherService client)
{
_client = client;
}
public Response SomeCall(SomeData data)
{
// how do I set ClientCredentials here, without necessarily casting to concrete implementation
_client.MakeACall();
}
}
What's the best way to set the credentials on proxy without having to cast to a known type or ChannelBase. I'm trying to avoid this because in my unit tests I'm mocking out that proxy interface so casting it back to one of those types would fail.
Any thoughts?
You can do it, but it's not straightforward, and you have to slightly change the design so the logic of "decide and set the credentials" is pulled out of the MyService class.
First, let's define the rest of the classes in the scenario so you can see it all come together.
We have the ISomeOtherService interface, which I've modified slightly just so you can actually see what credentials are getting set at the end. I have it return a string instead of being a void. I've also got an implementation of SomeOtherService that has a credential get/set (which is your ClientCredentials in WCF). That all looks like this:
public interface ISomeOtherService
{
string MakeACall();
}
public class SomeOtherService : ISomeOtherService
{
// The "Credentials" here is a stand-in for WCF "ClientCredentials."
public string Credentials { get; set; }
// This just returns the credentials used so we can validate things
// are wired up. You don't actually have to do that in "real life."
public string MakeACall()
{
return this.Credentials;
}
}
Notice the Credentials property is not exposed by the interface so you can see how this will work without casting the interface to the concrete type.
Next we have the IMyService interface and associated request/response objects for the SomeCall operation you show in your question. (In the question you have SomeData but it's the same idea, I just went with a slightly different naming convention to help me keep straight what was input vs. what was output.)
public class SomeCallRequest
{
// The Number value is what we'll use to determine
// the set of client credentials.
public int Number { get; set; }
}
public class SomeCallResponse
{
// The response will include the credentials used, passed up
// from the call to ISomeOtherService.
public string CredentialsUsed { get; set; }
}
public interface IMyService
{
SomeCallResponse SomeCall(SomeCallRequest request);
}
The interesting part there is that the data we're using to choose the set of credentials is the Number in the request. It could be whatever you want it to be, but using a number here makes the code a little simpler.
Here's where it starts getting more complex. First you really need to be familiar with two Autofac things:
Implicit relationships - we can take a reference on a Func<T> instead of a T to get a "factory that creates T instances."
Using parameters from registration delegates - we can take some inputs and use that to inform the outputs of the resolve operation.
We'll make use of both of those concepts here.
The implementation of MyService gets switched to take a factory that will take in an int and return an instance of ISomeOtherService. When you want to get a reference to the other service, you execute the function and pass in the number that will determine the client credentials.
public class MyService : IMyService
{
private Func<int, ISomeOtherService> _clientFactory;
public MyService(Func<int, ISomeOtherService> clientFactory)
{
this._clientFactory = clientFactory;
}
public SomeCallResponse SomeCall(SomeCallRequest request)
{
var client = this._clientFactory(request.Number);
var response = client.MakeACall();
return new SomeCallResponse { CredentialsUsed = response };
}
}
The real key there is that Func<int, ISomeOtherService> dependency. We'll register ISomeOtherService and Autofac will automatically create a factory that takes in an int and returns an ISomeOtherService for us. No real special work required... though the registration is a little complex.
The last piece is to register a lambda for your ISomeOtherService instead of a simpler type/interface mapping. The lambda will look for a typed int parameter and we'll use that to determine/set the client credentials.
var builder = new ContainerBuilder();
builder.Register((c, p) =>
{
// In WCF, this is more likely going to be a call
// to ChannelFactory<T>.CreateChannel(), but for ease
// here we'll just new this up:
var service = new SomeOtherService();
// The magic: Get the incoming int parameter - this
// is what the Func<int, ISomeOtherService> will pass
// in when called.
var data = p.TypedAs<int>();
// Our simple "credentials" will just tell us whether
// we passed in an even or odd number. Yours could be
// way more complex, looking something up from config,
// resolving some sort of "credential factory" from the
// current context (the "c" parameter in this lambda),
// or anything else you want.
if(data % 2 == 0)
{
service.Credentials = "Even";
}
else
{
service.Credentials = "Odd";
}
return service;
})
.As<ISomeOtherService>();
// And the registration of the consuming service here.
builder.RegisterType<MyService>().As<IMyService>();
var container = builder.Build();
OK, now that you have the registration taking in an integer and returning the service instance, you can just use it:
using(var scope = container.BeginLifetimeScope())
{
var myService = scope.Resolve<IMyService>();
var request = new SomeCallRequest { Number = 2 };
var response = myService.SomeCall(request);
// This will write "Credentials = Even" at the console
// because we passed in an even number and the registration
// lambda executed to properly set the credentials.
Console.WriteLine("Credentials = {0}", response.CredentialsUsed);
}
Boom! The credentials got set without having to cast to the base class.
Design changes:
The credential "set" operation got moved out of the consuming code. If you don't want to cast to the base class in your consuming code, you won't have a choice but to also pull the credential "set" operation out. That logic could be right in the lambda; or you could put it in a separate class that gets used inside that lambda; or you could handle the OnActivated event and do a little magic there (I didn't show that - exercise left to the reader). But the "tie it all together" bit has to be somewhere in the component registration (the lambda, the event handler, etc.) because that's the only point at which you still have the concrete type.
The credentials are set for the lifetime of the proxy. It's probably not good if you have a single proxy in your consuming code where you set different credentials just before you execute each operation. I can't tell from your question if that's how you have it, but... if that's the case, you will need a different proxy for each call. That may mean you actually want to dispose of the proxy after you're done with it, so you'll need to look at using Owned<T> (which will make the factory Func<int, Owned<T>>) or you could run into a memory leak if services are long-lived like singletons.
There are probably other ways to do this, too. You could create your own custom factory; you could handle the OnActivated event that I mentioned; you could use the Autofac.Extras.DynamicProxy2 library to create a dynamic proxy that intercepts calls to your WCF service and sets the credentials before allowing the call to proceed... I could probably brainstorm other ways, but you get the idea. What I posted here is how I'd do it, and hopefully it will at least point you in a direction to help you get where you need to go.
The approach we ended up taking is to cast ISomeOtherService to ClientBase,
This avoids referencing the proxy type. Then in our unit tests we can set up the mock like so
var client = new Mock<ClientBase<ISomeOtherService>>().As<ISomeOtherService>();
So it can be casted to ClientBase, but still setup as ISomeOtherService

Ninject Interception: Service calling intercepted method not being intercepted when called within itself

I have a service class injected with Ninject 3.0. I have set it up so it's proxy is a class proxy rather than an interface proxy. The service has 2 methods, a first one returning broad result and a second one calling the first one and filtering it. I added a interceptor to cache the result of the first method.
The interception works fine when I call the first method from outside the service.
The problem is that when the interceptor invokes the second method, it invokes it through the service itself and not through the proxy, resulting in my call to the first method from my service not being intercepted, therefor not cached.
How can I get this to work?
UPDATE: Added sample code
This is on the top of my head so sorry if anything doesn't seem to compile
Here is a sample the service class
public class Service : IService
{
[CacheMethodOutput]
public virtual object[] GetObjects(int x)
{
...
}
public virtual object GetObject(int x, int y)
{
return GetObjects(x).SingleOrDefault(o => o.y == y);
}
}
The CacheMethodOutputAttribute is a simple attribute class
Here is a sample binding (this is the way I make sure to have a class proxy instead of a interface proxy but actually leave the injected reference by interface)
// Binds by type instead of proxy to create a class proxy
Bind<Service>().ToSelf().InSingletonScope().Intercept().With<CacheAttributeInterceptor>()
Bind<IService>().ToMethod<Service>(r => r.Kernel.Get<Service>());
So when I call GetObjects from any class in which the IService is injected, the interceptor is triggered, but it's not triggered from the GetObject method of the Service itself.
The CacheAttributeInterceptor looks like this (but details of implementation is irrelevant):
public class CacheAttributeInterceptor : SimpleInterceptor
{
public ICacheManager CacheManager {get;set;}
public override void BeforeInvoke(IInvocation invocation)
{
if (Attributes.GetCustomAttribute(invocation.Request.Method, typeof(CacheMethodOutputAttribute) != null)
{
string key = GenerateKey(invocation.Request.Method.Name, invocation.Request.Method.Arguments);
object returnValue;
if (!CacheManager.TryGet(key, out returnValue))
{
invocation.Proceed();
returnValue = invocation.ReturnValue;
CacheManager.Add(key, returnValue);
}
else
invocation.ReturnValue = returnValue;
}
else
base.BeforeInvoke(invocation);
}
}
I found the solution / more detail on the problem.
If I remove the virtual modifier on the GetObject method, it will then not be intercepted anymore and when it will call GetObjects, the incerceptor will trigger.
All this got me thinking that if I want both method to be intercepted, I need to make the interceptor work deeply, if this is even possible.

How to wrap all results of an EndPoint in OperationResult?

I want to wrap each result from one Wcf service in my application in something like
public class OperationResult{
public string Status;
public string Data;
}
even if my contract looks like
[ServiceContract]
internal interface ITest
{
[OperationContract,
WebGet(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
MyDc EchoDc(MyDc input);
}
From what I've read the potential extensibility points are IServiceBehavior, IEndpointBehavior, IContractBehavior, IOperationBehavior.
Any thoughts where I can hook my wrapping magic ?
Look # my answer here:
How to customize the process employed by WCF when serializing contract method arguments?
There it is mentioned how you can replace an object of one type to another type while it is being returned.
I think thats not possible via extensionpoints on the WCF framework because what you watn to do is to change your contract.
The contract is a c# interface which is used by your client.
You have to write an own proxy class for use by your client where you can map the operation results to whatever you like:
class ServiceProxy : ClientBase<YourServiceInterface>
{
public OperationResult EchoDc(MyDs input)
{
MyDc result = Channel.EchoDc(input);
return new OperationResult( ... // map your operation result here))
}
}

Run WCF ServiceHost with multiple contracts

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
}
}