I have application based on this tutorial
Method I use to test connection to server (in client app):
public class PBMBService : IService
{
private void btnPing_Click(object sender, EventArgs e)
{
ServiceClient service = new ServiceClient();
tbInfo.Text = service.Ping().Replace("\n", "\r\n");
service.Close();
}
//other methods
}
Service main function:
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8000/PBMB");
ServiceHost selfHost = new ServiceHost(typeof(PBMBService), baseAddress);
try
{
selfHost.AddServiceEndpoint(
typeof(IService),
new WSHttpBinding(),
"PBMBService");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
selfHost.Open();
Console.WriteLine("Serwis gotowy.");
Console.WriteLine("Naciśnij <ENTER> aby zamknąć serwis.");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("Nastąpił wyjątek: {0}", ce.Message);
selfHost.Abort();
}
}
}
Ping() function decaration
[ServiceContract(Namespace = "http://PBMB")]
public interface IService
{
[OperationContract]
string Ping();
}
Ping() function implementation
public class PBMBService : IService
{
SqlConnection sql = new SqlConnection(#"Data Source=.\SqlExpress;Initial Catalog=PBMB;Integrated Security=True");
SqlCommand cmd;
private void Message(string message)
{
Console.WriteLine(DateTime.Now + " -> " + message);
}
public string Ping()
{
Message("Ping()");
return "Metoda Ping() działa.";
}
}
How can I put caller's IP in Message method?
The original blog is available through the Wayback Machine. Note that you'll need to be using WCF 3.5 or later per the author's post.
The code from the article is below;
Service Contract
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace ClientInfoSample
{
[ServiceContract]
public interface IService
{
[OperationContract]
string GetData(string value);
}
}
Implementation with retrieving IP:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Channels;
namespace ClientInfoSample
{
public class MyService : IService
{
public string GetData(string value)
{
OperationContext context = OperationContext.Current;
MessageProperties messageProperties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpointProperty = messageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
return string.Format("Hello {0}! Your IP address is {1} and your port is {2}", value, endpointProperty.Address, endpointProperty.Port);
}
}
}
Are you looking for something like
HttpContext.Current.Request.UserHostAddress
Related
I am currently working on an asp.net Web API project. The project consists of the following files: "S3BucketController", "IS3Service", "S3Service". Basically, I am trying to call the AmazonS3 web service to create and retrieve data. To make my code cleaner, I reference on the following article on dependency injection
https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection
I am using the Unity.WebApi NuGet package (Unity 5.2.0 and Unity.WebApi 5.3.0) The issue I am facing is that when attempting to run the code, I get the error: Make sure that the controller has a parameterless public constructor. I've research similar issues in StackOverflow but still could not solve my issue.
Update I am still trying to solve this issue, any help is greatly appreciated
Below is my code:
S3BucketController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Task_7.Services;
namespace Task_7.Controllers
{
public class S3BucketController : ApiController
{
private readonly IS3Service _service;
// Initialize at constructor
// injected the IS3Service,
public S3BucketController(IS3Service service)
{
_service = service;
}
[HttpPost]
[Route("api/S3Bucket/CreateBucket")]
public async Task<IHttpActionResult> CreateBucket([FromBody] string bucketName)
{
var response = await _service.createBucketAsync(bucketName);
return Ok(response);
}
[HttpPost]
public async Task<IHttpActionResult> AddFile([FromBody] string bucketName)
{
await _service.createFileAsync(bucketName);
return Ok();
}
}
}
IS3Service
using System.Threading.Tasks;
using Task_7.Models;
namespace Task_7.Services
{
public interface IS3Service
{
Task<S3Response> createBucketAsync(string bucketName);
Task createFileAsync(string bucketName);
}
S3Service
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using Amazon.S3.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
using Task_7.Models;
namespace Task_7.Services
{
public class S3Service : IS3Service
{
private readonly IAmazonS3 _client;
public S3Service(IAmazonS3 client)
{
_client = client;
}
public async Task<S3Response> createBucketAsync(string bucketName)
{
try
{
if (await AmazonS3Util.DoesS3BucketExistAsync(_client, bucketName) == false)
{
var putBucketRequest = new PutBucketRequest
{
BucketName = bucketName,
UseClientRegion = true
};
var response = await _client.PutBucketAsync(putBucketRequest);
return new S3Response
{
Message = response.ResponseMetadata.RequestId,
Status = response.HttpStatusCode
};
}
}
catch (AmazonS3Exception e)
{
return new S3Response
{
Status = e.StatusCode,
Message = e.Message
};
}
catch (Exception e)
{
return new S3Response
{
Status = HttpStatusCode.InternalServerError,
Message = e.Message
};
}
return new S3Response
{
Status = HttpStatusCode.InternalServerError,
Message = "Something Went Wrong"
};
}
private const string filePath = "C:\\Users\\ randomguy1\\Desktop\\Project\\Background_Images";
public async Task createFileAsync(string bucketName)
{
try
{
var fileTransferUtility = new TransferUtility(_client);
await fileTransferUtility.UploadAsync(filePath, bucketName);
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
//https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-install-assemblies.html#net-dg-nuget
}
}
}
UnityResolver.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
using Unity;
using Unity.Exceptions;
namespace Task_7.Resolver
{
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
}
WebApiConfig.cs
using Amazon.S3;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using Task_7.Resolver;
using Task_7.Services;
using Unity;
using Unity.Lifetime;
namespace Task_7
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var container = new UnityContainer();
container.RegisterType<IS3Service, S3Service>(new HierarchicalLifetimeManager());
container.RegisterType<IAmazonS3>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
This question already exists:
SignalR Server Hosting Localhost
Closed 5 years ago.
I'm running a server with a localhost http://*:52080.
On the same computer, I'm run client and trying to connect to a local IP hub http://192.168.1.102:52080/signalr. Everything works well.
But if I run the client on another computer (from the same local network) and try to connect to http://192.168.1.102:52080/signalr, it does not connect. The client catches an exception ("System.AggregateException" in mscorlib.dll).
Port 52080 on the computer with the hub is open.
What could be the reason for the failure?
Server:
using System;
using Microsoft.Owin.Hosting;
public class Program
{
static void Main(string[] args)
{
string url = "http://*:52080";
using (WebApp.Start<Startup>(url))
{
Console.WriteLine("Server running at {0}\n", url);
Console.ReadLine();
}
}
}
Startup.cs
using Owin;
using Microsoft.Owin.Cors;
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
SGHub.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using System.Collections.Generic;
public class SGHub : Hub
{
public static List<string> Users = new List<string>();
public override Task OnConnected()
{
Console.WriteLine("\nOnConnected {0}", Context.ConnectionId);
Users.Add(Context.ConnectionId);
Clients.Caller.broadcastMessage("Server:", "Successful connection");
Clients.Others.broadcastMessage("Server:", "New connection");
return (base.OnConnected());
}
}
Client:
using System;
using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNet.SignalR.Client.Hubs;
using Newtonsoft.Json.Linq;
class Program
{
static void Main(string[] args)
{
string serverURL = "http://192.168.1.102:52080/signalr";
Console.WriteLine("Connection to {0}\n", serverURL);
HubConnection hubConnection = new HubConnection(serverURL);
IHubProxy myHubProxy = hubConnection.CreateHubProxy("StartGameHub");
myHubProxy.On<string, string>("Send", (name, message) => Console.Write("Recieved addMessage: " + name + ": " + message + "\n"));
myHubProxy.On("heartbeat", () => Console.Write("Recieved heartbeat \n"));
Subscription subscription = myHubProxy.Subscribe("broadcastMessage");
subscription.Received += SubscriptionData;
while (true)
{
string key = Console.ReadLine();
if (key.ToUpper() == "A")
{
try
{
Console.WriteLine("Start connect..");
hubConnection.Start().Wait();
}
catch (System.AggregateException e)
{
Console.WriteLine("Connected fauld :(");
}
}
}
}
private static void SubscriptionData(IList<JToken> obj)
{
Console.WriteLine(obj[1].ToString());
}
}
The problem wasn`t in the code and the implementation method, but in the banal glitch of the router, after it rebooted and rebooted all computers (just in case) everything worked.
I have a long-running WCF service hosted in a Windows service. I have a service library whose purpose is to report on the state of the service. How can I get to the instance of the service from inside an instance of the service library?
To illustrate, I created a service that records the time it started, and exposes a method to report how long it's been running. The service library needs to be able to call the service's ElapsedSeconds() method, so the the library needs a reference to the running service.
I thought I could use OperationContext.Current. Here's my service library class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
namespace TimerService
{
public class TimerServiceLib : ITimerServiceLib
{
TheTimerService m_timerService;
public TimerServiceLib()
{
var currentContext = OperationContext.Current;
var instanceContext = currentContext.InstanceContext;
m_timerService = (TheTimerService)instanceContext.GetServiceInstance();
}
public double SecondsSinceStart()
{
return m_timerService.ElapsedSeconds();
}
}
}
But the call to GetServiceInstance() creates a new instance of TimerServiceLib(), which of course gives me an infinite loop. So, what is the correct way to do this?
Here is my service class, actually being hosted in a console application:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace TimerService
{
public partial class TheTimerService : ServiceBase
{
private DateTime m_startTime;
ServiceHost m_svcHost;
public TheTimerService()
{
InitializeComponent();
Init();
m_startTime = DateTime.Now;
}
public double ElapsedSeconds()
{
return (DateTime.Now - m_startTime).TotalSeconds;
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
public void Init()
{
if (m_svcHost != null)
{
m_svcHost.Close();
}
string httpAddress = "http://localhost:1234/TimerService";
string tcpAddress = "net.tcp://localhost:1235/TimerService";
Uri[] adrbase = { new Uri(httpAddress), new Uri(tcpAddress) };
m_svcHost = new ServiceHost(typeof(TimerServiceLib), adrbase);
ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
m_svcHost.Description.Behaviors.Add(mBehave);
var debugBehavior = m_svcHost.Description.Behaviors.Find<ServiceDebugBehavior>();
debugBehavior.IncludeExceptionDetailInFaults = true;
BasicHttpBinding httpBinding = new BasicHttpBinding();
m_svcHost.AddServiceEndpoint(typeof(ITimerServiceLib), httpBinding, httpAddress);
m_svcHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
NetTcpBinding tcpBinding = new NetTcpBinding();
m_svcHost.AddServiceEndpoint(typeof(ITimerServiceLib), tcpBinding, tcpAddress);
m_svcHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
m_svcHost.Open();
// SimShopServiceLib.m_shop = new CSimShopManager();
}
}
}
You can do it this way:
First, modify your TimerServiceLib and do the constructor injection of TheTimerService:
public class TimerServiceLib : ITimerServiceLib
{
private readonly TheTimerService m_timerService;
public TimerServiceLib(TheTimerService theTimerService)
{
m_timerService = theTimerService;
}
public double SecondsSinceStart()
{
return m_timerService.ElapsedSeconds();
}
}
Then, in your Init() upon creation of ServiceHost, instantiate first your service and pass the TheTimerService. Since your are creating the ServiceHost inside your windows service, wich is TheTimerService you can pass this.
Uri[] adrbase = { new Uri(httpAddress), new Uri(tcpAddress) };
var timerServiceLib = new TimerServiceLib(this)
m_svcHost = new ServiceHost(timerServiceLib , adrbase);
For more details about passing object in you service see this link.
Disclaimer : The above code is not tested.
I'm new at .NET remoting and C#. I need a client/server application and want to handle this with .NET Remoting. I've wrote a class library for the remoting object, the EchoServer class, with some test methods.
The class library I've added to my server project in Visual Studio. The assembly "System.Runtime.Remoting" I've added, too.
The following is the code of my server:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using Remoting; //Namespace Lib
namespace Server
{
public partial class Server : Form
{
public Server()
{
InitializeComponent();
TcpChannel serverChannel = null;
try
{
serverChannel = new TcpChannel(9998);
lvStatus.Items.Add("Server is listening on port 8089...");
string strIn = "";
ChannelServices.RegisterChannel(serverChannel, true);
RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("Remoting.EchoServer, remoting_dll"), "Echo", WellKnownObjectMode.SingleCall);
}
catch (Exception ex)
{
ChannelServices.UnregisterChannel(serverChannel);
MessageBox.Show(ex.Message.ToString());
}
}
}
}
If I start the server, I will get an exception:
The value cannot be NULL
Parametername: type
I've tried some other code of a tutorial, but I will get the same excetion, equal if the class for the remoting object is implented as a class library or it is as a class directly in my project.
Can you post implementation of Remoting?
I thing that your mistake is next:
"Remoting.EchoServer, remoting_dll"
So, you should use Type.GetType correctly.
Example of working code:
static void Main(string[] args)
{
Server();
}
static void Server()
{
Console.WriteLine("Server started...");
var httpChannel = new HttpChannel(9998);
ChannelServices.RegisterChannel(httpChannel);
RemotingConfiguration.RegisterWellKnownServiceType(Type.GetType("Server.Program+SomeClass"), "SomeClass", WellKnownObjectMode.SingleCall);
Console.WriteLine("Press ENTER to quit");
Console.ReadLine();
}
public interface ISomeInterface
{
string GetString();
}
public class SomeClass : MarshalByRefObject, ISomeInterface
{
public string GetString()
{
const string tempString = "ServerString";
Console.WriteLine("Server string is sended: {0}", tempString);
return tempString;
}
}
In my client/server application, I want count other value in everyone client.
I made application using callbacks, but something is wrong. I get Exception, when I want call method pipeproxy.polacz(S); Which get value to server and write in server console now.
Exception is:
This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute.
Other problem is, how sum resault in this funkction from all clients.
example;
client 1: S = 1;
client 2: S = 2;
client 3: S = 3;
And this function take result from all clients and sum it. So server will write 6 in server console.
My application code:
server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Interface;
namespace WCFapp
{
class Program
{
static void Main(string[] args)
{
Klienci cust = new Klienci();
cust.Connect();
}
}
}
.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interface;
namespace WCFapp
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class Klienci : IMessage
{
private static List<ImessageCallback> subscribers =
new List<ImessageCallback>();
public void lista()
{
string nm = Console.ReadLine();
if (nm == "1")
{
Console.WriteLine("Number of conected clients: " + subscribers.Count());
funkcja();
}
}
public void Connect()
{
using (ServiceHost host = new ServiceHost(
typeof(Klienci), new Uri("net.tcp://localhost:8000")))
{
host.AddServiceEndpoint(typeof(IMessage),
new NetTcpBinding(), "ISubscribe");
try
{
host.Open();
lista();
Console.ReadLine();
host.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
public bool Subscribe()
{
try
{
ImessageCallback callback = OperationContext.Current.GetCallbackChannel<ImessageCallback>();
if (!subscribers.Contains(callback))
subscribers.Add(callback);
Console.WriteLine("Client is conected ({0}).", callback.GetHashCode());
return true;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
}
public bool Unsubscribe()
{
try
{
ImessageCallback callback = OperationContext.Current.GetCallbackChannel<ImessageCallback>();
if (subscribers.Contains(callback))
subscribers.Remove(callback);
Console.WriteLine("Client is unconected ({0}).", callback.GetHashCode());
return true;
}
catch
{
return false;
}
}
public void funkcja()
{
int a = 1; int b = 3;
subscribers.ForEach(delegate(ImessageCallback callback)
{
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
{
Console.WriteLine("a= {0} , b= {1}", a, b);
callback.klient_licz(a, b);
a++;
b++;
}
});
}
public void polacz(int S)
{
Console.WriteLine("Sum: {0}", S);
}
}
}
Interface:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace Interface
{
[ServiceContract(CallbackContract = typeof(ImessageCallback), SessionMode = SessionMode.Required)]
public interface IMessage
{
[OperationContract]
void funkcja();
[OperationContract]
void polacz(int S);
[OperationContract]
bool Subscribe();
[OperationContract]
bool Unsubscribe();
}
[ServiceContract]
public interface ImessageCallback
{
[OperationContract]
void klient_licz(int a, int b);
}
}
Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Interface;
namespace Client
{
class Program
{
static void Main(string[] args)
{
clients cl = new clients();
if (cl.Conect() == true)
{
string tmp = Console.ReadLine();
while (tmp != "EXIT")
{
cl.SendMessage(tmp);
tmp = Console.ReadLine();
}
}
cl.Close();
Environment.Exit(0);
}
}
}
.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Interface;
namespace Client
{
class clients : ImessageCallback, IDisposable
{
IMessage pipeProxy = null;
public bool Conect()
{
DuplexChannelFactory<IMessage> pipeFactory =
new DuplexChannelFactory<IMessage>(
new InstanceContext(this),
new NetTcpBinding(),
new EndpointAddress("net.tcp://localhost:8000/ISubscribe"));
try
{
pipeProxy = pipeFactory.CreateChannel();
pipeProxy.Subscribe();
return true;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
}
public void Close()
{
pipeProxy.Unsubscribe();
}
public void klient_licz(int a, int b)
{
int S = a + b;
Console.WriteLine("Sum= {0}", S);
pipeProxy.polacz(S); //ERROR
}
}
}
The issue here is that inside your callback method klient_licz (which is called by the server) you are making another server call. This is not allowed the way your contracts are currently setup.
Check you really need this behaviour. Do you really need to make a server call INSIDE a method on the callback interface (klient_licz).
If you do need this behaviour then you might be able to fix things by marking the klient_licz call OneWay on the callback interface. That will mean that server call to the callback will not block until the client returns (which is what is currently causing your issue because the server is waiting for the client call to return but the client call is waiting on a call to the server):
[ServiceContract]
public interface ImessageCallback {
[OperationContract(IsOneWay = true)]
void klient_licz(int a, int b);
}
Alternatively you could mark the callback implimentation with a concurrancy mode other than the default mode Single. Eg Reentrant as follows - but bear in mind that this means that calls to callback will not long be marshalled to the UI thead ie will be on threadpool threads so you would have to dispatch to update the UI from method on the callback interface:
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
class clients : ImessageCallback, IDisposable {
...
}
If you want to understand ConcurrencyMode and how it effects execution then you will really need to do someback ground reading as it does get a little complicated - but if you dont have that background it is difficult to really understand what is happen when you change the ConcurrencyMode. This dasBlonde blog post has a good summary of the different modes and behaviour - but you might want to start with some tutorials that are a bit more beginner orientated.