WCF ServiceDebugBehavior IncludeExceptionDetailInFaults = true - wcf

I have a server/client WCF app with calls from client to server and callbacks from server to client.
I'm getting some kind of error when I try to do the callback.
But the info I get is useless, so they give you the tip to set the exception Detail In Faults to true to see more details.
I have this but I dont know how to include other behaviour since only 1 is allowed.
ServiceMetadataBehavior smb1 = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb1 == null)
smb1 = new ServiceMetadataBehavior();
smb1.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb1);
I also want to let know the way I'm using the callbacks.
When the client calls the server, my function in the server does all the stuff I need and saves the channel:
callbacks = OperationContext.Current.GetCallbackChannel<IServiceCallbackContract>();
And then when I need to call the client from the server, I use that channel. BUT NOT IN THAT FUNCTION!
I thought this couldn't be done but I saw it in some examples.
So maybe I'm doing something wrong there too and you only can do the callback within the function in the server called from the client and which interface specifies the interface callback contract.

Finally got it working that way, just saved the channel and answered when I need in other function.

Related

Azure Functions Consumption Plan WCF Client Errors "attempt failed because the connected..."

We recently switched our azure functions durable functions based app from a dedicated s1/standard app service plan to dynamic y1 plan to same money and now we are getting a common error:
"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond."
this happens after about an hour of the app running. The exceptions comes from a svcutil generated wcf client. I'm fairly certain this is related to the limitation of socket connections from a consumption function app vs a "dedicated" app plan as described at https://learn.microsoft.com/en-us/azure/azure-functions/functions-scale#service-limits but not totally convinced because i do NOT see the log message "Host thresholds exceeded: Connections" listed at https://learn.microsoft.com/en-us/azure/azure-functions/manage-connections#connection-limit
our client is actually a wrapper around a dozen wcf clients instantiated on our wrappers construction. the wrapper is registed with di as a singleton
builder.Services.AddSingleton<IWrapperClient, OurSoapClient>();
public OurSoapClient(
IMemoryCache memoryCache,
IOptions<Options> options,
ILogger<OurSoapClient> log
)
{
this.options = options.Value;
this.memoryCache = memoryCache;
this.log = log;
this.metaClient = new Meta.MetaWebServiceClient(
Meta.MetaWebServiceClient.EndpointConfiguration.MetaWebServicePort,
this.options.MetaHref
);
this.wmsClient = new Wms.WmsWebServiceClient(
Wms.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsStageItemsClient = new Wms.Stage.Items.WmsWebServiceClient(
Wms.Stage.Items.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsReceiptClient = new Wms.Stage.ExpectedReceipts.WmsWebServiceClient(
Wms.Stage.ExpectedReceipts.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsStageRmaClient = new Wms.Stage.Rma.WmsWebServiceClient(
Wms.Stage.Rma.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsStageShipmentsClient = new Wms.Stage.Shipments.WmsWebServiceClient(
Wms.Stage.Shipments.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsUpdateShipmentsClient = new Wms.Updates.ShippingResults.WmsWebServiceClient(
Wms.Updates.ShippingResults.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsUpdatesReceivingResultsClient = new Wms.Updates.ReceivingResults.WmsWebServiceClient(
Wms.Updates.ReceivingResults.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsUpdatesInventoryAdjustmentClient = new Wms.Updates.InventoryAdjustments.WmsWebServiceClient(
Wms.Updates.InventoryAdjustments.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsInboundOrderClient = new Wms.Inbound.CurrentAndHistory.WmsWebServiceClient(
Wms.Inbound.CurrentAndHistory.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsOutboundOrderClient = new Wms.Outbound.CurrentAndHistory.WmsWebServiceClient(
Wms.Outbound.CurrentAndHistory.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsInboundOrderDetailsClient = new Wms.Inbound.CurrentAndHistoryDetails.WmsWebServiceClient(
Wms.Inbound.CurrentAndHistoryDetails.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
this.wmsOutboundOrderDetailsClient = new Wms.Outbound.CurrentAndHistoryDetails.WmsWebServiceClient(
Wms.Outbound.CurrentAndHistoryDetails.WmsWebServiceClient.EndpointConfiguration.WmsWebServicePort,
this.options.WmsHref
);
}
switching back to standard app service plan seems to make this go away.
i'm fairly certain durable functions isn't a cause here, but just to be clear all the calls to the client happen from Orchestrator or Activity functions...we see the same failure errors in both function types.
One anecdote i've noticed repeated is the errors seem to occur just after a second OurWrapperClient is instantiated (which instantiates all the wcf clients again)...since it's a singleton this must be the azure functions control plane spinning up another instance of my app
so a couple of questions:
any idea how to prove this is max outbound connections related issue?
any suggestions for reasons why this becomes a problem
assuming this is related to WCF
what's the correct way to use wcf clients, should they be instantiated for each call with usings, or is it ok to instantiate them once per wrapper client as we have and then dispose them only once?
should we instantiate them as singletons with the DI and then inject them instead? This means DI would call Dispose on them i believe
is there any way to pass the http client to be used to the wcf client generated code? a lot of the azure functions best practices say to have a single injected http client for all your http I/O, but i don't see how to do that with WCF.
Using app insights i noticed that the takes about an hour thing corresponded to my app switching host instances around that time. eventually i started to see that on deploys it would fail right away..ie got a "bad" host. opened up a MS support case they remoted into a bad isntance and found they could not TCP ping from that host.
Each webspace you are assigned makes requests from a pool of IPs, i suspect my targets WAF was blocking some of these IPs for whatever reason. Switching to a new region which guaranteed a new webspace (they're assigned on created, but are region specific) made the problem go away.
did find https://github.com/dotnet/runtime/issues/35508 during this which seemed similar

What to use so Geode native client pool doesn't hang if no locator found

If I turn off my Geode server and server locator, and then try and connect a client using:
PoolFactory poolFactory = PoolManager
.CreateFactory()
.SetSubscriptionEnabled(true)
.AddLocator(host, port);
if (PoolManager.Find("MyPool") == null)
p = poolFactory.Create("MyPool");
then the poolFactory.Create("MyPool") instruction simply hangs. What do I use to return the Create in this situation of no connection?
It ought to be something like DEFAULT_SOCKET_CONNECT_TIMEOUT in the Javadoc but that doesn't exist in the C# native client...
.SetFreeConnectionTimeout doesn't return either.
Thanks
I don't believe PoolFactory::Create makes any synchronous connections, so I can't explain why it hangs. As this issue would require more back and forth you should post your question on the users#geode.apache.org mailing list.

How to simulate an uncompleted Netty ChannelFuture

I'm using Netty to write a client application that sends UDP messages to a server. In short I'm using this piece of code to write the stream to the channel:
ChannelFuture future = channel.write(request, remoteInetSocketAddress);
future.awaitUninterruptibly(timeout);
if(!future.isDone()){
//abort logic
}
Everything works fine, but one thing: I'm unable to test the abort logic as I cannot make the write to fail - i.e. even if the server is down the future would be completed successfully. The write operation usually takes about 1 ms so setting very little timeout doesn't help too much.
I know the preffered way would be to use an asynch model instead of await() call, however for my scenario I need it to be synchronous and I need to be sure it get finnished at some point.
Does anyone know how could I simulate an uncompleted future?
Many thanks in advance!
MM
Depending on how your code is written you could use a mock framework such as mockito. If that is not possible, you can also use a "connected" UDP socket, i.e. a datagram socket that is bound to a local address. If you send to a bogus server you should get PortunreachableException or something similar.
Netty has a class FailedFuture that can be used for the purpose of this,
You can for example mock your class with tests that simulate the following:
ChannelFuture future;
if(ALWAYS_FAIL) {
future = channel.newFailedFuture(new Exception("I failed"));
else
future = channel.write(request, remoteInetSocketAddress);

Rest and ZF session management

I'm trying to create a web service which utilizes Zend framework. The API is REST based and uses Zend_Rest_Controller as base class. I wish to have user management and session, and for that I'm using the following code:
Login (POST)
// user id and password fetched first
$users = new Application_Model_DbTable_UserInfo();
$auth = Zend_Auth::getInstance();
$authAdapter = new Zend_Auth_Adapter_DbTable($users->getAdapter(),'users');
$authAdapter->setIdentityColumn('userid')
->setCredentialColumn('password');
$authAdapter->setIdentity($userid)
->setCredential($pwd);
$result = $auth->authenticate($authAdapter);
if($result->isValid()){
Zend_Session::rememberMe(604800);
$storage = new Zend_Auth_Storage_Session();
$usa = $authAdapter->getResultRowObject();
$auth->getStorage()->write($usa);
$authSession = new Zend_Session_Namespace('Zend_Auth');
$authSession->setExpirationSeconds(60*60);
}
and when accessing the service with e.g. some GET method I wish to check that there is a valid session with the following code:
$auth = Zend_Auth::getInstance();
if(!$auth->hasIdentity())
{
// error handling etc.
}
I never get an identity, hence the service doesn't work.
I have followed the guidance for ZF authentication quite strictly, but does the REST stuff need additional items to be taken into account?
I know I'm not answering your question, but if you are REALLY planning to implement a true REST interface (which implies it's going to enable you to scale well), you'd probably better forget about sessions and using Zend_Auth in the way you've depicted above.
Take a look here, where something about REST interfaces and authentication has been discussed already:
Can you help me understand this? "Common REST Mistakes: Sessions are irrelevant"
In short, quoting from the Q/A thread above, "To be RESTful, each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP". I really feel like seconding that.

Identify WCF clients that do not dispose properly

we have a WCF service hosted inside IIS. Now there are loads of different client applications calling this service. WS-SecureConversion is used.
Now, the service diagnostic log shows warnings that security sessions are being aborted. Most likely this is because of clients that do not properly close the session.
More info: the problem were "pending" security sessions. Those are sessions that were never used, only opened. This is pretty annoying as you can have a maximum of 128 such pending sessions before your services starts barfing 500s.
This can be easily reproduced (see answer below). I was able to query 128 SessionInitiationMessageHandlers using WinDbg. So this might be a good measure to identify this scenario.
Still, a way to identify those "misbehaving" clients would be useful.
Regards,
Alex
Since client and server share nothing but messages going between them, there's not much you can really do.
On the server side, you could look at some bits of information being sent from the client - check out the OperationContext.Current property in your service method - see the MSDN documentation on OperationContext about details what exactly is provided.
So you might be able to log certain information to identify the "offending" clients.
Marc
Sweet....the best way to kill a WCF service with a secure conversion seems to be to do nothing.
ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
var client = new MyClient();
client.ClientCredentials.UserName.UserName = "user";
client.ClientCredentials.UserName.Password = "password";
while(true)
{
Console.WriteLine("OPEN");
var c = client.ChannelFactory.CreateChannel();
((ICommunicationObject)c).Open();
// If I comment the following line, the service throws a
// "Too busy, too many pending sessions" 500.
var request = new MyRequest { };
c.Do(request);
// Of course I did *not* comment this line
((ICommunicationObject)c).Close();
}
Meanwhile, this bug has been confirmed by MS but still remains in .NET 4.x even if MS says otherwise:
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=499859