1

I have created a CLR User-defined function to look up the latitude and longitude information of a location using Google geocode. The function is as follows:

using System;
using System.Net;
using System.Xml.XPath;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class latlong
{
[Microsoft.SqlServer.Server.SqlFunction]

public static SqlString GetLatLong(string address, string city, string state, string zip)
{
    string latitude = "#NA", longitude = "#NA";
    string url = "http://maps.googleapis.com/maps/api/geocode/xml?address=";
    string[] addresssplit = Regex.Split(address, @"\W+");
    if (address != "NULL")
        for (int i = 0; i < addresssplit.Length; i++)
            url = url + addresssplit[i] + "+";
    if (city != "NULL")
    {
        if (state != "NULL")
        {
            if (zip != "NULL") url = url + city + "+" + state + "+" + zip;
            else url = url + city + "+" + state;
        }
        else
        {
            if (zip!= "NULL") url = url + city + "+" + zip;
            else url = url + city;
        }
    }
    else
    {
        if (state != "NULL")
        {
            if (zip != "NULL") url = url + state + "+" + zip;
            else url = url + state;
        }
        else
        {
            if (zip != "NULL") url = url + zip;
        }
    }
    url = url + "&sensor=false";

    WebResponse response = null;
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "GET";
    response = request.GetResponse();
    if (response != null)
    {
        XPathDocument document = new XPathDocument(response.GetResponseStream());
        XPathNavigator navigator = document.CreateNavigator();
        XPathNodeIterator statusIterator = navigator.Select("/GeocodeResponse/status");
        while (statusIterator.MoveNext())
            if (statusIterator.Current.Value != "OK")
            {
                Thread.Sleep(1000);
                return new SqlString("OQL, OQL");
            }
        XPathNodeIterator resultIterator = navigator.Select("/GeocodeResponse/result");
        while (resultIterator.MoveNext())
        {
            XPathNodeIterator geometryIterator = resultIterator.Current.Select("geometry");
            while (geometryIterator.MoveNext())
            {
                XPathNodeIterator locationIterator = geometryIterator.Current.Select("location");
                while (locationIterator.MoveNext())
                {
                    XPathNodeIterator latIterator = locationIterator.Current.Select("lat");
                    while (latIterator.MoveNext())
                        latitude = latIterator.Current.Value;
                    XPathNodeIterator longIterator = locationIterator.Current.Select("long");
                    while (longIterator.MoveNext())
                        longitude = longIterator.Current.Value;
                }
            }
        }
    }
    Thread.Sleep(1000);
    return new SqlString(latitude + ", " + longitude);
}
}

I have built and deployed the function successfully. So I tried executing the function in the SQL server as follows:

SELECT dba.dbo.GetLatLong('3366 Cherry Avenue','Zion','WI','54963')

When I do so the following security expression is raised

A .NET Framework error occurred during execution of user-defined routine or aggregate "GetLatLong": 
System.Security.SecurityException: Request for the permission of type 'System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
System.Security.SecurityException: 
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessPermission.Demand()
at System.Net.HttpWebRequest..ctor(Uri uri, ServicePoint servicePoint)
at System.Net.HttpRequestCreator.Create(Uri Uri)
at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
at latlong.GetLatLong(String address, String city, String state, String zip).

I can see that there is a problem with the security permissions. But beyond that I do not see the way to fix the exception.

Any help is appreciated.

3
  • what kind of app is this? Commented Jun 13, 2013 at 14:07
  • i meant winforms, aspnet, winphone, etc. Commented Jun 13, 2013 at 17:05
  • I know in business there are always reasons for things. Unfortunately I have to ask was putting this logic in to a database the best way to solve the problem? I don't see any code related to Data Access. My first guess is you had a procedure before that looked it up in a database and you are maintaining compatibility, but it still seems strange. Having a database connect to the internet directly is usually a security "No, No". Commented Jun 13, 2013 at 17:48

3 Answers 3

2

In order to make network request from sql clr code the assembly must be configured with EXTERNAL_ACCESS permission. You can set the specified permission by using CREATE ASSEMBLY statement

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it fixed the error. I had to add it to the CREATE ASSEMBLY.
0

You need to declare your procedure with EXTERNAL_ACCESS* permission:

EXTERNAL_ACCESS assemblies have the same permissions as SAFE assemblies, with the additional ability to access external system resources such as files, networks, environmental variables, and the registry.

(My emphasis)


*Or UNSAFE, but I'd say EXTERNAL_ACCESS unless or until it's demonstrated that you actually needed UNSAFE.

Comments

0

Run this in sql:

ALTER DATABASE databasename SET TRUSTWORTHY ON
USE master
GO
grant external access assembly to [domain\computerusername]
grant external access assembly to sa

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.