Based on below pic, there may be several WebSite on IIS with several services,
So the only thing which I have separate them from together is Hostname , in the other site sibling services may call together so I have decided to change hostname if they are not on localhost so in service I tried something like this:
HostName = OperationContext.Current.Channel.LocalAddress.Uri.Host.ToString();
and in service when I am calling another service by it's proxy I Rehome
public void ReHome(string hostName)
{
if (!string.IsNullOrEmpty(hostName))
{
if (this.Endpoint.Address.Uri.DnsSafeHost.ToLower().Equals("localhost"))
{
string newAddress = string.Format("{0}://{1}{2}/{3}", Endpoint.Address.Uri.Scheme
, hostName, string.IsNullOrEmpty(Endpoint.Address.Uri.Port.ToString()) ? string.Empty : ":" + Endpoint.Address.Uri.Port.ToString()
, Endpoint.Address.Uri.AbsolutePath);
this.Endpoint.Address = new EndpointAddress(newAddress);
}
}
}
call example in a service:
using (var hisProxy = new HISIntegrationClient("hisIntegrationEndPoint", Internals.SYSTEM))
{
hisProxy.ReHome(HostName);
....
}
so is OperationContext.Current.Channel.LocalAddress.Uri.Host give me what I want that mentioned in above pic?
You get the current base address of server(hostname and port) using following code snippet
var baseAddress = OperationContext.Current.Host.BaseAddresses[0].Authority;
Related
The following code works OK locally, but it will only get the server's IP (if I'm correct).
try
{
string externalIP;
externalIP = (new WebClient()).DownloadString("http://checkip.dyndns.org/");
externalIP = (new Regex(#"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
.Matches(externalIP)[0].ToString();
model.IpCreacion = externalIP;
}
catch { }
I can't test this right now, because the two guys at my office that can make this as a public URL for testing on a server aren't here today. The code is in the controller of the project, so it runs on the server every time a client executes the app, it's not actually the client who is getting the IP address.
How can I make the client get his IP address, instead of the server, executing the code I just showed?
If I managed to put this functionality in a view, would it work as I'm intending to?
UPDATE: I tried other methods posted as answers, like
string ip = System.Web.HttpContext.Current.Request.UserHostAddress;
and
model.IpCreacion = null;
model.IpCreacion = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(model.IpCreacion))
{
model.IpCreacion = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
but now I'm only getting ::1 as a result. Which didn't happen before, as I was getting a correct IP address.
if you want to get client ip address,visit bellow post in stackoverflow
How can I get the client's IP address in ASP.NET MVC?
That gets only IP of server, because you send the request from Web Server to checkip.dyndns.org.
To get the client IP, you need to use JavaScript and do the same thing.
$.get('http://checkip.dyndns.org/', function(data) {
console.log(data); // client IP here.
})
UPDATED:
If you need client IP Address in ASP.NET Core, you can inject this service
private IHttpContextAccessor _accessor;
And use it as
_accessor.HttpContext.Connection.RemoteIpAddress.ToString()
Or in ASP.NET Framework
Public string GetIp()
{
string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ip))
{
ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}
Public string GetIp()
{
string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ip))
{
ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}
I have 2 Applications here. One is a Xamarin Application and the other is a Asp.Net MVC Application which has the WebApi to connect to a SqlServer Database "where the database is on a Hosted Website of like some IP Address xxx.xxx.xxx.xxx" .
I run the MVC application Locally to IIS, and then Once the Website is Up in IIS, I run the Xamarin Application from the second instance of Visual Studio.
Firstly I don't think the MVC WebApi gets called, because I tried putting Breakpoints there and it does not come there. I don't know why. Because I had done the same thing with a Winforms and MVC application (WebApi), then at least the WebApi was getting called which I saw with breakpoints in the MVC application.
Now in Xamarin I am getting this error
System.Net.Http.HttpRequestException: 'Network subsystem is down'
in the line
var responseTask = await client.GetAsync("ConnectToAscDatabase");
I have this code in Xamarin Application's MainPage.cs
private async void Button_OnClicked(object sender, EventArgs e)
{
HttpClientHandler handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
using (var client = new HttpClient(handler))
{
client.BaseAddress = new Uri("http://localhost:49252/api/");
// !!! This Line gives the error System.Net.Http.HttpRequestException: 'Network subsystem is down'
var responseTask = await client.GetAsync("ConnectToAscDatabase");
var readTask = responseTask.Content.ReadAsAsync<Microsoft.Data.SqlClient.SqlConnection>();
SqlConnection con = readTask.Result;
var staty = con.State;
}
}
and this is a WebApi
public class ConnectToAscDatabaseController : ApiController
{
public async Task<Microsoft.Data.SqlClient.SqlConnection> Get()
{
string SqlServer_ServerPath_Server = "SomeServer";
string SqlServer_Database_Server = "SomeDatabase";
string SqlServer_User_Server = "SomeUser";
string SqlServer_Password_Server = "SomePassword";
int timeOutInSeconds = 15;
string connectionString = "data source=" + SqlServer_ServerPath_Server + ";" + "initial catalog=" + SqlServer_Database_Server + ";" + "user id=" + SqlServer_User_Server + ";" + "Password=" + SqlServer_Password_Server + ";" + "Trusted_Connection=false" + ";" + "Connection Timeout=" + timeOutInSeconds + ";" + "Persist Security Info=False";
SqlConnection con = new SqlConnection(connectionString);
con.Open();
return con;
}
}
From this documentation, Android's Network Address Space is responsible as there is no direct connection from the emulator to your local machine, except with the IP Address "10.0.2.2". You can attach your port number to target whatever services you are trying to reach.
It is also worth noting that for service running with self-signed certificates, you still may not get a connection because of trust issues as Android and IOS will not honor connections to services running with self-signed certificates. Read more from here.
I use the following codes to resolve those issues (On Android):
Shared Project (Add the following interface):
using System.Net.Http;
namespace DemoApp.Services
{
public interface IHttpClientHandlerService
{
HttpClientHandler GetInsecureHandler();
}
}
Android Project (Add the following class):
using DemoApp.Droid.Services;
using DemoApp.Services;
using System.Net.Http;
using Xamarin.Forms;
[assembly: Dependency(typeof(HttpClientHandlerService))]
namespace DemoApp.Droid.Services
{
public class HttpClientHandlerService : IHttpClientHandlerService
{
public HttpClientHandler GetInsecureHandler()
{
HttpClientHandler handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
{
if (cert.Issuer.Equals("CN=localhost"))
return true;
return errors == System.Net.Security.SslPolicyErrors.None;
}
};
return handler;
}
}
}
Now from within your codes you can create a new HttpClient using the following:
#if DEBUG
HttpClientHandler insecureHandler = DependencyService.Get<IHttpClientHandlerService>().GetInsecureHandler();
HttpClient client = new HttpClient(insecureHandler);
#else
HttpClient client = new HttpClient();
#endif
Note: There are better ways of creating an HttpClient (like using dependency injection and IHttpClientFactory) and it is up to the reader to use what suites them best.
For the BaseAddress of HttpClient, you can use the following code as well:
public static string BaseAddress =
DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";
where port 5000 may be the port to reach your service and todoitems may be the api url to invoke.
According to your description, you want to display data using web api in Xamarin.Forms, there are many article about this, you can take a look:
https://www.c-sharpcorner.com/article/how-to-fetch-data-from-web-api-using-xamarin-forms/
You need to make sure the Web API project is up and running because the Xamarin app will call WebAPI to access data.
More detailed info about building an ASP.NET Web API with Entity Framework and retrieve data from an SQL server, you can also take a look:
https://medium.com/better-programming/building-a-restful-api-with-asp-net-web-api-and-sql-server-ce7873d5b331
Maybe I'm not searching with the right terms because this seems pretty simple. I'm just looking for a way to list the endpoints of a WCF service that has it's endpoints created during runtime the same way WCF Test Client Does.
Specify URL
Get MetaData and Endpoints
This is how I add the endpoints during runtime
string SetInstrumentsURL = serviceUrl + "SetInstruments/";
string SetInstrumentsPipe = "net.pipe://localhost/TestService/SetInstruments/";
ServiceHost SetInstrumentsHost = null;
var SetInstruments = InstrumentLoader.Factory.GetIEnumerableOf<ISetInstrument>();
if (SetInstruments.Count() > 0)
{
Uri SetInstrumentsURI = new Uri(SetInstrumentsURL);
Uri SetInstrumentsPipedURI = new Uri(SetInstrumentsPipe);
NetTcpBinding netTcpBindingSetInstruments = new NetTcpBinding();
NetNamedPipeBinding NamedPipeBindingSetInstruments = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
SetInstrumentsHost = new ServiceHost(typeof(TeraSetInstrumentService), new Uri[] { SetInstrumentsURI, SetInstrumentsPipedURI });
ServiceMetadataBehavior SetInstrumentServiceMetadataBehavior = new ServiceMetadataBehavior();
SetInstrumentsHost.Description.Behaviors.Add(SetInstrumentServiceMetadataBehavior);
SetInstrumentsHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
SetInstrumentsHost.AddServiceEndpoint(typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexNamedPipeBinding(), "mex");
foreach (var setter in SetInstruments)
{
SetInstrumentsHost.AddServiceEndpoint(typeof(ISetInstrumentService), netTcpBindingSetInstruments, SetInstrumentsURL + setter.Name).Name = "Set_" + setter.Name.Replace(" ", "_");
SetInstrumentsHost.AddServiceEndpoint(typeof(ISetInstrumentService), NamedPipeBindingSetInstruments, SetInstrumentsPipe + setter.Name).Name = "Set_" + setter.Name.Replace(" ", "_");
}
SetInstrumentsHost.Open();
}
What functions can I use from the client side to access those same endpoints as WCF Test Client? I know how to connect to those endpoints if I already have the Endpoint's URL but I would like to have a list of the endpoints so I can create a drop down list choose from that changes depending on what host you connect to.
Adding a service reference through Visual Studio doesn't list all of the endpoints because the are not created yet. Is the a library I can use to get them at run time like WCF Test Client does.
Provided that we have the service metadata URI, we could use MetadataExchangeClientMode and MetadataResolver class which is provided in the System.ServiceModel.Description namespace to retrieve and process the metadata.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-metadataresolver-to-obtain-binding-metadata-dynamically
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-metadataexchangeclient-to-retrieve-metadata
I have made a simple example, wish it is useful to you.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://10.157.13.69:3336/mex");
MetadataExchangeClient client = new MetadataExchangeClient(uri, MetadataExchangeClientMode.MetadataExchange);
MetadataSet metadata = client.GetMetadata();
WsdlImporter importer = new WsdlImporter(metadata);
ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();
//ServiceEndpointCollection endpoints = MetadataResolver.Resolve(typeof(IService), uri, MetadataExchangeClientMode.MetadataExchange);
foreach (var item in endpoints)
{
Console.WriteLine(item.Address.Uri);
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string SayHello();
}
Result
Okay it was pretty easy to do, I just needed to use the MetadataExchangeClient to get the config. In the code all I had to do to get the MetaData Xml was this:
var meta = new System.ServiceModel.Description.MetadataExchangeClient(new Uri("net.tcp://10.0.2.124:9000/TeraService/SetInstruments/mex"), System.ServiceModel.Description.MetadataExchangeClientMode.MetadataExchange);
var data = meta.GetMetadata();
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(data.GetType());
TextWriter writer = new StreamWriter("xmlfile.xml");
x.Serialize(writer, data);
writer.Close();
I posted my answer in the wrong place. But Abraham Qian has a more elegant solution that I will test now.
I am supporting a system that needs to get the client's computer name I try different codes but all of them just get the computer name of the host server, not the client's computer name. Here's the snippet:
public void CreateEvents(string className, string eventName, string eventData, string userId)
{
string hostName = Dns.GetHostName(); // Retrive the Name of HOST
string compname= HttpContext.Current.Request.UserHostAddress;
var browser = HttpContext.Current.Request.Browser.Browser + " " + HttpContext.Current.Request.Browser.Version;
if (string.IsNullOrEmpty(userId))
{
userId = compname;
}
var entity = new EventLog
{
ClassName = className,
EventName = eventName,
EventData = eventData,
IpAddress = ipAddress,
Browser = browser,
UserId = userId,
CreatedDate = DateTime.Now
};
_db.EventLogs.Add(entity);
_db.SaveChanges();
}
public string GetIpAddress()
{
HttpContext context = System.Web.HttpContext.Current;
string compname= context.Request.UserHostAddress; //System.Net.Dns.GetHostName();
return compname;
}
Thanks in advance!
No you can't, unless the client sends such info when making HTTP requests. By "client", I'm referring to any - some app, browser, etc.
You can inspect your own browser request flow using standard browser dev tools and see exactly what info your browser is sending. It will not have your machine name (unless something in your machine is and that would likely be a problem).
That said, HTTP Header data is what you have aside from standard network info such as IP address (which also isn't guaranteed to be the client's IP address - it could be the client's network address). The closest you can get to is hostname if it exists, and even then, just like IP address, is not guaranteed to be machine name.
A possible exception would be in an internal network (LAN).
you can use
HttpContext.Request.UserHostAddress
for getting the IP address, also Request has UserHostName but I am not sure about this property
You can get computer name as follows:
Environment.MachineName.ToString()
You can get hosting server name as follows:
Server.MachineName.ToString()
I have Wcf rest service.
I host it in console application.
when I try to access the service from my local computer it works but when I try from remote
computer the service is not found.
here is the code:
service definition:
[ServiceContract]
public interface IInstagramCallbackService
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "url/?hub.mode={mode}&hub.challenge={challenge}&hub.verify_token={token}")]
string CheckServiceAvailability(string mode, string challenge, string token);
}
public class InstagramCallbackService : IInstagramCallbackService
{
public string CheckServiceAvailability(string mode, string challenge, string token)
{
return challenge;
}
}
hosting:
ServiceHost host = new ServiceHost(typeof(InstagramCallbackService),new Uri[]{});
WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.None);
ServiceEndpoint endPoint = new ServiceEndpoint(
ContractDescription.GetContract(
typeof(InstagramCallbackService)), binding, new EndpointAddress(
"http://127.0.0.1:6064/InstagramCallbackService"));
WebHttpBehavior webBehavior = new WebHttpBehavior();
endPoint.Behaviors.Add(webBehavior);
host.AddServiceEndpoint(endPoint);
host.Open();
Console.WriteLine("ready");
Console.ReadLine();
127.0.0.1 is a local address. It's like saying localhost or "this computer". You can't hit 127.0.0.1 from another computer, because 127.0.0.1 from another computer would just be that computer. Surely your machine has other addresses you can use though no? Try ipconfig from the command line.