Get detail of who is invoking webservice in C# - c#

I have a simple webservice which returns a string of message as below:
[WebMethod]
public string GetData()
{
return "Here is your response";
}
So just to log details, is it possible to identify from which system the service has been invoked?

You can use HttpContext by:
string ip = System.Web.HttpContext.Current.Request.UserHostAddress;
And there is more usefull informations.

You can get the host address from the OperationContext.Current. The below code would do it.
RemoteEndpointMessageProperty endpoint = OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
string address = endpoint.Address;
This will work for both self hosted and IIS hosted services. The Address might give a IPV6 address when the network is configured with it. So you may need to resolve using Dns.GetHostEntry(address) to get the IPV4 address.

Related

Get user IP address using dns host not working on IIS

I am running an application that has to get the current user IP address, the functionality seems to be working when running the app from VS, however it breaks completely when deployed on IIS, here is the code to get the user IP
public static string GetUserIP()
{
string strHostName = "";
strHostName = System.Net.Dns.GetHostName();
IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(strHostName);
IPAddress[] addr = ipEntry.AddressList;
return ipEntry.AddressList.Last().ToString();
}
I have another method which uses the return value from the GetUserIP() method, here is the code
private void SaveSmsDetails(string cellNumber, string message, string userLogonName)
{
string[] userIP = IPAddressGetter.GetUserIP().Split('.');
}
Now this method is throwing a an index out of range exception, this means the GetUserIP method does not returning any value hence the Split method is falling apart, is there anything I need to do or change or perhaps something must be done on the IIS server.
Note: IIS version is 8.5.9
MSDN says: If the host name could not be found, the SocketException exception is returned with a value of 11001 (Windows Sockets error WSAHOST_NOT_FOUND). This exception can be returned if the DNS server does not respond. This exception can also be returned if the name is not an official host name or alias, or it cannot be found in the database(s) being queried.
Details here: Dns.GetHostEntry Method (String)
So, make sure that the known issues/scenarios are properly handled.
Further, try GetHostByName instead of GetHostEntry
source here

Use SignalR with IP Address instead of computer name

I have a SignalR service setup to run self hosted in a Windows Service.
When I enter this address:
http://mycomputer.mydomain.net:8789/signalr/signalr/negotiate
I get some xml (for negotiation) displayed in the browser (showing that hit the service correctly.)
But if I enter this address (that has mycomputer.mydomain.net's ip address in place of the computer name):
http://10.92.15.6:8789/signalr/signalr/negotiate
or this
http://localhost:8789/signalr/signalr/negotiate
I get this error:
Bad Request - Invalid Hostname
HTTP Error 400. The request hostname is invalid.
I have tried also using:
http://10.92.15.6.mydomain.net:8789/signalr/signalr/negotiate
But I just get:
This site can’t be reached
10.92.15.6.mydomain.net’s server DNS address could not be found.
Is there someway to be able to make SignalR work using an IP Address instead of the computer name?
I had to change my startup from this:
string url = "http://" + machineName + ".mydomain.net:8789";
server = WebApp.Start<Startup>(url);
to this:
string url = "http://*:8789";
var startOptions = new StartOptions(url);
server = WebApp.Start<Startup>(startOptions);

how to find the ip address of client who is login to our website or browsing our website

Here i have a small problem, that i want to find out the IP Address of the client who is accessing my website, i tried so many but all these are giving me 127.0.0.1 as IP, while i am testing in local host,
Please some one provide the code snippet and help me,
Thanks in advance,
public string GetClientIP()
{
string result = string.Empty;
string ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ip))
{
string[] ipRange = ip.Split(',');
int le = ipRange.Length - 1;
result = ipRange[0];
}
else
{
result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return result;
}
This is to be expected, your localhost IP address will most of the time be 127.0.0.1.
As said in the comments, when you will deploy your site and remote clients access it, their actual IP will correctly be retrieved.
If you want to try locally, you can try to configure your local network so that a remote computer on the same network access your web site. There you should see the IP address of that computer (for instance: 192.168.x.x).

WP7 Mango - How to get an IP address for a given hostname

