403被禁止。 WebException未处理.NET

时间:2015-09-18 14:25:16

标签: c# distance webrequest http-status-code-403

我编写了一个类来计算两个坐标之间的距离。但是一旦我运行该项目,它就会出错:

  

WebException未处理。

     

System.Xml.dll中发生未处理的“System.Net.WebException”类型异常

     

其他信息:远程服务器返回错误:(403)禁止。

我的代码是:

public Tuple<double, double> GetCoords(string Streetnumber, string Streetname, string Cityname, string Country)
{
    XmlDocument doc = new XmlDocument();
    string clientId = "///"; =
    string key = "//";
    string address = Streetnumber + "+" + Streetname + ",+" + Cityname + ",+" + Country;

    var urlRequest = "/maps/api/geocode/xml?address=" + address + "&client=" + clientId;
    System.Security.Cryptography.HMACSHA1 myhmacsha1 = new System.Security.Cryptography.HMACSHA1();
    myhmacsha1.Key = Convert.FromBase64String(key);
    var hash = myhmacsha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(urlRequest));
    string signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_");
    WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;

    doc.Load("https://maps.googleapis.com/maps/api/geocode/xml?address=" + address + "&client=" + clientId + "&signature=" + signature);

    string longitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lng").InnerText;
    double lng = LongitudePlace(longitude);
    string latitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lat").InnerText;
    double lat = LatitudePlace(latitude);
    return Tuple.Create(lng, lat);
}

我还有一些其他方法,但它们与此问题无关。错误发生在:

doc.Load("https://maps.googleapis.com/maps/api/geocode/xml?address=" + address + "&client=" + clientId + "&signature=" + signature);

也许这很容易解决,但我尝试了很多东西。我的clientID是正确的,如果我没有误会,也是console.developer.google.com上的密钥。

我尝试了“1600”,“Amphitheatre + Parkway”,“Mountain + View”,“CA”的测试地址。

如何解决错误?

1 个答案:

答案 0 :(得分:0)

看起来您的签名可能无法正确形成。具体来说,它缺少URL的一部分。以下是使用Google提供的代码对代码进行编辑的代码的编辑版本。代码可以找到here

<强>代码

public Tuple<double, double> GetCoords(string streetNumber, string streetName, string cityName, string country)
{
    XmlDocument doc = new XmlDocument();
    string clientId = "gme-" + "///";
    string key = "//"; //Note this is NOT your API key, it's the Client Secret
    string address = streetNumber + "+" + streetName + ",+" + cityName + ",+" + country;

    WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;

    doc.Load(Sign("https://maps.googleapis.com/maps/api/geocode/xml?address=" + address + "&client=" + clientId, key));

    string longitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lng").InnerText;
    double lng = LongitudePlace(longitude);
    string latitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lat").InnerText;
    double lat = LatitudePlace(latitude);
    return Tuple.Create(lng, lat);
}

//From the Google
public static string Sign(string url, string keyString) 
{
    ASCIIEncoding encoding = new ASCIIEncoding();

    // converting key to bytes will throw an exception, need to replace '-' and '_' characters first.
    string usablePrivateKey = keyString.Replace("-", "+").Replace("_", "/");
    byte[] privateKeyBytes = Convert.FromBase64String(usablePrivateKey);

    Uri uri = new Uri(url);
    byte[] encodedPathAndQueryBytes = encoding.GetBytes(uri.LocalPath + uri.Query);

    // compute the hash
    HMACSHA1 algorithm = new HMACSHA1(privateKeyBytes);
    byte[] hash = algorithm.ComputeHash(encodedPathAndQueryBytes);

    // convert the bytes to string and make url-safe by replacing '+' and '/' characters
    string signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_");

    // Add the signature to the existing URI.
    return uri.Scheme+"://"+uri.Host+uri.LocalPath + uri.Query +"&signature=" + signature;
}