Find server details when connection lost with client - wcf

I have a code to access multiple wcf server from one client with multiple instances. if any connection lost between this, having faulted/closed event trigger function to hande this.
((ICommunicationObject)notificationProviderClient).Faulted += new EventHandler(myHost_Faulted);
((ICommunicationObject)notificationProviderClient).Closed += new EventHandler(myHost_Closed);
void myHost_Faulted(object sender, EventArgs e)
{
}
void myHost_Closed(object sender, EventArgs e)
{
}
The above function get called, if any connection get fault/closed.
In this scenarion how to find which wcf server connection lost with the clent? is there any possible to find this or we have to go for another method to handle this?

to find remote address of server during connection lost, use this on client side
this.notificationProviderClient.InnerDuplexChannel.Faulted += new EventHandler(myHost_Faulted);
void myHost_Faulted(object sender, EventArgs e) {
IContextChannel channel = sender as IContextChannel;
if (channel != null)
{
var remoteAddrs = a1.RemoteAddress;
}
}

Related

RS-232 erratic behavior

Windows 10-64.
I coded a small VB application last fall, to drive a "PR-705" serial device from the RS-232 port.
It worked flawlessly. Now, whenever I fire that code, the PR-705 is not responding so nicely?
I originally used a FTDI-based USB to RS232 adapter (Thunderlinx 1000) which worked perfect. I figured, the problem might have to do with the "driver"? So I added a PCI-Express serial port card from StarTech to my PC. The result: no improvement - same erratic behavior? Out of curiosity, this morning, I fired my trusty Windows HyperTerminal and it worked flawlessly (out of the PCI-e port)! So I know the trouble does not come from the device itself (sigh!) but somewhere in the chain of communications.
The problem I run into is as follows (hopefully, you can detect a "pattern"):
a) Open the serial port
b) Send a command to the port, in an ASCII string (e.g. "M1")
<- Device responds by sending data back
In order to obtain ALL data from device, however, I have to send additional commands:
c) "D2"
d) "D3"
e) "D4"
f) "D5"
When I run these commands from HyperTerminal, I get stellar behavior.
In my application, however, the additional commands ("D2", "D3", "D4" and "D5") are not getting THROUGH to the device, somehow? When I send "D2", for example, I get "XYZ" data back, which is OK.
But when I follow-up with "D3", I still get the same "XYZ" data back?
It is as though the new command ("D3") never reached the device?
My (ugly) workaround is to resend the same command over and THEN I get the new data (most of the time).
Here is some of my code:
Dim myPort As New IO.Ports.SerialPort("COM2") With {
.BaudRate = 9600,
.DataBits = 8,
.StopBits = IO.Ports.StopBits.One,
.Parity = IO.Ports.Parity.None,
.Handshake = IO.Ports.Handshake.RequestToSend,
.RtsEnable = True,
.DtrEnable = True,
.ReadTimeout = 1000000,
.WriteTimeout = 10000
}
myPort.Open()
myPort.WriteLine("M1")
myPort.WriteLine("D2")
Incoming = myPort.ReadLine()
myPort.WriteLine("D2")
Incoming = myPort.ReadLine()
myPort.WriteLine("D3")
Incoming = myPort.ReadLine()
myPort.WriteLine("D4")
Incoming = myPort.ReadLine()
myPort.WriteLine("D5")
Incoming = myPort.ReadLine()
I know the TimeOut value is "extreme" but the device can take up to 15 minutes to reply, depending on the circumstances. I can't close the port before the device responds back otherwise I'll get an error, something to do with CTS, and then device automatically reboots -- not ideal. I'm not a RS-232 expert but I do the best I can with the little knowledge I have.
Found a partial answer to my serial port problem but this solution is not without its own problems. I found some c# code I adapted where the serial port "Received" is separated into its own "event". This works very well. As you'll see in the code below, it does the job. But now I'm facing the question of how to go about "successively" polling the port to get all the data returned by the instrument?
Here's the c# code first:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
namespace WindowsApplication14
{
public partial class Form1 : Form
{
string Operation, MesureM1, MesureD2, MesureD3, MesureD4;
SerialPort _serialPort;
// delegate is used to write to a UI control from a non-UI thread
private delegate void SetTextDeleg(string text);
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
try
{
if (!_serialPort.IsOpen)
_serialPort.Open();
_serialPort.Write("PR705\r\n");
}
catch (Exception ex)
{
MessageBox.Show("Error opening serial port :: " + ex.Message, "Error!");
}
}
private void Form1_Load(object sender, EventArgs e)
{
_serialPort = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
_serialPort.Handshake = Handshake.RequestToSend;
_serialPort.RtsEnable = true;
_serialPort.DtrEnable = true;
_serialPort.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
_serialPort.Open();
_serialPort.Write("PR705\r\n");
}
private void btnM1_Click(object sender, EventArgs e)
{
Operation = "M1";
_serialPort.Write("M1\r\n"); // 0000,111,3.896e+002,0.3371,0.3563
Thread.Sleep(500);
}
private void btnD2_Click(object sender, EventArgs e)
{
Operation = "D2";
_serialPort.Write("D2\r\n");
Thread.Sleep(500);
}
private void btnD3_Click(object sender, EventArgs e)
{
Operation = "D3";
_serialPort.Write("D3\r\n");
Thread.Sleep(500);
}
private void btnD4_Click(object sender, EventArgs e)
{
Operation = "D4";
_serialPort.Write("D4\r\n");
Thread.Sleep(500);
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
string data = _serialPort.ReadLine();
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
}
private void si_DataReceived(string data)
{
String Result = data.Trim();
textBox1.Text = Result;
switch (Operation)
{
case "M1":
MesureM1= Result; // MesureBase = "0000,111,3.884e+002,0.3377,0.3570"
break;
case "D2":
MesureD2 = Result; // MesureD2 = "0000,111,3.674e+002,3.884e+002,3.322e+002"
break;
case "D3":
MesureD3 = Result; // MesureD3 = "0000,111,3.884e+002,0.2044,0.4862"
break;
case "D4":
MesureD4 = Result; //
break;
default:
break;
}
}
}
}
In my main form, I have four buttons and a textbox.
Button M1 is used to take a measurement (send "M1" command to the instrument).
Buttons D2, D3 and D4 are used to retrieve data from the instrument.
In my old VB application, I used code like this, to successively retrieve data from the instrument:
myPort.WriteLine("M1")
myPort.WriteLine("D2")
Incoming = myPort.ReadLine()
myPort.WriteLine("D3")
Incoming = myPort.ReadLine()
myPort.WriteLine("D4")
Incoming = myPort.ReadLine()
That was but I don't know how to accomplish the same thing using the 'separate' approach in c#? I tried lumping the read operations in the same "event" sub as the M1 button, like this :
private void btnM1_Click(object sender, EventArgs e)
{
Operation = "M1";
_serialPort.Write("M1\r\n"); // 0000,111,3.896e+002,0.3371,0.3563
Thread.Sleep(500);
Operation = "D2";
_serialPort.Write("D2\r\n");
Thread.Sleep(500);
Operation = "D3";
_serialPort.Write("D3\r\n");
Thread.Sleep(500);
Operation = "D4";
_serialPort.Write("D4\r\n");
Thread.Sleep(500);
}
But it does not work, I only get the "last" serial port "Read", the D4. The code never goes through D2 and D3.
How would you suggest I go about this? I have not shown you D5 yet… The D5 operation is the most involved as I have to do "two reads", one for one piece of data and then 201 successive reads, to retrieve wavelength data, like this :
myPort.WriteLine("D5")
Incoming = myPort.ReadLine()
Temp = Split(Incoming, ",")
PeakWL = Convert.ToDouble(Temp(2))
For i = 1 To 201
Incoming = myPort.ReadLine()
Temp = Split(Incoming, ",")
nmValue(i) = CDbl(Temp(0))
SpectralValue(i) = CDbl(Temp(1))
Next
I'm going to try to solve my problem myself but I would appreciate suggestions.