I need to get an IP address for a given hostname from a DnsEndPoint, and convert it to an IPEndPoint. How would I go about doing this? WP7 lacks a Dns.GetHostEntry function, so is there any way to do this without creating a Socket, sending data to the host, then receiving a ping from the host and reading the RemoteEndPoint property to get the IP address of the host?
Try using DeviceNetworkInformation.ResolveHostNameAsync in the Microsoft.Phone.Net.NetworkInformation namespace, like this:
public void DnsLookup(string hostname)
{
var endpoint = new DnsEndPoint(hostname, 0);
DeviceNetworkInformation.ResolveHostNameAsync(endpoint, OnNameResolved, null);
}
private void OnNameResolved(NameResolutionResult result)
{
IPEndPoint[] endpoints = result.IPEndPoints;
// Do something with your endpoints
}
There is no way to do this built into the framework. You could use a socket assumming that the host supports ping. It will depend on the network you are running in (I'd assume you can't control this) and the exact requirements of the application.
It may be easier to get your app to work with IP addresses and not require a hostname if all you have is an IP address.
I think Im dealing with the same problem. I also have a dynamic IP updating the dns with No-ip.
For what I know the System.Net.Dns is not available in this version of Windows Phone.
Maybe in next releases.
http://msdn.microsoft.com/en-us/library/system.net.dns.aspx
At the start of my app Im going to create a web service call to the host (to the webserver in it) asking for the IPAddress. I think I'll solve the problem in the meantime.
This could be the WCF service
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetIpAddress(string value);
}
public class Service1 : IService1
{
public string GetIpAddress()
{
// Add the proper error handling and collection matching of course
IPAddress s = Dns.GetHostAddresses("www.mysite.com")[0];
return s.ToString();
}
}
If you guys find a direct approach please let me know

Get external IP address over remoting in C#

