We have Request.UserHostAddress to get the IP address in ASP.NET, but this is usually the user's ISP's IP address, not exactly the user's machine IP address who for example clicked a link. How can I get the real IP Address?
For example, in a Stack Overflow user profile it is: "Last account activity: 4 hours ago from 86.123.127.8", but my machine IP address is a bit different. How does Stack Overflow get this address?
In some web systems there is an IP address check for some purposes. For example, with a certain IP address, for every 24 hours can the user just have only 5 clicks on download links? This IP address should be unique, not for an ISP that has a huge range of clients or Internet users.
Did I understand well?
Often you will want to know the IP address of someone visiting your website. While ASP.NET has several ways to do this one of the best ways we've seen is by using the "HTTP_X_FORWARDED_FOR" of the ServerVariables collection.
Here's why...
Sometimes your visitors are behind either a proxy server or a router and the standard Request.UserHostAddress only captures the IP address of the proxy server or router. When this is the case the user's IP address is then stored in the server variable ("HTTP_X_FORWARDED_FOR").
So what we want to do is first check "HTTP_X_FORWARDED_FOR" and if that is empty we then simply return ServerVariables("REMOTE_ADDR").
While this method is not foolproof, it can lead to better results. Below is the ASP.NET code in VB.NET, taken from James Crowley's blog post "Gotcha: HTTP_X_FORWARDED_FOR returns multiple IP addresses"
C#
protected string GetIPAddress()
{
System.Web.HttpContext context = System.Web.HttpContext.Current;
string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
return context.Request.ServerVariables["REMOTE_ADDR"];
}
VB.NET
Public Shared Function GetIPAddress() As String
Dim context As System.Web.HttpContext = System.Web.HttpContext.Current
Dim sIPAddress As String = context.Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If String.IsNullOrEmpty(sIPAddress) Then
Return context.Request.ServerVariables("REMOTE_ADDR")
Else
Dim ipArray As String() = sIPAddress.Split(New [Char]() {","c})
Return ipArray(0)
End If
End Function
As others have said you can't do what you are asking. If you describe the problem you are trying to solve maybe someone can help?
E.g.
are you trying to uniquely identify your users?
Could you use a cookie, or the session ID perhaps instead of the IP address?
Edit The address you see on the server shouldn't be the ISP's address, as you say that would be a huge range. The address for a home user on broadband will be the address at their router, so every device inside the house will appear on the outside to be the same, but the router uses NAT to ensure that traffic is routed to each device correctly. For users accessing from an office environment the address may well be the same for all users. Sites that use IP address for ID run the risk of getting it very wrong - the examples you give are good ones and they often fail. For example my office is in the UK, the breakout point (where I "appear" to be on the internet) is in another country where our main IT facility is, so from my office my IP address appears to be not in the UK. For this reason I can't access UK only web content, such as the BBC iPlayer). At any given time there would be hundreds, or even thousands, of people at my company who appear to be accessing the web from the same IP address.
When you are writing server code you can never be sure what the IP address you see is referring to. Some users like it this way. Some people deliberately use a proxy or VPN to further confound you.
When you say your machine address is different to the IP address shown on StackOverflow, how are you finding out your machine address? If you are just looking locally using ipconfig or something like that I would expect it to be different for the reasons I outlined above. If you want to double check what the outside world thinks have a look at whatismyipaddress.com/.
This Wikipedia link on NAT will provide you some background on this.
UPDATE:
Thanks to Bruno Lopes. If several ip addresses could come then need to use this method:
private string GetUserIP()
{
string ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipList))
{
return ipList.Split(',')[0];
}
return Request.ServerVariables["REMOTE_ADDR"];
}
If is c# see this way, is very simple
string clientIp = (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ??
Request.ServerVariables["REMOTE_ADDR"]).Split(',')[0].Trim();
What else do you consider the user IP address? If you want the IP address of the network adapter, I'm afraid there's no possible way to do it in a Web app. If your user is behind NAT or other stuff, you can't get the IP either.
Update: While there are Web sites that use IP to limit the user (like rapidshare), they don't work correctly in NAT environments.
I think I should share my experience with you all. Well I see in some situations REMOTE_ADDR will NOT get you what you are looking for. For instance, if you have a Load Balancer behind the scene and if you are trying to get the Client's IP then you will be in trouble. I checked it with my IP masking software plus I also checked with my colleagues being in different continents. So here is my solution.
When I want to know the IP of a client, I try to pick every possible evidence so I could determine if they are unique:
Here I found another sever-var that could help you all if you want to get exact IP of the client side. so I am using : HTTP_X_CLUSTER_CLIENT_IP
HTTP_X_CLUSTER_CLIENT_IP always gets you the exact IP of the client. In any case if its not giving you the value, you should then look for HTTP_X_FORWARDED_FOR as it is the second best candidate to get you the client IP and then the REMOTE_ADDR var which may or may not return you the IP but to me having all these three is what I find the best thing to monitor them.
I hope this helps some guys.
You can use:
System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.GetValue(0).ToString();
All of the responses so far take into account the non-standardized, but very common, X-Forwarded-For header. There is a standardized Forwarded header which is a little more difficult to parse out. Some examples are as follows:
Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17
I have written a class that takes both of these headers into account when determining a client's IP address.
using System;
using System.Web;
namespace Util
{
public static class IP
{
public static string GetIPAddress()
{
return GetIPAddress(new HttpRequestWrapper(HttpContext.Current.Request));
}
internal static string GetIPAddress(HttpRequestBase request)
{
// handle standardized 'Forwarded' header
string forwarded = request.Headers["Forwarded"];
if (!String.IsNullOrEmpty(forwarded))
{
foreach (string segment in forwarded.Split(',')[0].Split(';'))
{
string[] pair = segment.Trim().Split('=');
if (pair.Length == 2 && pair[0].Equals("for", StringComparison.OrdinalIgnoreCase))
{
string ip = pair[1].Trim('"');
// IPv6 addresses are always enclosed in square brackets
int left = ip.IndexOf('['), right = ip.IndexOf(']');
if (left == 0 && right > 0)
{
return ip.Substring(1, right - 1);
}
// strip port of IPv4 addresses
int colon = ip.IndexOf(':');
if (colon != -1)
{
return ip.Substring(0, colon);
}
// this will return IPv4, "unknown", and obfuscated addresses
return ip;
}
}
}
// handle non-standardized 'X-Forwarded-For' header
string xForwardedFor = request.Headers["X-Forwarded-For"];
if (!String.IsNullOrEmpty(xForwardedFor))
{
return xForwardedFor.Split(',')[0];
}
return request.UserHostAddress;
}
}
}
Below are some unit tests that I used to validate my solution:
using System.Collections.Specialized;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UtilTests
{
[TestClass]
public class IPTests
{
[TestMethod]
public void TestForwardedObfuscated()
{
var request = new HttpRequestMock("for=\"_gazonk\"");
Assert.AreEqual("_gazonk", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv6()
{
var request = new HttpRequestMock("For=\"[2001:db8:cafe::17]:4711\"");
Assert.AreEqual("2001:db8:cafe::17", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv4()
{
var request = new HttpRequestMock("for=192.0.2.60;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv4WithPort()
{
var request = new HttpRequestMock("for=192.0.2.60:443;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedMultiple()
{
var request = new HttpRequestMock("for=192.0.2.43, for=198.51.100.17");
Assert.AreEqual("192.0.2.43", Util.IP.GetIPAddress(request));
}
}
public class HttpRequestMock : HttpRequestBase
{
private NameValueCollection headers = new NameValueCollection();
public HttpRequestMock(string forwarded)
{
headers["Forwarded"] = forwarded;
}
public override NameValueCollection Headers
{
get { return this.headers; }
}
}
}
IP addresses are part of the Network layer in the "seven-layer stack". The Network layer can do whatever it wants to do with the IP address. That's what happens with a proxy server, NAT, relay, or whatever.
The Application layer should not depend on the IP address in any way. In particular, an IP Address is not meant to be an identifier of anything other than the idenfitier of one end of a network connection. As soon as a connection is closed, you should expect the IP address (of the same user) to change.
If you are using CloudFlare,
you can try this Extension Method:
public static class IPhelper
{
public static string GetIPAddress(this HttpRequest Request)
{
if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();
if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) return Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
return Request.UserHostAddress;
}
}
then
string IPAddress = Request.GetIPAddress();
string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;
What you can do is store the router IP of your user and also the forwarded IP and try to make it reliable using both the IPs [External Public and Internal Private]. But again after some days client may be assigned new internal IP from router but it will be more reliable.
Combining the answers from #Tony and #mangokun, I have created the following extension method:
public static class RequestExtensions
{
public static string GetIPAddress(this HttpRequest Request)
{
if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();
if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
{
string ipAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
}
return Request.UserHostAddress;
}
}
public static class Utility
{
public static string GetClientIP(this System.Web.UI.Page page)
{
string _ipList = page.Request.Headers["CF-CONNECTING-IP"].ToString();
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
_ipList = page.Request.ServerVariables["HTTP_X_CLUSTER_CLIENT_IP"];
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
_ipList = page.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
return page.Request.ServerVariables["REMOTE_ADDR"].ToString().Trim();
}
}
}
}
}
Use;
string _ip = this.GetClientIP();
use in ashx file
public string getIP(HttpContext c)
{
string ips = c.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ips))
{
return ips.Split(',')[0];
}
return c.Request.ServerVariables["REMOTE_ADDR"];
}
In NuGet package install Microsoft.AspNetCore.HttpOverrides
Then try:
public class ClientDeviceInfo
{
private readonly IHttpContextAccessor httpAccessor;
public ClientDeviceInfo(IHttpContextAccessor httpAccessor)
{
this.httpAccessor = httpAccessor;
}
public string GetClientLocalIpAddress()
{
return httpAccessor.HttpContext.Connection.LocalIpAddress.ToString();
}
public string GetClientRemoteIpAddress()
{
return httpAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
}
public string GetClientLocalPort()
{
return httpAccessor.HttpContext.Connection.LocalPort.ToString();
}
public string GetClientRemotePort()
{
return httpAccessor.HttpContext.Connection.RemotePort.ToString();
}
}
Its easy.Try it:
var remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;
just it :))
use this
Dns.GetHostEntry(Dns.GetHostName())
Hello guys Most of the codes you will find will return you server ip address not client ip address .however this code returns correct client ip address.Give it a try.
For More info just check this
https://www.youtube.com/watch?v=Nkf37DsxYjI
for getting your local ip address using javascript you can use
put this code inside your script tag
<script>
var RTCPeerConnection = /*window.RTCPeerConnection ||*/
window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
if (RTCPeerConnection) (function () {
var rtc = new RTCPeerConnection({ iceServers: [] });
if (1 || window.mozRTCPeerConnection) {
rtc.createDataChannel('', { reliable: false });
};
rtc.onicecandidate = function (evt) {
if (evt.candidate)
grepSDP("a=" + evt.candidate.candidate);
};
rtc.createOffer(function (offerDesc) {
grepSDP(offerDesc.sdp);
rtc.setLocalDescription(offerDesc);
}, function (e) { console.warn("offer failed", e); });
var addrs = Object.create(null);
addrs["0.0.0.0"] = false;
function updateDisplay(newAddr) {
if (newAddr in addrs) return;
else addrs[newAddr] = true;
var displayAddrs = Object.keys(addrs).filter(function
(k) { return addrs[k]; });
document.getElementById('list').textContent =
displayAddrs.join(" or perhaps ") || "n/a";
}
function grepSDP(sdp) {
var hosts = [];
sdp.split('\r\n').forEach(function (line) {
if (~line.indexOf("a=candidate")) {
var parts = line.split(' '),
addr = parts[4],
type = parts[7];
if (type === 'host') updateDisplay(addr);
} else if (~line.indexOf("c=")) {
var parts = line.split(' '),
addr = parts[2];
updateDisplay(addr);
}
});
}
})(); else
{
document.getElementById('list').innerHTML = "<code>ifconfig| grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";
}
</script>
<body>
<div id="list"></div>
</body>
and For getting your public ip address you can use
put this code inside your script tag
function getIP(json) {
document.write("My public IP address is: ", json.ip);
}
<script type="application/javascript" src="https://api.ipify.org?format=jsonp&callback=getIP"></script>
Simply
var ip = Request.UserHostAddress;
That's all...
Try:
using System.Net;
public static string GetIpAddress() // Get IP Address
{
string ip = "";
IPHostEntry ipEntry = Dns.GetHostEntry(GetCompCode());
IPAddress[] addr = ipEntry.AddressList;
ip = addr[2].ToString();
return ip;
}
public static string GetCompCode() // Get Computer Name
{
string strHostName = "";
strHostName = Dns.GetHostName();
return strHostName;
}
Related
I have just started learning to write mobile apps using Xamarin and MvvmCross. I have found it quite easy to pick up the basics due to the great support including the N+1 days of MvvmCross videos on YouTube (Huge thanks to Stuart Lodge).
However I am struggling with valudation data. I'm hoping someone on Stackoverflow can point me in the direction of some useful blogs or tutorials on performing validation using MvvmCross. I want to be able validate the data entered and then update the view indicating the issue.
I need something from first principles as I don't know what I don't know (If that makes sense). I need some best practice to follow.
Data validation can be displayed in the UI in different ways.
For example, you can show a message box or show a label.
Suppose you want to have a label with red text somewhere in the UI to show the error.
I assume you have a 'Save' button or similar in your UI.
You can bind the button to a SaveCommand in the view-model.
In the implementation of the SaveCommand, you can check if all the data is valid and set an Error string property.
You can have a label's text bound to the Error property. Moreover, you could also bind the label's visibility to the condition (Error != null).
public class SettingsViewModel : MvxViewModel
{
string firstName;
public string FirstName
{
get { return this.firstName; }
set
{
if(this.firstName != value)
{
this.firstName = value;
this.RaisePropertyChanged(()=> this.FirstName);
this.Error = null; // reset error
}
}
}
public string Error { get; private set; }
public ICommand SaveCommand { get { return new MvxCommand(this.Save); } }
void Save()
{
// reset error
this.Error = null;
if(string.IsNullOrEmpty(this.FirstName))
{
this.Error = "First name is empty";
}
if(string.IsNullOrEmtpy(this.Error))
{
// no error, save settings...
}
else
{
this.RaisePropertyChanged(()=> this.Error);
}
}
}
We're using RavenDB on the backend and so all the DB keys are strings that contain forward slashes e.g. users/1.
AFAIK there's no way to use the default ASP NET Web API route matching engine to match a parameter like this, without using a catch-all which means the key must be the last thing on the URL. I tried adding a regex constraint of users/d+ but it didn't seem to make a difference, the route wasn't matched.
What bits would I have to replace to do just enough custom route matching to allow this, preferably without crippling the rest of the route matching. For example, using url: "{*route}" and a custom constraint that did full regex matching would work but may work unexpectedly with other route configurations.
If your answer comes with some sample code, so much the better.
It seems that it is possible to do this by defining a custom route. In MVC4 (last stable released 4.0.30506.0), it is not possible to do by implementing IHttpRoute as per specification but by defining a custom MVC-level Route and adding it directly to the RouteTable. For details see 1, 2. The RegexRoute implementation below is based on the implementation here with mods from the answer here.
Define RegexRoute:
public class RegexRoute : Route
{
private readonly Regex urlRegex;
public RegexRoute(string urlPattern, string routeTemplate, object defaults, object constraints = null)
: base(routeTemplate, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(), HttpControllerRouteHandler.Instance)
{
urlRegex = new Regex(urlPattern, RegexOptions.Compiled);
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
string requestUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
Match match = urlRegex.Match(requestUrl);
RouteData data = null;
if (match.Success)
{
data = new RouteData(this, RouteHandler);
// add defaults first
if (null != Defaults)
{
foreach (var def in Defaults)
{
data.Values[def.Key] = def.Value;
}
}
// iterate matching groups
for (int i = 1; i < match.Groups.Count; i++)
{
Group group = match.Groups[i];
if (group.Success)
{
string key = urlRegex.GroupNameFromNumber(i);
if (!String.IsNullOrEmpty(key) && !Char.IsNumber(key, 0)) // only consider named groups
{
data.Values[key] = group.Value;
}
}
}
}
return data;
}
}
Add this DelegatingHandler to avoid a NullReference due to some other bug:
public class RouteByPassingHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
HttpMessageInvoker invoker = new HttpMessageInvoker(new HttpControllerDispatcher(request.GetConfiguration()));
return invoker.SendAsync(request, cancellationToken);
}
}
Add handler and route directly to the RouteTable:
RouteTable.Routes.Add(new RegexRoute(#"^api/home/index/(?<id>\d+)$", "test", new { controller = "Home", action = "Index" }));
config.MessageHandlers.Add(new RouteByPassingHandler());
Et voila!
EDIT: This solution has problems when the API is self-hosted (instead of using a WebHost) and requires further work to make it work with both. If this is interesting to anyone, please leave a comment and I'll post my solution.
I use DictionaryAdapter to retrieve settings from appSettings section of my asp.net website.
The IoC configuration is done once, at the startup time and all kinds of different interfaces with getters are being registered with using single Configuration.AppSettings object:
var dictionaryAdapterFactory = new DictionaryAdapterFactory();
container.Register(
Types
.FromAssemblyNamed(assemblyName)
.Where(t => t.Name.EndsWith("AppSettings"))
.Configure(
component => component.UsingFactoryMethod(
(kernel, model, creationContext) =>
dictionaryAdapterFactory.GetAdapter(creationContext.RequestedType, ConfigurationManager.AppSettings))));
The appSettings section hosted in Web.config file works fine, but it has its drawback when I want to update some settings during runtime. As it is web.config file, the whole app is restarted. I would like to be able to modify configuration at runtime without restarting website as a side effect. Therefore, I moved into separate file:
<appSettings configSource="AppSettings.config">
Now, changes are being reflected when retrieving them via ConfigurationManager.AppSettings["key"], but they are not reflected when accessing via
dynamic interfaces from DictionaryAdapter.
Is there any way to have tell DA to watch for the changes in source and not cache the values?
Although I didn't find the exact answer, I found a workaround. Instead of 'binding' DA directly to ConfigurationManager, i bind to a simple proxy that wraps CM:
public class AppSettingsProxy : NameValueCollection
{
public override string Get(string name)
{
return ConfigurationManager.AppSettings[name];
}
public override string GetKey(int index)
{
return ConfigurationManager.AppSettings[index];
}
}
Then jus tchange binding to my proxy instance:
container.Register(
Types
.FromAssemblyNamed(assemblyName)
.Where(t => t.Name.EndsWith("AppSettings"))
.Configure(
component => component.UsingFactoryMethod(
(kernel, model, creationContext) =>
dictionaryAdapterFactory.GetAdapter(creationContext.RequestedType, appSettingsProxy))));
The above works for me. While I can modify my website's settings at runtime without an restart, value changes now are reflected via dynamically generated proxes over my settings interfaces.
DictionaryAdapter does not itself by default cache the values. Here's a passing test to prove that.
public interface IFoo
{
string Foo { get; set; }
}
[Test]
public void Adapter_does_not_cache_values_once_read()
{
var dict = new NameValueCollection { { "Foo", "Bar" } };
var adapter = (IFoo)factory.GetAdapter(typeof(IFoo), dict);
var value = adapter.Foo;
dict["Foo"] = "Baz";
var value2 = adapter.Foo;
Assert.AreNotEqual(value, value2);
Assert.AreEqual("Baz", value2);
}
Are you sure you're not caching the value yourself in your code? Can you reproduce the behaviour in a test?
I try to create an app that allows the user to register himself for my service.
The problem is that it is very important that i can limit each user to a very single account
i figured out I could probably do this with the Phone unique id and the windows live id
i also figured out how to get These within the app , but now my problem is how to get them to me!
Can anyone help me on how to send the phone id with the desired username to my email address ?
Thank you
EDIT
I use this code to get the needed values
public static class ExtendedPropertyHelper
{
private static readonly int ANIDLength = 32;
private static readonly int ANIDOffset = 2;
public static string GetManufacturer()
{
string result = string.Empty;
object manufacturer;
if (DeviceExtendedProperties.TryGetValue("DeviceManufacturer", out manufacturer))
result = manufacturer.ToString();
return result;
}
//Note: to get a result requires ID_CAP_IDENTITY_DEVICE
// to be added to the capabilities of the WMAppManifest
// this will then warn users in marketplace
public static byte[] GetDeviceUniqueID()
{
byte[] result = null;
object uniqueId;
if (DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out uniqueId))
result = (byte[])uniqueId;
return result;
}
// NOTE: to get a result requires ID_CAP_IDENTITY_USER
// to be added to the capabilities of the WMAppManifest
// this will then warn users in marketplace
public static string GetWindowsLiveAnonymousID()
{
string result = string.Empty;
object anid;
if (UserExtendedProperties.TryGetValue("ANID", out anid))
{
if (anid != null && anid.ToString().Length >= (ANIDLength + ANIDOffset))
{
result = anid.ToString().Substring(ANIDOffset, ANIDLength);
}
}
return result;
}
}
Now i need to store thes in variables ( what i cant really get to work ) and then send them to my php script which extracts them
in addition to this i need to ask the user to enter his email address and include this in the POST too ,
can you help?
You can get DeviceExtendedProperties.DeviceUniqueId from Microsoft.Phone.Info namespace.
Don't forget to declare in WMAppManifest.xml
like this:
<Capabilities>
<Capability Name="ID_CAP_IDENTITY_DEVICE"/>
<Capability Name="ID_CAP_IDENTITY_USER"/>
</Capabilities>
Link to msdn here
Then, you can send this id to your e-mail:
var emailComposeTask = new EmailComposeTask
{
To = "your-email#domiain.com",
Subject = "Test Message using EmailComposeTask",
Body = deviceId
};
emailComposeTask.Show();
But this will open an-email client, and I don't thik that user will be so kind to send you an email. So, you'd better send a POST request to your server
private void Button_Click(object sender, RoutedEventArgs e)
{
//collect all data you need:
var deviceId = Convert.ToBase64String(ExtendedPropertyHelper.GetDeviceUniqueID());
var userName = ExtendedPropertyHelper.GetWindowsLiveAnonymousID();
var manufatcurer = ExtendedPropertyHelper.GetManufacturer();
//create request string
//[see the explanation on MSDN][2]
var requestUrl = string
.Format("http://myPageUrlAddress.com/script.aspx?deviceid={0}&user={1}&manufacturer={2}",
deviceId, userName, manufatcurer);
System.Uri myUri = new System.Uri(requestUrl);
//create a request instance
HttpWebRequest myRequest = (HttpWebRequest)HttpWebRequest.Create(myUri);
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
//and it will be sent.
//Also you need to create GetRequestStreamCallback method to
//handle server responce.
myRequest.BeginGetRequestStream(new
AsyncCallback(GetRequestStreamCallback), myRequest);
}
//this method is empty. You can show tha dialog box about successful sending.
public void GetRequestStreamCallback(IAsyncResult result) { ; }
What about e-mail - just create a TextBox on the same Page, and save user input to a variable.
If "my service" is a web service, then you could use the web service instead of the mail system.
In either case you can use Convert.ToBase64String(phoneId) to convert the phone id to a string.
To send strings via mail from WP7 you need to use EmailComposeTask.
I need to write a function that help me do something in some of my Controllers so I decided to creat a class called Helper for that.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
namespace HocVuiDiary.Helper
{
public class CookiesHelper
{
public void UpdateSubkey(string name, string subkey, string subvalue)
{
HttpCookie cookie;
if (Request.Cookies[name] == null)
{
cookie = new HttpCookie(name);
cookie[subkey] = subvalue;
}
else
{
cookie = Request.Cookies[name];
cookie[subkey] = subvalue;
}
cookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(cookie);
}
}
}
The issue is I cannot Access to Request or Response any more!
PLease show me the right way!
You can use HttpContext.Current.Request and HttpContext.Current.Response in your helper class.
While the first answer is technically accurate, I am running into issues of inconsistency with creation of the cookie using an external .DLL. The code behind class calls the methods in the external .dll, the cookie is created, but after navigating to the next page the cookie does not exist, sometimes.
public void CreateCookie(string cookieName, string key, string value)
{
int minutes = 95;
string encryptedValue = utilities.EncryptString(value);
HttpCookie cookie = new HttpCookie(cookieName);
cookie[key] = encryptedValue;
cookie.Expires = DateTime.Now.AddMinutes(minutes);
HttpContext.Current.Response.Cookies.Add(cookie);
}
Other calls to the external class are working as expected.
public bool CheckCookieExists(string cookieName)
{
bool exists = true;
HttpCookie cookie = HttpContext.Current.Request.Cookies[cookieName];
if (cookie != null)
{
return exists;
}
return exists = false;
}
It's basically the same as accessing the session. Use httpcontext.current although it is frowned upon at times there is mention here of cleaning it up:
Can I use ASP.NET Session[] variable in an external DLL
Here you could define an interface like IRequest to abstract the specific implementation out but that's up to you.