Detect/estimate country of a http-request in ASP.NET - c#

I'm looking for ways to detect/estimate the country from which a http-request is coming in ASP.NET.
I know there are some solutions with services/country lookups but I never used one.
I'm looking for small/clean solutions.
It's for helping someone filling out a form so it does not have to be 100% accurate.
Thanks in advance..

You can make a simple HTTP request to this URL:
http://api.hostip.info/get_html.php?ip=207.46.197.32
using the value of the REMOTE_ADDR server variable. That will return the country and city like this:
Country: UNITED STATES (US)
City: New York, NY
I use that service for a web form just as you describe. Occasionally it doesn't know the answer, but usually it's very good (and it's free and simple 8-)
In C#, you can use System.Net.WebRequest.Create to read from the URL.

You can use one of available web services to match an incoming request to a country.
Otherwise you may decide to grab the MaxMind database file (GeoLite Country), read from this file in your application and perform a match. Thus you will be independent from a third-party service, only pulling regularly updates for the database file.
Also check out similar questions:
Geolocation web service recommendations
Know a good IP address Geolocation Service?

If you choose to use the REMOTE_ADDR server variable, you can be fairly certain that the IP that you recover accurately represents the nation of origin of that user. It is fairly uncommon for a user to be accessing the Internet from outside of the country that he is currently in, with a few notable exceptions, such as those who choose to surf though an anonymous proxy server, such as is discussed below. If, however, you want to get the state that a user is coming from, or authenticate the identity of a user, you're out of luck as far as any even remotely reliable method is concerned.
More info here.

This is what I've used:
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
'url': 'http://www.freegeoip.net/json/#(HttpContext.Current.Request.UserHostAddress)',
'type': 'GET',
'success': function(data) {
// for example
if (data.country_code === "GB") {
... further logic here
}
}
});
});
</script>
Simple, and it works.

I just had to do this so here's a working example (specific to France) which may be of use to someone:
string userIP = Request.ServerVariables["REMOTE_ADDR"];
string localeAPIURL = "http://api.hostip.info/get_html.php?ip=" + userIP;
HttpWebRequest r = (HttpWebRequest)WebRequest.Create(localeAPIURL);
r.Method = "Get";
HttpWebResponse res = (HttpWebResponse)r.GetResponse();
Stream sr = res.GetResponseStream();
StreamReader sre = new StreamReader(sr);
// check response for FRANCE
string s = sre.ReadToEnd();
string sub = s.Substring(9, 6);
if (sub == "FRANCE")
{
Response.Redirect("http://fr.mysite.com");
}

Related

How to get Sub Domain on Web API Action

I am developing a Classified Web Site. This web site has a lot of Sub Domains like dubai.sitedomain.com, london.sitedomain.com, newyork.sitedomain.com etc depending on cities. I am using Angularjs as my front end and Web Api as server side.
My requirement is I want to get the subdomain on my Web Api Action. Like:
[HttpGet]
[Route("GetAds")]
public IHttpActionResult GetAds()
{
// Here I want to know, from which subdomain the request has been sent
// so I can filter my ads according to the city
var city = "city from subdomain";
var list = _adService.GetAdsByCity(city);
return Ok(list);
}
Use Request.Headers.Referrer.Host.Replace(".sitedomain.com", string.Empty);
Of course this will only work on your live environment, so you may need to modify this to work differently on your local test domains, or provide some sort of default fallback. I would suggest extracting this to a method in a common library, as it's likely you will need it in many places.
Alternatively, if you know that it will always be the first part, you can use
Request.Headers.Referrer.Host.Substring(0, Request.Headers.Referrer.Host.IndexOf("."));
You can extract it from
var x = Request.Host.Value;
Which will give you "london.sitedomain.com:port"
You can then do a
x.Split('.')[0] //(for example)
To get the subdomain
This should get you what you need.
HttpContext.Current.Request.UserHostAddress;
HttpContext.Current.Request.UserAgent;
HttpContext.Current.Request.Url.OriginalString;
There is also:
Request.Url.Scheme
Request.Url.Authority
Request.ApplicationPath
You can get host from HttpRequestMessage.RequestUri.Host:
string host = Request.RequestUri.Host;
int index = host.IndexOf('.');
return host.Substring(0, index + 1)

Can 'Clicky Web Analytics' be used in a C# WinForms environment?