I need to find out the external IP of the computer a C# application is running on.
In the application I have a connection (via .NET remoting) to a server. Is there a good way to get the address of the client on the server side?
(I have edited the question, to be a little more clear. I'm apologize to all kind people who did their best to respond to the question, when I perhaps was a little too vague)
Solution:
I found a way that worked great for me. By implementing a custom IServerChannelSinkProvider and IServerChannelSink where I have access to CommonTransportKeys.IPAddress, it's easy to add the client ip on the CallContext.
public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
IMessage requestmessage, ITransportHeaders requestHeaders,
System.IO.Stream requestStream, out IMessage responseMessage,
out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
try
{
// Get the IP address and add it to the call context.
IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
CallContext.SetData("ClientIP", ipAddr);
}
catch (Exception)
{
}
sinkStack.Push(this, null);
ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
requestStream, out responseMessage, out responseHeaders, out responseStream);
return srvProc;
}
And then later (when I get a request from a client) just get the IP from the CallContext like this.
public string GetClientIP()
{
// Get the client IP from the call context.
object data = CallContext.GetData("ClientIP");
// If the data is null or not a string, then return an empty string.
if (data == null || !(data is IPAddress))
return string.Empty;
// Return the data as a string.
return ((IPAddress)data).ToString();
}
I can now send the IP back to the client.
This is one of those questions where you have to look deeper and maybe rethink the original problem; in this case, "Why do you need an external IP address?"
The issue is that the computer may not have an external IP address. For example, my laptop has an internal IP address (192.168.x.y) assigned by the router. The router itself has an internal IP address, but its "external" IP address is also internal. It's only used to communicate with the DSL modem, which actually has the external, internet-facing IP address.
So the real question becomes, "How do I get the Internet-facing IP address of a device 2 hops away?" And the answer is generally, you don't; at least not without using a service such as whatismyip.com that you have already dismissed, or doing a really massive hack involving hardcoding the DSL modem password into your application and querying the DSL modem and screen-scraping the admin page (and God help you if the modem is ever replaced).
EDIT: Now to apply this towards the refactored question, "How do I get the IP address of my client from a server .NET component?" Like whatismyip.com, the best the server will be able to do is give you the IP address of your internet-facing device, which is unlikely to be the actual IP address of the computer running the application. Going back to my laptop, if my Internet-facing IP was 75.75.75.75 and the LAN IP was 192.168.0.112, the server would only be able to see the 75.75.75.75 IP address. That will get it as far as my DSL modem. If your server wanted to make a separate connection back to my laptop, I would first need to configure the DSL modem and any routers inbetween it and my laptop to recognize incoming connections from your server and route them appropriately. There's a few ways to do this, but it's outside the scope of this topic.
If you are in fact trying to make a connection out from the server back to the client, rethink your design because you are delving into WTF territory (or at least, making your application that much harder to deploy).
Dns.GetHostEntry(Dns.GetHostName()); will return an array of IP addresses. The first one should be the external IP, the rest will be the ones behind NAT.
So:
IPHostEntry IPHost = Dns.GetHostEntry(Dns.GetHostName());
string externalIP = IPHost.AddressList[0].ToString();
EDIT:
There are reports that this does not work for some people. It does for me, but perhaps depending on your network configuration, it may not work.
I found a way that worked great for me. By implementing a custom IServerChannelSinkProvider and IServerChannelSink where I have access to CommonTransportKeys.IPAddress, it's easy to add the client ip on the CallContext.
public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
IMessage requestmessage, ITransportHeaders requestHeaders,
System.IO.Stream requestStream, out IMessage responseMessage,
out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
{
try
{
// Get the IP address and add it to the call context.
IPAddress ipAddr = (IPAddress)requestHeaders[CommonTransportKeys.IPAddress];
CallContext.SetData("ClientIP", ipAddr);
}
catch (Exception)
{
}
sinkStack.Push(this, null);
ServerProcessing srvProc = _NextSink.ProcessMessage(sinkStack, requestmessage, requestHeaders,
requestStream, out responseMessage, out responseHeaders, out responseStream);
return srvProc;
}
And then later (when I get a request from a client) just get the IP from the CallContext like this.
public string GetClientIP()
{
// Get the client IP from the call context.
object data = CallContext.GetData("ClientIP");
// If the data is null or not a string, then return an empty string.
if (data == null || !(data is IPAddress))
return string.Empty;
// Return the data as a string.
return ((IPAddress)data).ToString();
}
I can now send the IP back to the client.
Better to just use http://www.whatismyip.com/automation/n09230945.asp it only outputs the IP just for the automated lookups.If you want something that does not rely on someone else put up your own page http://www.unkwndesign.com/ip.php is just a quick script:
<?php
echo 'Your Public IP is: ' . $_SERVER['REMOTE_ADDR'];
?>
The only downside here is that it will only retrieve the external IP of the interface that was used to create the request.
Jonathan Holland's answer is fundamentally correct, but it's worth adding that the API calls behind Dns.GetHostByName are fairly time consuming and it's a good idea to cache the results so that the code only has to be called once.
The main issue is the public IP address is not necessarily correlated to the local computer running the application. It is translated from the internal network through the firewall. To truly obtain the public IP without interrogating the local network is to make a request to an internet page and return the result. If you do not want to use a publicly available WhatIsMyIP.com type site you can easily create one and host it yourself - preferably as a webservice so you can make a simple soap compliant call to it from within your application. You wouldn't necessarily do a screen capture as much as a behind the scenes post and read the response.
If you just want the IP that's bound to the adapter, you can use WMI and the Win32_NetworkAdapterConfiguration class.
http://msdn.microsoft.com/en-us/library/aa394217(VS.85).aspx
Patrik's solution works for me!
I made one important change. In process message I set the CallContext using this code:
// try to set the call context
LogicalCallContext lcc = (LogicalCallContext)requestMessage.Properties["__CallContext"];
if (lcc != null)
{
lcc.SetData("ClientIP", ipAddr);
}
This places the ip address in the correct CallContext, so it can later be retrieved with
GetClientIP().
Well, assuming you have a System.Net.Sockets.TcpClient connected to your client, you can (on the server) use client.Client.RemoteEndPoint. This will give you a System.Net.EndPoint pointing to the client; that should contain an instance of the System.Net.IPEndPoint subclass, though I'm not sure about the conditions for that. After casting to that, you can check it's Address property to get the client's address.
In short, we have
using (System.Net.Sockets.TcpClient client = whatever) {
System.Net.EndPoint ep = client.Client.RemoteEndPoint;
System.Net.IPEndPoint ip = (System.Net.IPEndPoint)ep;
DoSomethingWith(ip.Address);
}
Good luck.
I believe theoretically you are unable to do such a thing while being behind a router (e.g. using invalid ip ranges) without using an external "help".
You can basically parse the page returned by doing a WebRequest of http://whatismyipaddress.com
http://www.dreamincode.net/forums/showtopic24692.htm
The most reliable manner of doing this is checking a site like http://checkip.dyndns.org/ or similar, because until you actually go external to your network, you cannot find your external IP. However, hardcoding such a URL is asking for eventual failure. You may wish to only perform this check if the current IP looks like an RFC1918 private address (192.168.x.x being the most familiar of these.
Failing that, you can implement your own, similar, service sitting external to the firewall, so you will at least know if it's broken.

Categories