Pulling Information from 'Server' via WCF - c#

I have two WinForms applications: a 'server' and a 'client'. On the server
private ServiceHost host;
private const string serviceEnd = "Done";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
List<string> sqlList = new List<string>();
foreach (string line in this.richTextBoxSql.Lines)
sqlList.Add(line);
SqlInfo sqlInfo = new SqlInfo(sqlList);
host = new ServiceHost(
typeof(SqlInfo),
new Uri[] { new Uri("net.pipe://localhost") });
host.AddServiceEndpoint(typeof(ISqlListing),
new NetNamedPipeBinding(),
serviceEnd);
host.Open();
}
Where
public class SqlInfo : ISqlListing
{
public SqlInfo() {}
private List<string> sqlList;
public SqlInfo(List<string> sqlList) : this()
{
this.sqlList = sqlList;
}
public List<string> PullSql()
{
return sqlList;
}
}
[ServiceContract]
public interface ISqlListing
{
[OperationContract]
List<string> PullSql();
}
On the client I have
private ISqlListing pipeProxy { get; set; }
private const string serviceEnd = "Done";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
List<string> l = pipeProxy.PullSql();
string s = String.Empty;
foreach (string str in l)
s += str + " ";
this.richTextBoxSql.AppendText(s.ToString());
}
private void Form1_Load(object sender, EventArgs e)
{
ChannelFactory<ISqlListing> pipeFactory =
new ChannelFactory<ISqlListing>(
new NetNamedPipeBinding(),
new EndpointAddress(
String.Format("net.pipe://localhost/{0}", serviceEnd)));
pipeProxy = pipeFactory.CreateChannel();
}
The problem is, that when I 'pull' the List<string> from the server using pipeProxy.PullSql() it is calling the public SqlInfo() {} default constructor and setting the sqlList = null.
How do I get this code to return the text in the RichTextBox on the server app?

This is because you are using this kind of service host:
host = new ServiceHost(
typeof(SqlInfo),
new Uri[] { new Uri("net.pipe://localhost") });
you are passing a type and the WCF framework guess it have to create an instance of type SqlInfo to handle the request. Try to pass a reference to your constructed SqlInfo instance, ie sqlInfo in your case.
Use this overload of ServiceHost, it allow tyou to pass the instance directly:
host = new ServiceHost(
sqlInfo,
new Uri[] { new Uri("net.pipe://localhost") });

Related

Connecting to Websocket on shared hosting when port is blocked

I built a program in c# (asp.net) that connects to wss://stream.binance.com:9443/ws using WebSocket4Net, and gets ticker data which is public.
My application runs fine on localhost, but on my hosting provider I get an error "An attempt was made to access a socket in a way forbidden by its access permissions" which is an issue of blocked port if I understand correctly.
My hosting provider allows me to enable specific ports for specific ip addresses, but in this case I don't have the ip address for the remote host wss://stream.binance.com:9443/ws
Is there a way to find out the ip address of the remote host when connection is open or when a message is received?
My code:
using System.Collections.Generic;
using Newtonsoft.Json;
using WebSocket4Net;
public static class BinanceWShandler
{
static WebSocket ws;
internal static bool isOpen { get; private set; }
public static void Start()
{
ws = new WebSocket("wss://stream.binance.com:9443/ws");
ws.Opened += Ws_Opened;
ws.Closed += Ws_Closed;
ws.Error += Ws_Error;
ws.MessageReceived += Ws_MessageReceived;
ws.EnableAutoSendPing = true;
ws.Open();
}
private static void Ws_Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
{
}
private static void Ws_Closed(object sender, EventArgs e)
{
}
private static void Ws_Opened(object sender, EventArgs e)
{
Request_Individual_Ticker obj = new Request_Individual_Ticker();
obj.method = "SUBSCRIBE";
List<string> pars = new List<string>();
pars.Add("!bookTicker");
obj.#params = pars;
obj.id = 1;
string JSONstring = JsonConvert.SerializeObject(obj);
ws.Send(JSONstring);
isOpen = true;
}
private static void Ws_MessageReceived(object sender, MessageReceivedEventArgs e)
{
SignalRChat.Hubs.ChatHub.instance.SendBinanceWS(e.Message);
}
public class Request_Individual_Ticker
{
public string method { get; set; }
public List<string> #params { get; set; }
public int id { get; set; }
}
}

Update a control in the UI from a different thread