Can 'Clicky Web Analytics' be utilized in a C# WinForms environment?
The only thing I can spot is a HTML code snippet for websites.
They also accept HTTP requests, but I believe they are just for polling data, not for pushing new events/stats to Clicky.
I realize it is probably called 'Clicky Web Analytics' for a reason (i.e. only website/web app based stat tracking), but I could really use a C# solution right about now.
Here is how to track custom events from C# to your clicky site:
private static void TrackStatWithClicky(string eventValue)
{
// Prepare HTTP request
WebRequest request = WebRequest.Create
(
"http://in.getclicky.com/in.php?" +
"site_id=" + ClickySiteID + //click site id , found in preferences
"&sitekey_admin=" + ClickySiteAdminKey + //clicky site admin key, found in preferences
"&ip_address=" + GetLocalIPAddressString() + //ip address of the user - used for mapping action trails
"&type=custom" +
"&href=" + eventValue.Replace(" ", "_") + //string that contains whatever event you want to track/log
"&title=APPNAME Action" +
"&type=click"
);
request.Method = "GET";
// Get response
WebResponse response = request.GetResponse();
response.Close();
}
public static string GetLocalIPAddressString()
{
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
return "";
}
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
return host.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
}
Some of the information here was usefull in figuring it out: https://clicky.com/help/custom/manual#internal
They appear to have an API for Manual data logging. Specifically, they mention Logging internal events:
Logging data from an internal script
Clicky lets you log data from an internal script, such as PHP, ASP, Perl, etc. Other services don't offer this feature because they don't document their incoming "API", and they only verify incoming data from the referrer. Clicky is different.
It seems to be really made for your backend webserver scripts to also contribute user data, but I'm pretty sure you could make the web API calls from whatever language you'd like, including a WinForms script. Not really what it's made for, but hey, why not? Just issue a GET request with the URL-encoded parameters:
How to talk to our tracking servers
The page you want to talk to is at http://in.getclicky.com/in.php. This is the same script that our tracking code talks to. You just need to send the right parameters, and we'll log it.
So you'll need to port their example PHP Script to C# and you'll be good to go.

Minecraft 1.6.2 Custom Launcher