SqlDependency not firing

I am trying SqlDepenedency for the first time. I am not getting any notifications on Database Update.
I am placing breakpoints inside :
OnChange(object sender, SqlNotificationEventArgs e),
but it never gets hit.
Here is my code :
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "Cache Refresh: " + DateTime.Now.ToLongTimeString();
DateTime.Now.ToLongTimeString();
// Create a dependency connection to the database.
SqlDependency.Start(GetConnectionString());
using (SqlConnection connection = new SqlConnection(GetConnectionString()))
{
using (SqlCommand command = new SqlCommand(GetSQL(), connection))
{
SqlDependency dependency =
new SqlDependency(command);
// Refresh the cache after the number of minutes
// listed below if a change does not occur.
// This value could be stored in a configuration file.
connection.Open();
dgHomeRequests.DataSource = command.ExecuteReader();
dgHomeRequests.DataBind();
}
}
}
private string GetConnectionString()
{
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
//return "Data Source=(local);Integrated Security=true;" +"Initial Catalog=AdventureWorks;";
return ConfigurationManager.ConnectionStrings["TestData"].ConnectionString;
}
private string GetSQL()
{
return "Select [Address] From [UserAccount1]";
}
void OnChange(object sender, SqlNotificationEventArgs e)
{
// have breakpoint here:
SqlDependency dependency = sender as SqlDependency;
// Notices are only a one shot deal
// so remove the existing one so a new
// one can be added
dependency.OnChange -= OnChange;
// Fire the event
/* if (OnNewMessage != null)
{
OnNewMessage();
}*/
}
I have also placed some code in Global.asax file :
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
SqlDependency.Start(ConfigurationManager.ConnectionStrings["TestData"].ConnectionString);
}
protected void Application_End()
{
// Shut down SignalR Dependencies
SqlDependency.Stop(ConfigurationManager.ConnectionStrings["TestData"].ConnectionString);
}
}
The SQL server is on local machine. I am running the code through Visual Studio(IIS Express).
To enable service broker on database:
ALTER DATABASE SET ENABLE_BROKER
GO
To subscribe query notification, we need to give permission to IIS service account
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO “<serviceAccount>”
I guessed the 2nd point is not needed as it is local. But I tried giving it some permissions. Don't know if they are right as I don't think it is using app pool.And don't need the permission on local env. if I am the user myself and created the schema myself.
One of the questions that I saw was granting :
alter authorization on database::<dbName> to [sa];
I gave that permission too.
I was missing :
dependency.OnChange += new OnChangeEventHandler(OnChange);
The new code would look like :
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(OnChange);
now I can fire
void OnChange(object sender, SqlNotificationEventArgs e)