I have a M2MQTT client subscribed to a topic in the DashboardViewModel class. On message receive, the UI gets updated by calling Writelog.
public class DashboardViewModel : Object, IDashboardViewModel
{
private IDashboardView View { get; }
public DashboardViewModel(IDashboardView view)
{
View = view;
mqttClient = new MqttClient("localhost");
mqttClientId = Guid.NewGuid().ToString();
mqttClient.MqttMsgPublishReceived += mqttClient_MsgPublishReceived;
mqttClient.Subscribe(new string[] { "Home/Temperature" }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
mqttClient.Connect(mqttClientId);
//...
}
private void mqttClient_MsgPublishReceived(object sender, MqttMsgPublishEventArgs eventArgs)
{
string message = Encoding.UTF8.GetString(eventArgs.Message);
View.Writelog(message);
}
}
The textbox on FrmMain does not update; tbxLogs.InvokeRequired always returns false, i.e. tbxLogs.AppendText always executes. Any suggestions please?
public partial class FrmMain : Form, IDashboardView
{
private IDashboardViewModel dashboardViewModel = null;
private delegate void WriteLogCallback(string text);
public FrmMain()
{
InitializeComponent();
}
public void Writelog(string text)
{
if (tbxLogs.InvokeRequired)
{
WriteLogCallback callback = new WriteLogCallback(Writelog);
tbxLogs.Invoke(callback, new object[] { text });
}
else
{
tbxLogs.AppendText(text + "\n");
}
}
}
I think you need to use dispatcher :)
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action<String>(Writelog), message);
inside of this method
private void mqttClient_MsgPublishReceived(object sender, MqttMsgPublishEventArgs eventArgs)
{
string message = Encoding.UTF8.GetString(eventArgs.Message);
//here instead of View.Writelog(message);
}

Windows Phone 8.1 Currency converter Json

I got a school project. I have to make a currency converter and I got stuck. I found something on the Code Project web site, but I am new at this and I do not really know how to implement it in my project.
I tried something like `
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
class WebClient
{
internal string DownloadString(string url)
{
throw new NotImplementedException();
url = "https://openexchangerates.org/api/latest.json?app_id=ae11142304694b10a1dbf2d25933a333";
var currencyRates = _download_serialized_json_data<App9.CurrencyRates>(url);
}
}
public static T _download_serialized_json_data<T>(string url) where T : new()
{
var w = new WebClient();
{
//using (var w = new WebClient()) {
var json_data = string.Empty;
// attempt to download JSON data as a string
try
{
json_data = w.DownloadString(url);
}
catch (Exception) { }
// if string with JSON data is not empty, deserialize it to class and return its instance
return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
}
}
private void comboBoxTo_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void convertButton_Click(object sender, RoutedEventArgs e)
{
if (amountTb.Text == string.Empty)
{
afisareTb.Text = "Scrieti o valoare";
}
else
{
var currencyRates = _download_serialized_json_data<CurrencyRates>("https://openexchangerates.org/api/latest.json?app_id=YOUR_APP_ID ");
}
}
}
`
I do not have any errors, it is just that, when I press on converter button from my app, nothing happens.

WCF Basic WinForm App Communication Issue

All, I have extended this tutorial to get and reverse string displayed in two seperate WinForm applications. However, the end goal is to get this working between to WinForm apps that pass SQL between eachother. To facilitate this I have extended this example and the following is what I have
A library .dll containing
public class WcfInterface
{
private static WcfInterface instance;
private ServiceHost host;
private const string serviceEnd = "Done";
protected WcfInterface()
{
}
public static WcfInterface Instance()
{
if (instance == null)
instance = new WcfInterface();
return instance;
}
public void OpenServiceHost<T, U>()
{
host = new ServiceHost(typeof(U), new Uri[] { new Uri("net.pipe://localhost") });
host.AddServiceEndpoint(typeof(T), new NetNamedPipeBinding(), serviceEnd);
host.Open();
}
public void CloseServiceHost<T>()
{
host.Close();
}
public T AddListnerToServiceHost<T>()
{
ChannelFactory<T> pipeFactory =
new ChannelFactory<T>(new NetNamedPipeBinding(),
new EndpointAddress(String.Format("net.pipe://localhost/{0}",
serviceEnd)));
T pipeProxy = pipeFactory.CreateChannel();
return pipeProxy;
}
}
So on the 'server' form, I do
private void Form1_Load(object sender, EventArgs e)
{
List<string> sqlList = new List<string>();
foreach (string line in this.richTextBoxSql.Lines)
sqlList.Add(line);
SqlInfo sqlInfo = new SqlInfo(sqlList);
WcfInterface wcfInterface = WcfInterface.Instance();
wcfInterface.OpenServiceHost<ISqlListing, SqlInfo>();
}
Where
public class SqlInfo : ISqlListing
{
private List<string> sqlList;
public SqlInfo(List<string> sqlList)
{
this.sqlList = sqlList;
}
public List<string> PullSql()
{
return sqlList;
}
}
[ServiceContract]
public interface ISqlListing
{
[OperationContract]
List<string> PullSql();
}
In the client WinForm app
private ISqlListing pipeProxy;
public Form1()
{
InitializeComponent();
WcfInterface wcfInterface = WcfInterface.Instance();
pipeProxy = wcfInterface.AddListnerToServiceHost<ISqlListing>();
}
and on the click event I attampt to get the List<string> from the server
private void button1_Click(object sender, EventArgs e)
{
this.richTextBoxSql.Text = pipeProxy.PullSql().ToString(); // Code hangs here.
}
My question is what is wrong with this?
Thanks for your time.
Edit. I have now also changed the client code according to comments as follows
private ISqlListing pipeProxy { get; set; }
private const string serviceEnd = "Done";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.richTextBoxSql.Text = pipeProxy.PullSql().ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
ChannelFactory<ISqlListing> pipeFactory =
new ChannelFactory<ISqlListing>(
new NetNamedPipeBinding(),
new EndpointAddress(
String.Format("net.pipe://localhost/{0}", serviceEnd)));
pipeProxy = pipeFactory.CreateChannel();
}
this also hangs on the click event.
The way you have the code set up, you are creating a WCF server on the client by referencing WcfInterface.Instance. You are then calling it from the same thread that it is being served on, causing your application to lock up.
There are a number of ways to get around this. Here are a few that come to mind:
Get the service running in your first WinForm app, then use the "Add Service Reference" functionality in visual studio to create your proxies. Note that you'll have to
You can still reference a common library for the WCF contracts, but rework your code so that you're not creating an instance of the service in your "client" WinForms app.