I am making a launcher for Minecraft. 1.6.2 changed a lot, so the way you login is different. If any of you have any knowledge of logging into minecraft using C#, I would appreciate it.
wClient.DownloadString("http://login.minecraft.net/?user=" + strUsername + "&password=" + strPassword + "&version=13");
I believe this used to be a valid way of doing it, but I am not quite sure anymore. Help is appreciated, thanks.
In reply to TheUnrealMegashark's comments to Rhys Towey's Answer. I have been working really hard to get it to launch, but. Its throwing me off a bit. The very next update will include a 1.6 fix. Just got to figure it out.
The proper answer to your question is that the web link that fetches the Session is still currently in use. Nothing new there.
Beware! You must know that your
"http://login.minecraft.net/?user=" + strUsername + "&password=" +
strPassword + "&version=13"
Is unsafe. It sends the password of the user through the internet in plain text. it can be subject to "Man in the Middle" attacks.
One of the proper ways to encrypt the connection is to use HTTPS with POST. Using POST, I avoid sending all of the data in the request URL and send the data through POST. Using HTTPS, I encrypt any data sent after the request URL returns. HTTPS makes POST encrypted, thus removing "Man in the Middle" attacks.
You can use GET with HTTPS and it still be secure (from what i have read). But, it is considered an unsafe practice. Although it is safe in all accounts between your computer and the connected device, anywhere else it might be seen and be subject to "Man behind you Attack". What I mean is that when you send this URL, it is possible for your computer to record the URL in some sort of history, or, display it in an address bar in plain text. Although, sense your not making a web browser and the URL is not displayed, this could possibly all be forgotten.
But, If it were me, I would still play it safe and just use the safer strategy.
To use HTTPS with POST.
Here is a sample of code i use in my "AtomLauncher." This code will send the POST data to the URL and return a string. Goto http://www.minecraftwiki.net/wiki/Minecraft.net to get more info on the string that is returned.
string mcURLData = "Error";
using (WebClient client = new WebClient()) // Get Data from Minecraft with username and password
{
// This a Text control for my Program, ignore this commented line if you wish.
// this.Invoke(new MethodInvoker(delegate { homeLabelTop.Text = "Connecting to Minecraft.net..."; }));
try
{
System.Collections.Specialized.NameValueCollection urlData = new System.Collections.Specialized.NameValueCollection();
urlData.Add("user", "UserName");
urlData.Add("password", "MYPa22w0rd");
urlData.Add("version", "13");
byte[] responsebytes = client.UploadValues("https://login.minecraft.net", "POST", urlData);
mcURLData = Encoding.UTF8.GetString(responsebytes);
}
catch
{
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
mcURLData = "Internet Disconnected.";
}
else
{
mcURLData = "Can't connect to login.minecraft.net.";
}
}
}
To use HTTPS with GET
just simply change the
http
in your code to
https
In other news.
I have fixed my code. Feel free (when its uploaded) to use it.
For your information, you need to know that when 1.6.X launches it creates a natives folder of which it starts using immediately. What I have done to fix this was to run 1.6.2 and copy the natives folder it created and removed the number.
Created "version/1.6.2/1.6.2-natives-###"
Copied it to "version/1.6.2/1.6.2.natives"
Point my program to "natives" folder I created.
What I'll end up doing in the future is automatically checking for the natives folder and if it doesn't exist, I'll have it download natives from the internet.
(I would love to know where minecraft is getting its current natives so i can essentially do the same thing. Unless, what it does is download it from the internet every time it launches. If true, that's kind of ugly. Seeing as I have bandwidth usage limits.)

C# PHP Connection Flood Protection

So let's say I created a feedback form in C#.
It sens the feedback to my PHP Page and my PHP Page adds it to my MySQL Database.
Code:
private void PostFeed(string Params)
{
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.Headers["Accept"] = #"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
wc.Headers["Accept-Language"] = #"en-US,en;q=0.5";
string HtmlResult = wc.UploadString("http://website/feedtest.php", "POST", Params);
Console.WriteLine(HtmlResult);
}
}
On my PHP I have a code that looks similar to:
$name = $_REQUEST['name'];
$email = $_REQUEST['email'];
$desc = $_REQUEST['description'];
connect
post result...
close connection
The question I have is: is there a way to protect against flood ? I understand anyone can just spam/flood it by sending feedback continuously or even creating a third party app that sends like 1000 post request per second. I was thinking of implementing some sort of check on the PHP side, for example: if the connection password from the c# app matches, then continue if not, exit.
Basically, I dont want people to take advantage of the feedback method and spam me.
Can anyone suggest a method ? or Should I not even worry about this ?
Any help is appreciated.
A typical technique is to have some kind of submissions per X unit of time limit where you have a last_submitted_at column in a table associated with some kind of identifier. For example, you might associate it with a user if you have a fairly robust user registration system, or you might associate it with an IP if you don't.
This is the system that Stack Overflow uses if you try and vote, post, or as questions too often. Each of these has a separate timer which probably translates to a separate last_X_at column in the database somewhere.
If the last time is less than some threshold, present an error instead of accepting the submission.

Web Service capture Response

My web service calls a url which returns a value which I must capture and use in a different function.
I've only recently starting working with web services and am very new to the concept of calling a url within a web service (Previously asked and answered on this forum for those requiring more information)
Webservice method to call a url
My web service is: Insurance Service.
My client sends me data through the Insurance service which calls a url which returns an Insurance Number.
How do I capture this insurance number? I thought I could use session to capture it but I was so wrong insurance Number comes as null with an object reference error.
int insuranceNo;
insuranceNo = Convert.ToInt16(HttpContext.Current.Session["insuranceNo"]);
It must have something to do with response right?
I thought I could try google what I am looking for but I honestly don't know what to call this in order to search for it. Thought I'd give it another shot in this forum since I found the answer to the first part of this function here.
code to call url:
string url = string.Format("www.insuranceini.com/insurance.asp?fileno1={0},&txtfileno2={1‌​}&username={2}&userid={3}&dteinsured={4}&dteDob={5}&InsurerName={6}", txtfileno1, txtfileno2, username, userid, dteinsured,dteDob,InsurerName)
WebRequest request = HttpWebRequest.Create(url);
using(WebResponse response = request.GetResponse())
{
using(StreamReader reader = new StreamReader(response.GetResponseStream()))
{
string urlText = reader.ReadToEnd();
//Do whatever you need to do
}
}
I would be grateful for any sort of pointers or places to start looking or any advice.
Code began giving different errors. Closing this and referring to : Datetime Conversion and Parsing
Thank you everyone for the helpful comments.

Categories

Resources