Calling Close() on Service Proxy blocks after One Way WCF call - c#

I have a simple Fire and Forget service operation that works fine and doesn't block. However, when I try to close the service proxy, it will block until the one-way call completes. Is this expected behavior?
Client Code:
var serviceProxy = new MyServiceProxy();
serviceProxy.OneWayCall();
serviceProxy.Close(); // This blocks until OneWayCall() is finished.
Service:
[ServiceContract]
public interface IMyService {
[OperationContract(IsOneWay = true)]
void OneWayCall();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyService {
public void OneWayCall() {
// Stuff and things
}
}

Yes - depending on the binding/configuration your service is using and if you are using sessions in any way. See the below link for information on configurations that lead to blocking:
WCF Best Practice #5: One-way is not always really one-way
Hope that helps

For completeness' sake; here is what Microsoft has to say about this behavior:
Clients Blocking with One-Way Operations

Related

Global.asax.cs Application_BeginRequest - Throw WebFaultException

Is there a way in WCF to check some logic based on the type of Request it receives? Can this be done in the actual service endpoint code?
For example:
After Service Initialization my service receives a PUT Request. In myService.svc.cs I would like to have logic that looks like this:
if httpRequest.Type == PUT
{
//Do Something
}
Is this possible? I'm sure there is a better way to handle requests than adding logic for every Operation Contract that is of type PUT. Apologies if this question doesn't make sense I'm sort of new to WCF and am trying to learn. Please let me know if you need clarifiers.
EDIT:
This is what myService.svc.cs looks like currently:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public partial class MyService: IMyService
{
public async Task<someObject> GetMethod1 () // Some GET Method
{
doSomethingForGetRequests();
//method implementation
}
public async Task<someObject> GetMethod2 () // Some GET Method
{
doSomethingForGetRequests();
//method implementation
}
public async Task<someObject> PutMethod1 () // Some PUTMethod
{
doSomethingForPutRequests();
//method implementation
}
doSomethingForPutRequests()
{
if(config.IsReadOnly)
{
throw new WebFaultException(HttpStatusCode.BadRequest);
}
}
}
I am wondering if there is a place where i can place doSomethingForGetRequest() and doSomethingForPutRequest() in a central location before the request reaches these methods so I don't have to add these methods to each one of my Service Methods.
Would global.asax.cs Application_BeginRequest() be an appropriate place for this logic?
Maybe a message inspector can help you, it's called on every request that arrives at the service.
IDispatchMessageInspector defines the methods that enable custom inspection or modification of inbound and outbound application messages in service applications.
You can check out these posts:
Detect if action is a POST or GET method
Call the method automatically for each and every request in the WCF REST

Disposing of database connection from within WCF

I have a WCF service hosted in IIS:
[WebServiceLogging]
public class ComplaintService : IComplaintService
This service has the WebServiceLogging attribute that does straightforward request/response logging into the database:
public class WebServiceLoggingAttribute : Attribute, IServiceBehavior {
SomeDatabaseConnection connection; // unmanaged resource
... interface implementations
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) {
IDispatchMessageInspector messageInspector = new WebServiceLogger(connection, _operations);
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
{
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
dispatchRuntime.MessageInspectors.Add(messageInspector); // pass the logger into WCF.
}
}
}
}
Logging work is done from the WebServiceLogger, which uses the SomeDatabaseConnection unmanaged resource:
public class WebServiceLogger : IDispatchMessageInspector {
public object AfterReceiveRequest {
... gather Request data.
}
public void BeforeSendReply {
... gather Request data.
... Log using ADO.NET
... Dispose of Command object. No Connection closing!
}
}
I need to close the connection within WebServiceLogger once I'm done with logging. Options I've identified are:
Implement an IDisposable on WebServiceLogging class and do a Dispose() there or
Dispose of SomeDatabaseConnection directly from WebServiceLogger.BeforeSendReply()
My questions here are:
IDispatchMessageInspectors (such as WebServiceLogger) passed into dispatchRuntime.MessageInspectors - I've noticed that this object is not recreated per each request, but rather only once on the first request towards my service. How are such objects disposed of? Does WCF call `Dispose()˙ on them or should I use some other approach here?
Since we're at it, I have a nagging thought that perhaps using unmanaged resources in an Attribute is not such a good idea. Googling for c# attribute dispose didn't yield any results (there is one result on destructor, though). Any critiques on this approach?
Open and close a connection inside the BeforeSendReply method; i.e. make it a local variable (with a using-block, etc.).
Something like this:
public void BeforeSendReply {
... gather Request data.
using (var conn = new SqlConnection(...)) {
... Log using ADO.NET
}
}
The overhead is usually irrelevant (as ADO.NET uses connection pooling and won't really open/close a brand new connection). Second, and most importantly, that way you don't have to think about how your interceptor instance is used/called in a multithreaded (parallel requests) scenario.
That also matches better the unit of work pattern, that would be typically used if you did the same thing in the implementation method of an OperationContract. If you think about it, the interceptor points (AfterReceiveRequest and BeforeSendReply) are really just extensions of such method implementations (kind of AOP).

How to make WCF Service take only one call at a time

We have a WCF service like
Public Class MyService
{
[OperationContract]
Public void OpperationA()
{
}
[OperationContract]
Public void OpperationB()
{
}
[OperationContract]
Public void OpperationC()
{
}
[OperationContract]
Public void OpperationD()
{
}
}
We have a client for this WCF service which is a windows service which invokes all the operations above OperationA/B/C/D with new proxies.
With the current implementation we have there are issues with Client Invoking all operations at the same time.
InstanceContextMode = PerCall and ConcurrencyMode = Single
Is there any combination of InstanceContextMode and COncurrency which Can change my service to take only one request at a time, I mean if client proxy A has called OPerationA and the service is processing the request and if the Client proxy B tries to call OperationB (or any other operation), it should be blocked until the first request is finished.
Thanks
It should be sufficient to change the InstanceContextMode to Single. From the MSDN documentation here:
ConcurrencyMode=Single : The service instance is single-threaded and does not accept reentrant calls. If the InstanceContextMode property is Single, and additional messages arrive while the instance services a call, these messages must wait until the service is available or until the messages time out.
From http://msdn.microsoft.com/en-us/library/system.servicemodel.instancecontextmode%28v=vs.110%29.aspx
If the InstanceContextMode value is set to Single the result is that your service can only process one message at a time unless you also set the ConcurrencyMode value to Multiple.
Obviously that won't work if you have multiple service hosts.

WCF invoke not interfaced method?

just came across a problem.
I'm trying to make a wcf service unittest ready or better all code have to be tested with unittest.
Atm its not possible coze I've got a connection to a crm 2011 server that is used every time.
so i replaced it with a Interface. but i want to unittest the WCF like you use it.
now my idea is to make a public method and and give a fake connection.
now my question is would it be possible to invoke this method(example: ConnectionHandler), even if its not in the interface?
this would look like this:
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
public class WCF: IWCF
{
public bool method1(){
...
}
public bool method2(){
...
}
private connection connectionHandler;
public connection ConnectionHandler(Iconnection con){
if(con != null){
connectionHandler = con;
} else {
connectionHandler = takedefault;
}
}
}
Edit
ah i forgot to tell this: im actually have the security in mind, i don't want that anyone can pass a different connection to the server its for unittest purpose only.
It is possible to invoke this method, you can cast the interface to the concrete object. But that would compromise the calling code, which should not know the implementation details of your service.
I would reccomend in your sittuation to use the constrcutor injection so your service implemetation would look like this:
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
public class WCF: IWCF
{
private connection connectionHandler;
public WCF(Iconnection con)
{
if(con != null){
connectionHandler = con;
} else {
connectionHandler = takedefault;
}
}
public bool method1(){
...
}
public bool method2(){
...
}
}
In this case the client code will not know the details of the service implementation, if you use the constrcutor injection on the client as well
One of important features of any well designed piece of code is that you are explicit about the functionality that you expose to your clients. This becomes a key feature of service orientated applications, as you are exposing your functionality in a standardised way for external clients to consume.
Calling a method that is not part of the interface is bad in principle as you are now programming to the implementation and not the interface. Happily WCF knows this and will not let you a method that is not on the interface as it is not decorated with the OperationContract attribute.
With respect to your code - I am not sure exactly what it is you are trying to achieve - to have a client set (what I assume is) something like a database connection makes me a little uneasy (for a start this means your service is holding some state which goes against the Service statelessness principle). This does not mean that what you are doing is necessarily wrong, but you should find that you only rarely have to violate this in a well designed application.
That said, if you want to expose different areas of functionality to different clients the correct way to do this is by exposing endpoints on your service representing the different contracts:
[ServiceContract]
public interface IWCF
{
[OperationContract]
bool method1();
[OperationContract]
bool method2();
}
[ServiceContract]
public interface IConnectionWCF
{
[OperationContract]
bool SetConnection(string connection);
}
public class WCF : IWCF, IConnectionWCF
{
public bool method1()
{
...
}
public bool method2()
{
...
}
public bool SetConnection(string connection)
{
...
}
}
You also need to be mindful that everything the WCF service received must first be serialized by the client, sent over the wire, and deserialized on the server. You are very much dealing with concrete classes here - not abstractions. Passing an interface (such as Iconnection) as an argument to a service call does not really make any sense in a service-orientated environment.
With regards to unit testing - just remember that fundamentally the class WCF is just a plain old class. You can unit test this class in isolation of the fact that it is a WCF service. You shouldn't be setting up any of the service hosting functionality within your unit tests anyway - you want to check that the code that YOU write is correct - the WCF stack has already been tested by Microsoft.
EDIT
In response to your comment, as suggested here, you should used constructor injection to set the connection object when the class is instantiated. This then raises the question of how you gain control over the instantiation of the WCF service. You need to implement IInstanceProvider, or for a more detailed implementation see here. This way, when you service is hosted in WCF, you use IInstanceProvider, when you are testing you simply pass your fake connection object to the constructor.
EDIT
To clarify, a unit test for this class would resemble this:
[TestClass]
public class UnitTests
{
[TestMethod]
public void Test()
{
Iconnection connection = new FakeConnection();
WCF classUnderTest = new WCF(connection);
//Run test logic
}
}

C# WCF NetTCPBinding Blocking Application

I have a basic buddylist type application which is a pub/sub deal in WCF. My problem is one or two of the calls are long running and this blocks up the entire server application (gui updates etc).
Here's my code:
[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract = typeof(IBuddyListContract))]
public interface IBuddyListPubSubContract
{
[OperationContract]
string GetABunchOfDataZipped(String sessionId); // this can take > 20 seconds
....
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class BuddyListPubSubContract : IBuddyListPubSubContract
{
string GetABunchOfDataZipped(String sessionId)
{
// do some calculations and data retrival
return result;
}
}
So far I have an idea on how to go about it but is there a simpler way?
Idea 1: Have GetABunchOfDataZipped(String sessionId) be a void, when it finishes have another endpoint which on my duplex contract which I hit. I don't like this as ifs a fundamental change in my architecture and if the string is a large block of text over a slow internet connection it will still suffer from the same issue?
My problem is one or two of the calls are long running and this blocks up the entire server application (gui updates etc).
You're not clear on where you're seeing the blocking behavior, but it sounds like it would be on the client side. You should be making your call to your WCF service from a background thread, not the UI thread. Then when you handle the result, you won't be able to interact with your UI elements directly, you will need to use each control's Invoke method.

Categories

Resources