Apir Documentation
The easiest and fastest way to create a REST API for a SQL Server Database
A simple Stored Procedure is all the code you need.
CREATE PROCEDURE API_Products_Get (@ID int = NULL) AS SELECT ProductId, ProductName FROM Products WHERE ProductID = @ID OR @ID IS NULL
In the above stored procedure the resource Products is declared. The prefix API_ is used by Apir to find API procedures. The _Get at the end means that this procedure will respond to the HTTP GET verb.
The resource itself has the fields ProductID and ProductName
When Apir is running it will create an API like:
GET http://myserver/products Retrieve an array of products GET http://myserver/products/2 Retrieve product with ID=2
Similar procedures using the verbs PUT, POST and DELETE for doing full CRUD operations on products may be created.
Installation
Download the installer from
http://apirdocs.azurewebsites.net/apir.msi
Apir must be installed on a Windows machine. After installation you will have a start menu entry for the apir command line. If your are using Bash or Powershell just add c:\apir to your path.
Register your email
Please register your email. You will get a key back which are stored in apir.json.
apir register -email:XX@YY.COM
Connect to the database
The connection string is in apir.json. You may edit it or use the GUI:
apir connection
Develop your API
Resources
A fundamental concept of REST APIs is the resource.
Resources are the objects of the API. The task of your API is to enable apps to manipulate resources.
You define resources in SQL by a simple SELECT statement in a stored procedure.
In our first example we have a Products table and want to create a Product resource.
Test table
The product table has a primary key.
CREATE TABLE Products ( ProductId INT NOT NULL IDENTITY(1,1), ProductName VARCHAR(100), CONSTRAINT [PK_Products] PRIMARY KEY ([ProductId]) ) GO INSERT INTO Products(ProductName) VALUES('Widget1'), ('Widget2'), ('Widget3')
Generate the API
Apir can generate the TSQL procedures for you.
apir sqlgen Usage: apir sqlgen -table:myTable -resource=myResource -verbs:Get,Put,Post,Delete -alter -filter -page apir sqlgen -t:Products -r:Product
The first command shows the syntax. The second is a short hand for generating 4 procedures for doing CRUD on the Products table.
CREATE PROCEDURE API_Products_POST(@Name VARCHAR(100)) CREATE PROCEDURE API_Products_GET(@ID int = NULL) CREATE PROCEDURE API_Products_PUT(@ID,@Name VARCHAR(100)) CREATE PROCEDURE API_Products_DELETE(@ID int)
If you want to view the SQL source code in SSMS refresh the list of stored procedures. Hint: right click in SSMS.
You may of course edit and modify these procedures.
--- <summary> --- Retrieve Product --- </summary> --- <param name = "ID" > Products ID </param> --- <remarks> Returns all or a single Products </remarks> ALTER PROCEDURE[dbo].[API_Product_Get](@ID int = NULL) AS SELECT ProductID, ProductName FROM Products WHERE (@ID IS NULL OR @ID = ProductID) ORDER BY ProductName
The Product:Get procedure will return a single Product or an array of products depending on the @ID parameter
Post new resources
The generated procedure for inserting new products is:
--- <summary> --- Insert Product --- </summary> --- <remarks> Insert new Products </remarks> --- <response code="200">OK</response> ALTER PROCEDURE[dbo].[API_Product_Post]( @ProductName varchar(100) = NULL ) AS INSERT INTO Products ( ProductName ) VALUES (@ProductName) RETURN 200 -- OK
You may do some error checking in the procedure like:
This is a more advanced implementation:
--- <summary> --- Add a new product to the database --- </summary> --- <remarks> A link to the new product is added </remarks> --- <response code="201">OK</response> --- <response code="521">Bad productname</response> --- <response code="522">Product with name exists</response> ALTER PROCEDURE [dbo].[API_Product_Post]( @ProductName VARCHAR(100), @NewId int OUTPUT) AS IF (@ProductName IS NULL OR LEN(@ProductName) < 2) BEGIN RAISERROR('Bad product name',1,1) RETURN 521 END IF EXISTS (SELECT ProductId FROM Products WHERE ProductName = @ProductName) BEGIN RAISERROR('Product with that name already exists',1,1) RETURN 522 END INSERT INTO Products(ProductName) VALUES(@ProductName) SET @NewId = @@IDENTITY RETURN 201
Here we check for a correct productname. A product with the new name must not exists in the database.
The output parameter @NewId returns the generated identifier and a HTTP header with the URL of the generated product will be returned.
Updating the resource
The generated procedure will let the user update all non key columns. The default value of a new column is NULL, which means that the value is not altered.
--- <summary> --- Update Product --- </summary> --- <param name = "ID" > Products ID </param> --- <remarks> Updates Products </remarks> --- <response code="200">OK</response> --- <response code="404">Not Found</response> ALTER PROCEDURE[dbo].[API_Product_Put]( @ID varchar(max) = NULL, @ProductName varchar(100) = NULL ) AS IF NOT EXISTS(SELECT ProductID FROM Products WHERE @ID = ProductID) BEGIN RAISERROR('Unknown Product',1,1) RETURN 404 END UPDATE Products SET ProductName = COALESCE(@ProductName,ProductName) WHERE @ID = ProductID RETURN 200 -- OK
Deleting a resource
The implementation is straight forward. If the product is unknown an error is returned.
--- <summary> --- Delete Product --- </summary> --- <param name = "ID" > Products ID </param> --- <remarks> Delete Products </remarks> --- <response code="200">OK</response> --- <response code="404">Not Found</response> ALTER PROCEDURE[dbo].[API_Product_Delete](@ID varchar(max) = NULL) AS IF NOT EXISTS(SELECT ProductID FROM Products WHERE @ID = ProductID) BEGIN RAISERROR('Unknown Product',1,1) RETURN 404 END DELETE Products WHERE @ID = ProductID RETURN 200 -- OK
Filtering and paging on the server
Clients may want to limit the rows returned by using a filter and/or paging. Implementing these on the server leads to a faster system with less data going down the line. For mobile clients there is also a cost saving with less data transfer.
You may generate the API_Product_Get procedure again with new options:
apir sqlgen -t:Products -r:Product -v:Get -page -filter -alter
The API_Resource_Get procedure will be generated as:
ALTER PROCEDURE[dbo].[API_Product_Get](@ID varchar(max) = NULL , @filter varchar(max)=NULL , @pageNo int = 1, @pageSize int=40 ) AS SELECT ProductID, ProductName FROM Products WHERE (@ID IS NULL OR @ID = ProductID) AND (@filter IS NULL OR CHARINDEX(@filter,CAST(ProductName AS varchar)) > 0) ORDER BY ProductName OFFSET (@pageNo-1)*@pageSize ROW FETCH NEXT @pageSize ROW ONLY
Self Host API
The apir.exe app can host the api without a webserver. Just start with
apir run
In apir.json these settings will be used
BaseAddress: "http://localhost:18092", RelayHost: false,
Relayhost will not be used and the selfhosting will be done on port 18092
Test the API
The Swagger test and documentation framework may be enabled in the apir.json config file by:
apir config -swagger:yes
When you start apir a browser window will be opened with Swagger. Apir provides the swagger UI which uses a description of the API.
Use Relay hosting
When you run the API on localhost it is generally not available on other machines and not on the internet. You may configure the firewall and routers in your company to open a port and also route request to the machine.
If you want to use the API from a mobile device you must make it available on the internet.
Apir can host the API on the internet in a safe way by using some magic called relay hosting. A cloud endpoint is used. The only local requirement is that outbound http is available. It will work across NAT and firewalls.
If you have registered your email you may try the Relay. First find a unique name for the api. Use that instead of myapi in the command below
apir registerApi -name:myapi
You will also get encryption since we always use SSL with the cloud endpoint.
Now start apir
apir run
Host in ASP.NET web app on IIS
If you have a ASP.NET web application you may use our nuget package
Install-Package ApirIO
It is that simple. You must have a connection string with DefaultConnection defined in your web.config file
<configuration> <connectionStrings> <add name="DefaultConnection" connectionString="Data Source=localhost\sqlexpress;Initial Catalog=myDatabase;Integrated Security=True" /> </connectionStrings>
When your app starts, the API code will be generated and compiled on the fly. If you change the API, just restart the app.
Try running the api directly in the browser
http://localhost:50608/api/products
Add Swagger to your ASP.NET website
You can install the same Swagger test harness to your ASP.NET website.
Install-Package Swashbuckle -Version 5.5.3
Hit F5 and then start Swagger with:
http://localhost:50608/swagger
Install as Windows Service
Windows has services which runs independent in the background. This is great in production since the api will be available even if no user is logged into the machine. If the machine is rebooted, the API will be started.
Apir.exe has commands for installing and uninstalling itself as a Windows service.
You may also start and stop the windows service. The start may me automatic with windows and it may be delayed, since we want to allow SQL Server to start first.
Working with windows services requires administrator access. You may use the --sudo flag on the command line or just start a new command line with "Run as Adminstrator". Hint: right click on the menu.
Goto c:\apir
apir install apir start
Hopefully the service started. If there was a problem see the logs.
If you make changes to the API_* stored procedures you may need to stop and start the service
Reference for Windows Service commands
The Windows service part of apir.exe is provided by the Topshelf library.
apir.exe [verb] [-option:value] [-switch] run Runs the service from the command line (default) help or --help Displays help install Installs the service -username The username to run the service -password The password for the specified username -instance An instance name if registering the service multiple times --autostart The service should start automatically (default) --disabled The service should be set to disabled --manual The service should be started manually --delayed The service should start automatically (delayed) --localsystem Run the service with the local system account --localservice Run the service with the local service account --networkservice Run the service with the network service permission --interactive The service will prompt the user at installation for the service credentials --sudo Prompts for UAC if running on Vista/W7/2008 -servicename The name that the service should use when installing -description The service description the service should use when installing. Eg: -description: MyService Eg: -description "My Service" -displayname The display name the the service should use when installing Eg: -displayname: MyService Eg: -displayname "My Service" start Starts the service if it is not already running -instance The instance to start stop Stops the service if it is running -instance The instance to stop uninstall Uninstalls the service -instance An instance name if registering the service multiple times --sudo Prompts for UAC
Documenting the API
The users of your API needs documentation. Your apir API can document itself with Swagger. A standard for describing an API. Also the swagger-ui is provided with apir. It is a test harness for the API.
There is also tools like code generators that uses the Swagger definition.
c# developers have documented code with XML comments for years. These comments are used by tools such as Visual Studio. ApirIO lets you comment the stored procedures and moves any comments to the generated c-sharp code. It is great for API documentation since it can be used in Swagger and lives with the database.
The comments are written before the stored procedure. They are XML tags.
--- <summary> --- Update Product --- </summary> --- <param name = "ID" > Products ID </param> --- <remarks> Updates Products </remarks> --- <response code="200">OK</response> --- <response code="404">Not Found</response> ALTER PROCEDURE[dbo].[API_Product_Put]( @ID varchar(max) = NULL , @ProductName varchar(100) = NULL )
Swagger will display this as:
Logging
apir uses the NLog library for logging.
By default, log entries are written to the console and to a logfile at ./logs
A file is created with the format YYYY-MM-DD.log
If you run as a Windows service the logfile is very important.
The Nlog configuration file is called NLog.config and its format is described here
Save and Update your API as SQL Script file
If you want to create a TSQL script file:
apir sqlretrieve -file:mySqlFile.sql
You may execute a TSQL script file by:
apir sqlexec -file:mySqlFile.sql
The script may also be stored on the internet:
apir sqlexec -url:http://myserver/myurl
The apir.json config file
Open the config file and have a look. Unfortunately there is no way of adding comments to the json file itself.
When hosting locally, this URL will be used "BaseAddress": "http://localhost:18092", Where to store compiled sourcecode for WebApi "OutPath": "cs\\", Should a Swagger description of the API be available "Swagger": true, Should the Swagger test GUI be available "SwaggerUI": true, A TSQL procedure to authenticate with user / password "UserValidator": "", The name of machine to authenticate "MachineValidate": "", A domain for which to authenticate "DomainValidate": "", Should relay hosting be used "RelayHost": true, A key returned when email is registered. "ApirKey": "", A key for a service when using Relay host "ServiceKey": "", Resources which should not be protected. (Auth needed) "FreeResources": "Login,Register", Connection string to database. "ConnectionString": "Server=;Database=;User ID=;Password=;", Experimental autorestart when TSQL procedures change "AutoRestart": false,
Securing the API
Two things must be implemented for securing the API. All communication between the client and the API must be encrypted. Client apps or users must be authenticated.
If you use our relay hosting only SSL encrypted access is allowed.
The authentication is done using Basic Authentication. The user / password may be verified by
- A stored procedure you write. The username and password i passed as parameters to the procedure.
-
A user on the machine running apir.exe may be used. Just add the name of the machine to apir.json machineValidate. You can find the machine name from DOS by using the command hostname
-
A user on a windows domain. Add the domain name to apir.json DomainValidate
Securing API on ASP.NET
If you host your API as part of a website in IIS, you may use ASP.NET and IIS to secure the API