A C# library for querying the Stack Exchange API.
Features | Installation | Usage | Contributing | Credits
- Supports all endpoints of the Stack Exchange API version
2.2
. - .NET Standard
1.1
compliant. Task<T>
based; asynchronous.- Provides helper methods for implicit authentication.
To install this library via NuGet (package),
PM> Install-Package RavinduL.SEStandard -Version 1.0.0-rc
To install the NuGet package via the .NET Core CLI,
PS> dotnet add package RavinduL.SEStandard --version 1.0.0-rc
Should you prefer to manually build the library from its source instead, please refer to the Contributing section for instructions on how to do so.
Sub-topics: Basic Usage | Implicit Authentication | Concerns | Customization
-
Step 1: Create a new instance of the
StackExchangeClient
class, -
using RavinduL.SEStandard; using Scopes = RavinduL.SEStandard.Models.Scopes; // Create an anonymous client to access endpoints of the API that don't require authentication. var client = new StackExchangeClient(); // -- or -- // Create an non-anonymous client to be able to access all endpoints of the API. var client = new StackExchangeClient ( clientId: 1234, key: "key", scopes: Scopes.ReadInbox | Scopes.PrivateAccess | Scopes.WriteAccess, // (optional) // If you've got an custom access token stored away, that you'd like to re-use, accessToken: "accessToken" // Ensure that the specified scopes correspond to the custom access token. );
-
Step 2: Use the newly created
StackExchangeClient
object to access data on the Stack Exchange API, -
// To retrieve and list the 10 highest voted questions on Stack Overflow, using Order = RavinduL.SEStandard.Models.Order; using QuestionSort = RavinduL.SEStandard.Models.QuestionSort; var query = await client.Questions.GetAsync ( site: "stackoverflow", pagesize: 10, order: Order.Descending, sort: QuestionSort.Votes ); foreach (var question in query.Items) { Console.WriteLine($"{question.Title} (score: {question.Score})"); }
To participate in the implicit authentication flow, a non-anonymous StackExchangeClient
object is required.
In this contrived example, the WebBrowser
class represents a web browser that, upon navigation or redirection to a new webpage, fires its event NavigationDelegate Navigated
whose arguments contain the new URL (as a property identified as NewUrl
). The StackExchangeClient
object is identified as client
.
-
Step 1: Retrieve the implicit authentication URL, and direct the user to it,
-
var url = client.GetImplicitAuthenticationUrl(); // Direct the user to uri WebBrowser.Navigate(url);
The user will be presented with a webpage with options to login to their Stack Exchange account. During the process of logging in, the user will be redirected multiple times.
-
Step 2: Handle redirections from the implicit authentication URL until authentication succeeds or fails.
-
NavigationDelegate WebBrowser_Navigated = null; WebBrowser_Navigated = (sender, eventArgs) => { var result = client.TryImplicitAuthentication(eventArgs.NewUrl); if (result.State == ImplicitAuthenticationState.Successful) { // The client is now authenticated, and has a valid access token. Console.WriteLine($"Access Token: {result.AccessToken}"); Console.WriteLine(client.HasAccessToken); // True // Unsubscribe from the event. WebBrowser.Navigated -= WebBrowser_Navigated; } // Do not use else here, as ImplicitAuthenticationState.Ignored should be ignored. else if (result.State == ImplicitAuthenticationState.Failed) { Console.WriteLine("Authentication failed"); // Unsubscribe from the event. WebBrowser.Navigated -= WebBrowser_Navigated; } }; WebBrowser.Navigated += WebBrowser_Navigated;
-
Rate Limiting
Read about the request throttling policies of the Stack Exchange API at api.stackexchange.com/docs/throttle.It is the reponsibility of all applications that use this library, to respect the rate limits imposed by the Stack Exchange API when making requests to it, themselves, in lieu of this library not doing so. The
Wrapper<T>
object (Stack Exchange documentation) in which all API responses are wrapped contains the propertiesBackOff
,QuotaMax
, andQuotaRemaining
, that are relevant in this regard. -
Custom Access Tokens
When a non-anonymousStackExchangeClient
object is constructed with a custom access token specified, ensure that it is valid. TheStackExchangeClient
object does not perform validation of the access token. -
min
andmax
Parameters
Themin
andmax
parameters that specify minimum and maximum values that requests are sorted by, areobject
s. To use them, make sure to assign data of the appropriate type (i.e.DateTime
s for dates,int
for numeric values, etc.)
The functionality of the StackExchangeClient
object can be tweaked in numerous ways by sub-classing it.
-
By default, this library uses the Json.NET library for deserializing the JSON responses from the Stack Exchange API. Should you wish to deserialize JSON some other way,
using RavinduL.SEStandard; using RavinduL.SEStandard.Serialization; // Sub-class the IJsonDeserializer class. public class CustomJsonDeserializer : IJsonDeserializer { public T Deserialize<T>(string json) { // Add logic to deserialize JSON to an object of type T here. } } // Sub-class the StackExchangeClient class, and override the CreateJsonDeserializer method. public class CustomStackExchangeClient : StackExchangeClient { public override IJsonDeserializer CreateJsonDeserializer() { return new CustomJsonDeserializer(); } }
-
By default, every instance of the
StackExchangeClient
class utilizes its ownHttpClient
object to make HTTP requests. TheHttpClient
class is robust, and thread-safe -- a single instance of which should ideally be used by the entire application.To provide a custom
HttpClient
(the instance used by your application, for example) for theStackExchangeClient
to utilize,using RavinduL.SEStandard; using RavinduL.SEStandard.Http; // Sub-class the StackExchangeClient class, and override the CreateHttpRequester method. public class CustomStackExchangeClient : StackExchangeClient { public override IHttpRequester CreateHttpRequester() { var httpClient = /* custom HttpClient object */; return new HttpClientRequester(httpClient); } }
To completely customize the means by which HTTP requests are made, create an implementation of the IHttpRequester
interface. You may also want to create your own corresponding implementation of the IHttpResponse
interface.
using RavinduL.SEStandard.Http;
// Optionally, create an implementation of the IHttpResponse interface.
public class CustomHttpResponse : IHttpResponse
{
// ...
}
// Create an implementation of the IHttpRequester interface.
public class CustomHttpRequester : IHttpRequester
{
public async Task<IHttpResponse> PerformRequestAsync(string url, Dictionary<string, string> data, HttpRequestMethod requestMethod)
{
// Perform HTTP request here.
CustomHttpResponse response = /* Initialize an IHttpResponse to return */;
return response;
}
}
// Sub-class the StackExchangeClient class, and override the CreateHttpRequester method.
public class CustomStackExchangeClient : StackExchangeClient
{
public override IHttpRequester CreateHttpRequester()
{
return new CustomHttpRequester();
}
}
Please refer to CONTRIBUTING.md for information on setting up this project for development, repository layout, etc.
Massive thanks to the developers and contributors of the following incredible open-source projects,
†
This is not an official product of Stack Exchange Inc. The name was inspired by that of the NETStandard.Library
NuGet package.