Officially supported .NET driver for Factual's public API.
In the package manager console window: Install-Package FactualDriver, or right click on your project, click manage packages, search for factual and install. Project uses nuget automatic package restore feature, please keep in mind if you don't have automatic restore enabled you would need to enable it in. In Visual Studio, enable "Allow NuGet to download missing packages during build". This setting lives under Options -> Package Manager -> General.
You can either clone the github repository, or [download as a zip or tar] (https://github.com/Factual/factual-csharp-driver/downloads) and then build.
The driver allows you to create an authenticated handle to Factual. With a Factual handle, you can send queries and get results back.
Queries are created using the Query class, which provides a fluent interface to constructing your queries.
Results are returned as the JSON returned by Factual.
First obtain free developer keys from factual.com
// Create an authenticated handle to Factual
Factual factual = new Factual(MY_KEY, MY_SECRET);
If you don't have a Factual API account yet, it's free and easy to get one.
You can optionally set a client-side request timeout for requests sent to Factual. Default values are 100000 and 300000 respectively. For example:
// Set the request timeouts to 2.5 seconds (values must be integers larger than 0 expressed in milliseconds):
factual.ConnectionTimeout = 2500;
factual.ReadTimeout = 2500;
// Set the request timeouts back to default 100000 and 300000 respectively
factual.ConnectionTimeout = null;
factual.ReadTimeout = null;
You can optionally override the default Factual API URL. Default value is http://api.v3.factual.com. For example:
// Set the base URL to http://fakeurl.factual.com
factual.FactualApiUrlOverride = "http://fakeurl.factual.com";
// Set the base URL back to default http://api.v3.factual.com
factual.FactualApiUrlOverride = null;
If you are going to clone or download the repository you will have access to integration tests which can also be used as documentation. To setup your tests you would need to add your factual key and factual secret key to the FactualDriver.Tests\app.config.
// 3 random records from Factual's Places table:
factual.Fetch("places", new Query().Limit(3))
// Entities that match a full text search for Sushi in Santa Monica:
factual.Fetch("places", new Query().Search("Sushi Santa Monica"));
// Entity from Factual's Places table with ID 03c26917-5d66-4de9-96bc-b13066173c65:
factual.GetRow("places", "03c26917-5d66-4de9-96bc-b13066173c65";
You can query Factual for entities located within a geographic area. For example:
// Build a Query that finds entities located within 5000 meters of a latitude, longitude
new Query().WithIn(new Circle(34.06018, -118.41835, 5000));
You can have Factual sort your query results for you, on a field by field basis. Simple example:
// Build a Query to find 10 random entities and sort them by name, ascending:
new Query().Limit(10).SortAsc("name");
You can specify more than one sort, and the results will be sorted with the first sort as primary, the second sort or secondary, and so on:
// Build a Query to find 20 random entities, sorted ascending primarily by region, then by locality, then by name:
var q = new Query()
.Limit(20)
.SortAsc("region")
.SortAsc("locality")
.SortDesc("name");
You can use limit and offset to support basic results paging. For example:
// Build a Query with offset of 150, limiting the page size to 10:
new Query().Limit(10).Offset(150);
By default your queries will return all fields in the table. You can use the only modifier to specify the exact set of fields returned. For example:
// Build a Query that only gets the name, tel, and category fields:
new Query().Only("name", "tel", "category");
Parameter | Description | Example |
---|---|---|
filters | Restrict the data returned to conform to specific conditions. | q.Field("name").BeginsWith("Starbucks") |
include count | Include a count of the total number of rows in the dataset that conform to the request based on included filters. Requesting the row count will increase the time required to return a response. The default behavior is to NOT include a row count. When the row count is requested, the Response object will contain a valid total row count via .getTotalRowCount(). | q.IncludeRowCount() |
geo | Restrict data to be returned to be within a geographical range based. | (See the section on Geo Filters) |
limit | Maximum number of rows to return. Default is 20. The system maximum is 50. For higher limits please contact Factual, however consider requesting a download of the data if your use case is requesting more data in a single query than is required to fulfill a single end-user's request. | q.Limit(10) |
search | Full text search query string. |
Find "sushi": q.Search("sushi")
Find "sushi" or "sashimi":
Find "sushi" and "santa" and "monica": |
offset | Number of rows to skip before returning a page of data. Maximum value is 500 minus any value provided under limit. Default is 0. | q.Offset(150) |
only | What fields to include in the query results. Note that the order of fields will not necessarily be preserved in the resulting JSON response due to the nature of JSON hashes. | q.Only("name", "tel", "category") |
sort | The field (or secondary fields) to sort data on, as well as the direction of sort. Supports $distance as a sort option if a geo-filter is specified. Supports $relevance as a sort option if a full text search is specified either using the q parameter or using the $search operator in the filter parameter. By default, any query with a full text search will be sorted by relevance. Any query with a geo filter will be sorted by distance from the reference point. If both a geo filter and full text search are present, the default will be relevance followed by distance. | q.SortAsc("name").SortDesc("$distance") |
The driver supports various row filter logic. Examples:
// Build a query to find places whose name field starts with "Starbucks"
new Query().Field("name").BeginsWith("Starbucks");
// Build a query to find places with a blank telephone number
new Query().Field("tel").Blank();
Predicate | Description | Example |
---|---|---|
equal | equal to | q.Field("region").Equal("CA") |
notEqual | not equal to | q.Field("region").NotEqual("CA") |
search | full text search | q.Field("name").Search("fried chicken") |
in | equals any of | q.Field("region").In("MA", "VT", "NH", "RI", "CT") |
notIn | does not equal any of | q.Field("locality").NotIn("Los Angeles") |
beginsWith | begins with | q.Field("name").BeginsWith("b") |
notBeginsWith | does not begin with | q.Field("name").NotBeginsWith("star") |
beginsWithAny | begins with any of | q.Field("name").BeginsWithAny("star", "coffee", "tull") |
notBeginsWithAny | does not begin with any of | q.Field("name").NotBeginsWithAny("star", "coffee", "tull") |
blank | is blank or null | q.Field("tel").Blank() |
notBlank | is not blank or null | q.Field("tel").NotBlank() |
greaterThan | greater than | q.Field("rating").GreaterThan(7.5) |
greaterThanOrEqual | greater than or equal to | q.Field("rating").GreaterThanOrEqual(7.5) |
lessThan | less than | q.Field("rating").LessThan(7.5) |
lessThanOrEqual | less than or equal to | q.Field("rating").LessThanOrEqual(7.5) |
includes | includes | q.Field("category_ids").Includes(10) |
includesAny | includes any | q.Field("category_ids").IncludesAny(10, 100) |
Queries support logical AND'ing your row filters. For example:
// Build a query to find entities where the name begins with "Coffee" AND the telephone is blank:
Query q = new Query();
q.And(
q.Field("name").BeginsWith("Coffee"),
q.Field("tel").Blank()
);
Note that all row filters set at the top level of the Query are implicitly AND'ed together, so you could also do this:
new Query()
.Field("name").BeginsWith("Coffee")
.Field("tel").Blank();
Queries support logical OR'ing your row filters. For example:
// Build a query to find entities where the name begins with "Coffee" OR the telephone is blank:
Query q = new Query();
q.Or(
q.Field("name").BeginsWith("Coffee"),
q.Field("tel").Blank());
You can nest AND and OR logic to whatever level of complexity you need. For example:
// Build a query to find entities where:
// (name begins with "Starbucks") OR (name begins with "Coffee")
// OR
// (name full text search matches on "tea" AND tel is not blank)
Query q = new Query();
q.Or(
q.Or(
q.Field("name").BeginsWith("Starbucks"),
q.Field("name").BeginsWith("Coffee")
),
q.And(
q.Field("name").Search("tea"),
q.Field("tel").NotBlank()
)
);
The driver fully supports Factual's Crosswalk feature, which lets you "crosswalk" the web and relate entities between Factual's data and that of other web authorities.
(See the Crosswalk API for more background.)
Crosswalk requests are treated as any other table read, as seen in the example below. All query-related features apply.
// Get all Crosswalk data for a specific Places entity, using its Factual ID:
var response = factual.Fetch("crosswalk", new Query().Field("factual_id").Equal("97598010-433f-4946-8fd5-4a6dd1639d77"));
Use the common query structure to add known attributes to the query:
//Build the query
MatchQuery matchQuery = new MatchQuery()
.Add("name", "McDonalds")
.Add("address", "10451 Santa Monica Blvd")
.Add("region", "CA")
.Add("postcode", "90025");
And then see if we found a match:
String id = Factual.Match("places", matchQuery);
// id = null means no match, id = some factual id means there is a match
The driver fully supports Factual's Resolve feature, which lets you start with incomplete data you may have for an entity, and get potential entity matches back from Factual.
Each result record will include a confidence score ("similarity"), and a flag indicating whether Factual decided the entity is the correct resolved match with a high degree of accuracy ("resolved").
For any Resolve query, there will be 0 or 1 entities returned with "resolved"=true. If there was a full match, it is guaranteed to be the first record in the JSON response.
(See the Resolve Blog for more background.)
The resolve method gives you the one full match if there is one, or null:
// Get the entity that is a full match, or null:
var response = Factual.Fetch("places", new ResolveQuery()
.Add("name", "Buena Vista")
.Add("latitude", 34.06)
.Add("longitude", -118.40));
Driver fully supports Factual's World Geographies. For a complete documentation please refer to http://developer.factual.com/display/docs/World+Geographies.
//Arrange
var query = new Query();
query.And
(
query.Field("name").Equal("philadelphia"),
query.Field("country").Equal("us"),
query.Field("placetype").Equal("locality")
);
//Act
var response = Factual.Fetch("world-geographies", query);
A Raw GET request can be used to make just about any kind of query against Factual, including features we've yet to design. public string RawQuery(string path, Dictionary<string, object> queryParameters)
You can run a GET request against the specified endpoint path, using the given parameters and your OAuth credentials. Returns the raw response body returned by Factual. The necessary URL base will be automatically prepended to path. If you need to change it, e.g. to make requests against a development instance of the Factual service, please set FactualApiUrlOverride property.
//GET only the name and category fields from places table, including the row count in the response:
//http://api.v3.factual.com/t/places?select=name,category&include_count=True
string result = Factual.RawQuery("t/places", new Dictionary<string, object>
{
{"select", "name,category"},
{"include_count", true}
});
dynamic json = JsonConvert.DeserializeObject(result);
//GET first 5 restaurants in the Food & Beverage category:
//http://api.v3.factual.com/t/restaurants?filters={"category":"Food+&+Beverage"}&limit=5
string result = Factual.RawQuery("t/restaurants", new Dictionary<string, object>
{
{
"filters", new Dictionary<string, object>
{
{
"category", "Food & Beverage"
}
}
},
{
"limit", 5
}
});
dynamic json = JsonConvert.DeserializeObject(result);
//GET first 5 deals in Los Angeles area:
//http://api.v3.factual.com/places/monetize?filters={"place_locality":"Los Angeles"}
string result = Factual.RawQuery("places/monetize", new Dictionary<string, object>
{
{
"filters", new Dictionary<string, object>
{
{
"place_locality", "Los Angeles"
}
}
},
{
"limit", 5
}
});
dynamic json = JsonConvert.DeserializeObject(result);
Note that the above examples demonstrate the ability to construct read queries using the raw read feature. However, in practice, the recommendation is to always use the convenience classes for features which are supported.
A Raw GET Encoded URL request can be used to make just about any kind of query against Factual, including features we've yet to design. public string RawQuery(string path, string queryParameters)
You can run a GET request against the specified endpoint path, using the given parameters and your OAuth credentials. Returns the raw response body returned by Factual. The necessary URL base will be automatically prepended to path. If you need to change it, e.g. to make requests against a development instance of the Factual service, please set FactualApiUrlOverride property. Developer is entirly responsible for correct query formatting and URL encoding.
//GET only the name and category fields from places table, including the row count in the response:
//http://api.v3.factual.com/t/places?select=name,category&include_count=True
string result = Factual.RawQuery("t/places", "select=name,category&include_count=True");
dynamic json = JsonConvert.DeserializeObject(result);
A Raw POST request can be used to make just about any kind of query against Factual, including features we've yet to design. public string RequestPost(string path, Dictionary<string, object> queryParameters, Dictionary<string, object> postData)
You can run a POST request against the specified endpoint path, using the given parameters and your OAuth credentials. Returns the raw response body returned by Factual. The necessary URL base will be automatically prepended to path. If you need to change it, e.g. to make requests against a development instance of the Factual service, please set FactualApiUrlOverride property.
//GET only the name and category fields from places table, including the row count in the response:
//http://api.v3.factual.com/t/us-sandbox/submit?values={"name":"Factual+North","address":"1+North+Pole","latitude":90,"longitude":0}&user=test_driver_user
string result = Factual.RequestPost("/t/us-sandbox/submit", new Dictionary<string, object>
{
{
"values", JsonConvert.SerializeObject(new Dictionary<string, object>
{
{
"name", "Factual North"
},
{
"address", "1 North Pole"
},
{
"latitude", 90
},
{
"longitude", 0
}
})
},
{
"user", "test_driver_user"
}
}, new Dictionary<string, object>());
dynamic json = JsonConvert.DeserializeObject(result);
A Raw POST request can be used to make just about any kind of query against Factual, including features we've yet to design. public string RequestPost(string path, string queryParameters, string postData)
You can run a POST request against the specified endpoint path, using the given parameters and your OAuth credentials. Returns the raw response body returned by Factual. The necessary URL base will be automatically prepended to path. If you need to change it, e.g. to make requests against a development instance of the Factual service, please set FactualApiUrlOverride property. Developer is entirly responsible for correct query formatting and URL encoding.
//GET only the name and category fields from places table, including the row count in the response:
//http://api.v3.factual.com/t/us-sandbox/submit?values={"name":"Factual North","address":"1 North Pole","latitude":90,"longitude":0}&user=test_driver_user
string result = Factual.RequestPost("/t/us-sandbox/submit", "values={"name":"Factual North","address":"1 North Pole","latitude":90,"longitude":0}&user=test_driver_user", "");
dynamic json = JsonConvert.DeserializeObject(result);
To see a full trace of debug information for a request and response, turn debug mode on. There are two ways to do so:
Use the Factual constructor to enable debug on a new instance:
Factual factual = new Factual(key, secret, true);
or modify an existing instance to toggle debug mode on and off for individual requests:
factual.Debug = true;
factual.Fetch(...);
factual.Debug = false;
Debug information will be printed to output window, with detailed request and response information.
The driver fully supports Factual's Facets feature, which lets you return row counts for Factual tables, grouped by facets of data. For example, you may want to query all businesses within 1 mile of a location and for a count of those businesses by category.
// Returns a count of Starbucks by country
var response = factual.Fetch("global", new FacetQuery("country").Search("starbucks"));
Not all fields are configured to return facet counts. To determine what fields you can return facets for, use the schema call. The faceted attribute of the schema will let you know.
Parameter | Description | Example |
---|---|---|
select | The fields for which facets should be generated. The response will not be ordered identically to this list, nor will it reflect any nested relationships between fields. | new Facet("region", "locality"); |
min count | For each facet value count, the minimum count it must show in order to be returned in the response. Must be zero or greater. The default is 1. | f.MinCountPerFacetValue(2) |
limit | The maximum number of unique facet values that can be returned for a single field. Range is 1-250. The default is 25. | f.MaxValuesPerFacet(10) |
filters | Restrict the data returned to conform to specific conditions. | f.Field("name").BeginsWith("Starbucks") |
include count | Include a count of the total number of rows in the dataset that conform to the request based on included filters. Requesting the row count will increase the time required to return a response. The default behavior is to NOT include a row count. When the row count is requested, the Response object will contain a valid total row count via .GetTotalRowCount(). | f.IncludeRowCount() |
geo | Restrict data to be returned to be within a geographical range. | (See the section on Geo Filters) |
search | Full text search query string. |
Find "sushi": f.Search("sushi")
Find "sushi" or "sashimi":
Find "sushi" and "santa" and "monica": |
The driver fully supports Factual's Multi feature, which enables making multiple requests on the same connection. Queue responses using QueueFetch, and send all queued reads using SendQueueRequests. The SendQueueRequests method requests all reads queued since the last SendQueueRequests. The responses from the multi request are returned in a list, corresponding to the same order in which they were queued.
// Fetch a multi response
factual.QueueFetch("places", new Query().Field("region").Equal("CA"));
factual.QueueFetch("places", new Query().Limit(1));
var multiResponse = factual.SendQueueRequests();
You can also en-queue monetize with Factual.QueueFetchMonetize(Query query)
By default driver prepends query keys with a "q" and then the number of the query. You can also specify your own multi key so that response data objects will have queries returned with you own prepended key. To do that you would need to set Factual.MultiQuery.Key property before calling QueueFetch methods.
//Arrange
Factual.MultiQuery.Key = "test";
Factual.QueueFetch("places", new Query().Field("region").Equal("CA"));
Factual.QueueFetch("places", new Query().Limit(1));
The driver supports Factual's Diffs feature, which enables Factual data update downloads.
The Fetch method gives the diff data:
// Request all diffs from the US Places dataset that were generated in a for window of just over 24 minutes, on Fri, 07 Dec 2012 13:41:03 -0800
DiffsQuery diffs = new DiffsQuery()
.After(1354916463822)
.Before(1354917903834);
var response = Factual.Fetch("places-us", diffs);
The driver fully supports Factual's Geopulse feature, which provides point-based access to geographic attributes: you provide a long/lat coordinate pair, we provide everything we can know about that geography.
The geopulse method fetches results based on the given point:
var respponse = factual.Geopulse(new Geopulse(new Point(latitude, longitude))
.Only("income", "housing"));
Parameter | Description | Example |
---|---|---|
geo | A geographic point around which information is retrieved. | new Point(latitude, longitude) |
select | What fields to include in the query results. Note that the order of fields will not necessarily be preserved in the resulting JSON response due to the nature of JSON hashes. | geopulse.Only("commercial_density", "commercial_profile") |
The driver fully supports Factual's Reverse Geocoder feature, which returns the nearest valid address given a longitude and latitude.
The ReverseGeocode method fetches results based on the given point:
var response = factual.ReverseGeocode(new Point(latitude, longitude));
The driver fully supports Factual's Monetize feature, which enables you to find deals for places in Factual's Global Places database. Use the Query object to specify filters on which to run the monetize request.
The monetize method fetches deals based on a specified query:
var response = Factual.Monetize(new Query().Field("place_locality").Equal("Los Angeles"));
Parameter | Description | Example |
---|---|---|
geo | A valid geographic point for which the closest address is retrieved. | new Point(latitude, longitude) |
#Submit
NOTICE: At the current time, this API call is ONLY compatible with places-v3. Please see the the migration page for more details.
Submit allows you to add a record to Factual, or update an existing record. To delete a record, see Flag.
Factual does not currently support deleting entity attributes.
Strictly speaking, our systems do an 'UPSERT' -- we determine if the entity already exists, and return the Factual ID as part of the result object. You can determine whether the entity you submitted is new However, it's always a good idea to obtain the Factual ID from a Submit Result, and store it against the submitted entity. See below for specific examples.
In a few cases (such as if the Factual ID you submitted has been deprecated), we may return a Factual ID different from the one you submitted. It is good practice to check.
The only difference between updating an extant record and adding a new one is the inclusion of the Factual ID.
Parameter | Description | Example |
---|---|---|
values | A JSON hash field of names and values to be added to a Factual table | Update a value: s.setValue("longitude", 100) Make a value blank: s.removeValue("longitude") |
user | An arbitrary token representing the user submitting the data. | new Metadata().User("my_username") |
comment | Any english text comment that may help explain your corrections. | metadata.Comment("my comment") |
reference | A reference to a URL, title, person, etc. that is the source of this data. | metadata.Reference("http://...") |
Add data to Factual's us-sandbox table:
// Entity data
Submit values = new Submit();
values.AddValue("name", "Starbucks");
values.AddValue("address", "123 Testing Blvd.");
values.AddValue("locality", "Los Angeles");
values.AddValue("region", "CA");
values.AddValue("postcode", "90049");
// An end user id is required
Metadata metadata = new Metadata().User("some_user_id");
// Run the Submit
var response = factual.Submit("us-sandbox", values, metadata);
Determine whether Factual considered your Submit to be a new entity:
dynamic json = JsonConvert.DeserializeObject(response);
Assert.IsTrue((bool)json.response.new_entity);
Correct the latitude and longitude of a specific entity in Factual's us-sandbox table:
Submit submit = new Submit()
.AddValue("latitude", -79.431708)
.AddValue("longitude", 43.641605);
factual.Submit("us-sandbox",
"f33527e0-a8b4-4808-a820-2686f18cb00c",
submit,
new Metadata().user("some_user_id"));
Correct the business name of a specific entity in Factual's us-sandbox table:
Submit submit = new Submit()
.setValue("name", "The New & Improved Tyler's Austin");
factual.Submit("us-sandbox",
"f33527e0-a8b4-4808-a820-2686f18cb00c",
submit,
new Metadata().user("some_user_id"));
Add a neighborhood to a specific entity in Factual's us-sandbox table:
Submit submit = new Submit()
.AddValue("neighborhood", "Downtown");
factual.Submit("us-sandbox",
"f33527e0-a8b4-4808-a820-2686f18cb00c",
submit,
new Metadata().user("some_user_id"));
#Clear
NOTICE: At the current time, this API call is ONLY compatible with places-v3. Please see the the migration page for more details.
Clear allows you to clear one or more attributes from a Factual record.
Parameter | Description | Required | Example |
---|---|---|---|
user | An arbitrary token representing the end user who is submitting the data. | Yes | new Metadata().User("my_username") |
fields | The attribute fields to be cleared. | Yes | Clear.AddField("longitude") |
comment | Any english text comment that may help explain the submit. | No | Metadata.Comment("my comment") |
reference | A reference to a URL, title, person, etc. that is the source of the submitted data. | No | Metadata.Reference("http://...") |
Clear the value of name, address, locality, and region in an existing entity:
String factualId = "1d93c1ed-8cf3-4d58-94e0-05bbcd827cba";
Clear clear = new Clear();
clear.AddField("name");
clear.AddField("address");
clear.AddField("locality");
clear.AddField("region");
var response = Factual.Clear("us-sandbox", factualId, clear, new Metadata().User("test_driver_user"));
Overloaded: Clear the value of name, address, locality, and region in an existing entity:
String factualId = "1d93c1ed-8cf3-4d58-94e0-05bbcd827cba";
Clear clear = new Clear("name", "address", "locality", "region");
var response = Factual.Clear("us-sandbox", factualId, clear, new Metadata().User("test_driver_user"));
#Flag NOTICE: At the current time, this API call is ONLY compatible with places-v3. Please see the the migration page for more details.
The Flag feature provides developers and editorial teams the ability to 'flag' problematic entities in tables for Factual editorial review. Use this feature to request an entity be deleted, flag an entity as a dupe or spam, note it does not exist, or just ask the Factual editors to check it out.
Calls to Flag require an indication of the problem type, the end user who is reporting the problem, and the Factual ID of the entity being flagged.
Parameter | Description | Example |
---|---|---|
problem | One of: duplicate, inaccurate, inappropriate, nonexistent, spam, or other. | factual.FlagDuplicate(table, factualId, metadata)
factual.FlagInaccurate(table, factualId, metadata) factual.FlagInappropriate(table, factualId, metadata) factual.FlagNonExistent(table, factualId, metadata) factual.FlagSpam(table, factualId, metadata) factual.FlagClosed(table, factualId, metadata) factual.FlagOther(table, factualId, metadata) |
user | An arbitrary token representing the user flagging the data. | Metadata metadata = new Metadata().User("my_username") |
comment | Any english text comment that may help explain your corrections. | metadata.Comment("my comment") |
reference | A reference to a URL, title, person, etc. that is the source of this data. | metadata.Reference("http://www.example.com") |
Flag a row as spam:
factual.FlagSpam("us-sandbox",
"e16ef265-b9be-437f-b7e2-ded852e3920e",
new Metadata().User("some_user_id"));
Flag a row as innacurate, and also include a comment and a reference:
Metadata metadata = new Metadata()
.Comment("Recently revised by IAAC")
.Reference("http://www.example.com");
factual.FlagInaccurate("us-sandbox",
"e16ef265-b9be-437f-b7e2-ded852e3920e",
metadata);
If Factual's API indicates an error, a FactualApiException unchecked Exception will be thrown. It will contain details about the request you sent and the error that Factual returned.
Here is an example of catching a FactualApiException and inspecting it:
Factual badness = new Factual("BAD_KEY", "BAD_SECRET");
try
{
badness.Fetch("places", new Query().Field("country").Equal(true));
}
catch (FactualApiException ex)
{
Console.WriteLine("Requested URL: " + ex.Url);
Console.WriteLine("Error Status Code: " + ex.StatusCode);
Console.WriteLine("Error Response Message: " + ex.Response);
}
This driver is thread safe.
This driver may be used in a VB.NET project as follows:
1. Add FactualDriver.dll using Package Manger Console (PM> Install-Package FactualDriver);
2. Add 'Imports FactualDriver' statement;
3. Create an instance of Factual object with oAuthKey and oAuthSecret.
Imports FactualDriver
Module Module1
Sub Main()
Dim oFactualDriver As New Factual("oAuthKey", "oAuthSecret")
Dim result As New String(oFactualDriver.FetchRow("places", "03c26917-5d66-4de9-96bc-b13066173c65"))
Console.WriteLine(result)
End Sub
End Module
For more code examples:
-
See the integration tests in FactualDriver.Tests/FactualIntegrationTests.cs
If you think you've identified a specific bug in this driver, please file an issue in the github repo. Please be as specific as you can, including:
- What you did to surface the bug
- What you expected to happen
- What actually happened
- Detailed stack trace and/or line numbers
If you are having any other kind of issue, such as unexpected data or strange behaviour from Factual's API (or you're just not sure WHAT'S going on), please contact us through GetSatisfaction.