UCMA 3.0 - Recording an incoming call

I am new to UCMA and I am learning as I go through examples. I am trying to build 2 Lync clients A and B with the scenario as follows,
A calls B
B answers
A plays audio
B records it using Recorder.
I am stuck at trying to record the call at B. For B its an incoming call. I need to attach the audiovideoflow to the recorder, but I am not sure on how to do it. I will appreciate any help.
Apologies on the unformatted code, I am not sure how to format it properly, I tried.
Thanks.
Kris
Client B Code:
Accepts an incoming call
Records the media received in the incoming call. ***This is the part I have trouble
using System;
using System.Threading;
using Microsoft.Rtc.Collaboration;
using Microsoft.Rtc.Collaboration.AudioVideo;
using Microsoft.Rtc.Signaling;
using Microsoft.Rtc.Collaboration.Lync;
namespace Microsoft.Rtc.Collaboration.LyncUAS
{
public class LyncUAS
{
#region Locals
private LyncUASConfigurationHelper _helper;
private UserEndpoint _userEndpoint;
private AudioVideoCall _audioVideoCall;
private AudioVideoFlow _audioVideoFlow;
private Conversation _incomingConversation;
//Wait handles are only present to keep things synchronous and easy to read.
private AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
private EventHandler<AudioVideoFlowConfigurationRequestedEventArgs> _audioVideoFlowConfigurationRequestedEventHandler;
private EventHandler<MediaFlowStateChangedEventArgs> _audioVideoFlowStateChangedEventHandler;
private AutoResetEvent _waitForAudioVideoCallEstablishCompleted = new AutoResetEvent(false);
private AutoResetEvent _waitForAudioVideoFlowStateChangedToActiveCompleted = new AutoResetEvent(false);
private AutoResetEvent _waitForPrepareSourceCompleted = new AutoResetEvent(false);
#endregion
#region Methods
/// <summary>
/// Instantiate and run the DeclineIncomingCall quickstart.
/// </summary>
/// <param name="args">unused</param>
public static void Main(string[] args)
{
LyncUAS lyncUAS = new LyncUAS();
lyncUAS.Run();
}
private void Run()
{
string filename = "received.wma";
_helper = new LyncUASConfigurationHelper();
// Create a user endpoint, using the network credential object
// defined above.
_userEndpoint = _helper.CreateEstablishedUserEndpoint("Lync UAS" /*endpointFriendlyName*/);
_userEndpoint.RegisterForIncomingCall<AudioVideoCall>(On_AudioVideoCall_Received);
Console.WriteLine("Waiting for incoming call...");
_autoResetEvent.WaitOne();
Console.WriteLine("came after call is connected");
//start recording for audio.
Recorder recorder = new Recorder();
recorder.StateChanged += new EventHandler<RecorderStateChangedEventArgs>(recorder_StateChanged);
recorder.VoiceActivityChanged += new EventHandler<VoiceActivityChangedEventArgs>(recorder_VoiceActivityChanged);
//**********This is the issue, currently _audioVideoFlow is null, it is not attached to the flow
//So this will fail, how to attach _audioVideoFlow to an incoming call ?? HELP !!!
// recorder.AttachFlow(_audioVideoFlow); ------------> HELP!
WmaFileSink sink = new WmaFileSink(filename);
recorder.SetSink(sink);
recorder.Start();
Console.WriteLine("Started Recording ...");
_autoResetEvent.WaitOne();
recorder.Stop();
Console.WriteLine("Stopped Recording ...");
recorder.DetachFlow();
Console.WriteLine("Exiting");
Thread.Sleep(2000);
}
private void audioVideoFlow_StateChanged(object sender, MediaFlowStateChangedEventArgs e)
{
Console.WriteLine("Flow state changed from " + e.PreviousState + " to " + e.State);
//When flow is active, media operations can begin
if (e.State == MediaFlowState.Active)
{
// Flow-related media operations normally begin here.
_waitForAudioVideoFlowStateChangedToActiveCompleted.Set();
}
// call sample event handler
if (_audioVideoFlowStateChangedEventHandler != null)
{
_audioVideoFlowStateChangedEventHandler(sender, e);
}
}
void recorder_VoiceActivityChanged(object sender, VoiceActivityChangedEventArgs e)
{
Console.WriteLine("Recorder detected " + (e.IsVoice ? "voice" : "silence") + " at " + e.TimeStamp);
}
void recorder_StateChanged(object sender, RecorderStateChangedEventArgs e)
{
Console.WriteLine("Recorder state changed from " + e.PreviousState + " to " + e.State);
}
void On_AudioVideoCall_Received(object sender, CallReceivedEventArgs<AudioVideoCall> e)
{
//Type checking was done by the platform; no risk of this being any
// type other than the type expected.
_audioVideoCall = e.Call;
// Call: StateChanged: Only hooked up for logging, to show the call
// state transitions.
_audioVideoCall.StateChanged += new
EventHandler<CallStateChangedEventArgs>(_audioVideoCall_StateChanged);
_incomingConversation = new Conversation(_userEndpoint);
Console.WriteLine("Call Received! From: " + e.RemoteParticipant.Uri + " Toast is: " +e.ToastMessage.Message);
_audioVideoCall.BeginAccept(
ar =>
{
try {
_audioVideoCall.EndAccept(ar);
Console.WriteLine("Call must be connected at this point. "+_audioVideoCall.State);
_autoResetEvent.Set();
} catch (RealTimeException ex) { Console.WriteLine(ex); }
}, null);
}
//Just to record the state transitions in the console.
void _audioVideoCall_StateChanged(object sender, CallStateChangedEventArgs e)
{
Console.WriteLine("Call has changed state. The previous call state was: " + e.PreviousState +
" and the current state is: " + e.State);
if (e.State == CallState.Terminated)
{
Console.WriteLine("Shutting down");
_autoResetEvent.Set();
_helper.ShutdownPlatform();
}
}
#endregion
}
}
I think I have figured out what's not quite right here.
Your Code
// Create a user endpoint, using the network credential object
// defined above.
_userEndpoint = _helper.CreateEstablishedUserEndpoint("Lync UAS" /*endpointFriendlyName*/);
_userEndpoint.RegisterForIncomingCall<AudioVideoCall>(On_AudioVideoCall_Received);
Console.WriteLine("Waiting for incoming call...");
_autoResetEvent.WaitOne();
Console.WriteLine("came after call is connected");
//start recording for audio.
Recorder recorder = new Recorder();
recorder.StateChanged += new EventHandler<RecorderStateChangedEventArgs>(recorder_StateChanged);
recorder.VoiceActivityChanged += new EventHandler<VoiceActivityChangedEventArgs>(recorder_VoiceActivityChanged);
//**********This is the issue, currently _audioVideoFlow is null, it is not attached to the flow //So this will fail, how to attach _audioVideoFlow to an incoming call ?? HELP !!!
// recorder.AttachFlow(_audioVideoFlow); ------------> HELP!
Looking good so far. I'm assuming you're establishing and such in your CreateEstablishedUserEndpoint method, but I'm not seeing where you're getting the value for _audioVideoFlow.
I'm guessing you might be doing it elsewhere, but on the off chance that's actually where you're running into problems, here's that bit:
Simplest pattern to get AVFlow
public static void RegisterForIncomingCall(LocalEndpoint localEndpoint)
{
localEndpoint.RegisterForIncomingCall
<AudioVideoCall>(IncomingCallDelegate);
}
private static void IncomingCallDelegate(object sender, CallReceivedEventArgs<AudioVideoCall> e)
{
e.Call.AudioVideoFlowConfigurationRequested += IncomingCallOnAudioVideoFlowConfigurationRequested;
}
private static void IncomingCallOnAudioVideoFlowConfigurationRequested(object sender, AudioVideoFlowConfigurationRequestedEventArgs e)
{
AudioVideoFlow audioVideoFlow = e.Flow; // <--- There's your flow, gentleman.
}
Now, instead of registering for your incoming call, just call RegisterForIncomingCall(_userEndpoint);.
Your AVFlow will be hanging off e.Flow above, you could then pass that into your recorder: recorder.AttachFlow(e.Flow) or simply assign the flow to a field in your class and autoResetEvent.WaitOne(); and set that up where you're setting that up now.
Obviously this is a pretty naive implementation. A lot can go wrong in those few lines of code (exception handling/static event handler memory leak comes immediately to mind); don't forget to wire up events related to status changes on the conversation/call and endpoints, as well as any of the recovery related items.