C# - How to make this thread wait?

I have this:
public class ServiceLibrary
{
public object result = null;
private bool finished = false;
public void testar()
{
ServiceReference.Service1SoapClient serviceReference = new ServiceReference.Service1SoapClient();
serviceReference.updateUserCompleted += new EventHandler<ServiceReference.updateUserCompletedEventArgs>(serviceReference_updateUserCompleted);
serviceReference.updateUserAsync();
ManualResetEvent m = new ManualResetEvent(true);
}
void serviceReference_updateUserCompleted(object sender, ServiceReference.updateUserCompletedEventArgs e)
{
result = e.Result;
finished = true;
}
}
and outside I have this:
public Home()
{
InitializeComponent();
ServiceLibrary serviceLibrary = new ServiceLibrary();
serviceLibrary.testar();
lblCharName.Text = Convert.ToString(serviceLibrary.result);
}
What should I do to the thread wait, so when I assign the text, it contains the value, please?
Thank you
Could you not use your ManualResetEvent? or create a fresh one.
I believe the ManualResetEvent is thread safe....
public class ServiceLibrary
{
public object result = null;
private bool finished = false;
public ManualResetEvent m;
public void testar()
{
ServiceReference.Service1SoapClient serviceReference = new ServiceReference.Service1SoapClient();
serviceReference.updateUserCompleted += new EventHandler<ServiceReference.updateUserCompletedEventArgs>(serviceReference_updateUserCompleted);
serviceReference.updateUserAsync();
m = new ManualResetEvent(false);
}
void serviceReference_updateUserCompleted(object sender, ServiceReference.updateUserCompletedEventArgs e)
{
result = e.Result;
finished = true;
m.Set();
}
}
public Home()
{
InitializeComponent();
ServiceLibrary serviceLibrary = new ServiceLibrary();
serviceLibrary.testar();
serviceLibrary.m.WaitOne();
lblCharName.Text = Convert.ToString(serviceLibrary.result);
}
Make your ManualResetEvent variable m a member variable of the class.
and inside your threaded method: serviceReference_updateUserCompleted, make sure to call
m.WaitOne();
What about
public class ServiceLibrary
{
public object result = null;
public void testar()
{
var serviceReference = new ServiceReference.Service1SoapClient();
using(var m = new ManualResetEvent(false))
{
Action<object, ServiceReference.updateUserCompletedEventArgs> handler =
(sender, e) =>
{
result = e.Result;
m.Set();
};
serviceReference.updateUserCompleted += handler;
serviceReference.updateUserAsync();
m.WaitOne();
serviceReference.updateUserCompleted -= handler;
}
}
}
I have a similar situation. I use a technique called polling, which is exactly what it sounds like. It may or may not be appropriate for you depending on your situation.
public class ServiceLibrary
{
public object result = null;
private bool finished = false;
public void testar()
{
ServiceReference.Service1SoapClient serviceReference = new ServiceReference.Service1SoapClient();
serviceReference.updateUserCompleted += new EventHandler<ServiceReference.updateUserCompletedEventArgs>(serviceReference_updateUserCompleted);
serviceReference.updateUserAsync();
ManualResetEvent m = new ManualResetEvent(true);
while !finished
Thread.Sleep(100);
doStuffWithResult(result);
}
void serviceReference_updateUserCompleted(object sender, ServiceReference.updateUserCompletedEventArgs e)
{
result = e.Result;
finished = true;
}

Categories