WCF - How to delay task for specified amount of time?

I have WCF WebService for Silverlight client.
Let's say client click "Make building".
Service will receive new task, and star counting time, until it's ready to make action (i.e add to database).
Time - how much time task will need to complete (i.e to construct building).
The point is how to delay task for the certain amount of time.
Also, is there a way to stream time from server to client ?
I have setup this:
[OperationContract]
public void GetTime()
{
foreach (IDuplexClient client in _clientDic.Values)
{
client.ShowStatus(DateTime.Now);
}
}
[OperationContract]
public void Login()
{
string clientID = OperationContext.Current.Channel.SessionId;
IDuplexClient client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
_clientDic.Add(clientID, client);
}
IDuplexClient:
[OperationContract(IsOneWay = true)]
void ShowStatus(DateTime status);
And client side:
_client.LoginAsync();
_client.GetTimeAsync();
_client.ShowStatusReceived += new EventHandler<ShowStatusReceivedEventArgs>(_client_ShowStatusReceived);
void _client_ShowStatusReceived(object sender, ShowStatusReceivedEventArgs e)
{
label1.Content = e.status.ToString();
}
It's working.. For first run. But time doesn't get refreshed, which is not what I want.
As well, after few forced refresh in browser, time stop to show at all.
public partial class MainPage : UserControl
{
Service1Client _client;
int time = 10000;
public MainPage()
{
InitializeComponent();
_client = new Service1Client(new PollingDuplexHttpBinding { DuplexMode = PollingDuplexMode.SingleMessagePerPoll, OpenTimeout = TimeSpan.FromMinutes(10), ReceiveTimeout = TimeSpan.FromMinutes(10) },
new EndpointAddress("http://localhost:44544/Service1.svc"));
_client.LoginAsync();
_client.DoWorkCompleted += new EventHandler<DoWorkCompletedEventArgs>(_client_DoWorkCompleted);
_client.DoWorkAsync();
_client.AddNewTaskAsync("testTaskzor", time);
_client.GetTimeAsync();
//_client.AddNewTaskCompleted += new EventHandler<AddNewTaskCompletedEventArgs>(_client_AddNewTaskCompleted);
_client.ShowStatusReceived += new EventHandler<ShowStatusReceivedEventArgs>(_client_ShowStatusReceived);
}
void _client_ShowStatusReceived(object sender, ShowStatusReceivedEventArgs e)
{
label1.Content = e.status.ToString();
}
void _client_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
{
//label1.Content = e.Result;
}
}
That' entire client code.
Although I finally fixed and time is streaming properly to client (it wa surpsingly easy it was enough to enlose foreach with while(true) statment, at least for now).
But on other side. When I close browser, and open it again, nothing show up. As well as after I refresh it, time do not show up at all.
The easiest way would be to implement the delay on the client side. You can't really delay a RESTful service like WCF without breaking the model.

DOTMsn is not firing the SingedIn event

I have just started building a app using “XihSolutions.DotMSN.dll” version: 2.0.0.40909,
My problem is that it is not firing the “Nameserver_SignedIn” event. Not sure if I am doing something wrong.
your help will be really helpful.
void Nameserver_SignedIn(object sender, EventArgs e)
{
throw new Exception("User Signed In");
}
private string message = string.Empty;
void NameserverProcessor_ConnectionEstablished(object sender, EventArgs e)
{
message = "Connected";
SetMessage();
}
void SetMessage()
{
if (tbMessage.InvokeRequired)
tbMessage. Invoke(new ThreadStart(SetMessage));
else
tbMessage.Text += Environment.NewLine+ message;
}
private void btnSingIn_Click(object sender, EventArgs e)
{
if (messenger.Connected)
{
// SetStatus("Disconnecting from server");
messenger.Disconnect();
}
// set the credentials, this is ofcourse something every DotMSN program will need to
// implement.
messenger.Credentials.Account = tbUserName.Text;
messenger.Credentials.Password = tbPwd.Text;
// inform the user what is happening and try to connecto to the messenger network.
//SetStatus("Connecting to server");
messenger.Connect();
}
You might use MSNPSharp instead - DotMSN is old and may not support the current MSN protocol. There link is here:
http://code.google.com/p/msnp-sharp/