-
Notifications
You must be signed in to change notification settings - Fork 3
Lesson 1: Step by Step Guide to Building a Simple API
This guide will take you through the steps of quickly building an in-memory cache and a RESTful API on top of an Entity Framework Core data model. When you're through, you'll have a persistent, in-memory data model that you can access through a full-featured REST API and all of it is automatically generated from an XSD description of your database.
In order to run this tutorial, you'll need administrator access to an SQL Server database.
In Visual Studio, Select Tools > Extensions and Updates...
Search the Online > Visual Studio Marketplace for Data Model Generator. Press the Download button to install it. Once installed, press the Close button to exit out of the Extensions and Updates dialog.
You'll need to exit out of Visual Studio and then start it back up to install the extension.
Create a new project. File > New > Project
In the New Project form, select Installed > Visual C# > .NET Core. We're going to create a new ASP.NET Core Web Application project called WebApplication1.
Use the API template to create the service. Take all the default settings.
At this point you should have a solution that looks like this:
Select the ValuesController.cs that was added by the template and delete it.
Add the Microsoft.EntityFrameworkCore and GammaFour.Data packages using the Tools > NuGet Package Manager > Package Manager Console.
Right-Click on the WebApplication1 project in the Solution Explorer pane and Add > New Item to the project.
Select ASP.NET Core > Data > XML File and change the name to DataModel.xsd (Note that everything will work fine with an XML extension, but you should change the extension to XSD. This will allow the Visual Studio Designer to recognize this as a Schema file).
The default viewer for XSD files is the XML Schema Designer. You may be presented with this screen after creating the XSD file:
If this is what you see, select Use the XML Editor to view and edit the underlying XML schema file. You may want to return to this view to maintain your schema or you may want to switch your default to XML editing. For now we're going to edit the XML.
Copy and paste this source into the DataModel.xsd file that you just created.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="DataModel" targetNamespace="http://tempuri.org/DataModel.xsd" xmlns="http://tempuri.org/DataModel.xsd" xmlns:mstns="http://tempuri.org/DataModel.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gfdata="urn:schemas-gamma-four-com:xml-gfdata">
<xs:element name="DataModel">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Customer" gfdata:verbs="Delete,Get,Post,Put">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="CustomerId" gfdata:autoIncrement="true" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Order" gfdata:verbs="Delete,Get,Post,Put">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomerId" type="xs:int" />
<xs:element name="OrderId" gfdata:autoIncrement="true" type="xs:int" />
<xs:element name="ProductId" type="xs:int" />
<xs:element name="Quantity" type="xs:decimal" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Product" gfdata:verbs="Delete,Get,Post,Put">
<xs:complexType>
<xs:sequence>
<xs:element name="ProductId" gfdata:autoIncrement="true" type="xs:int" />
<xs:element name="Name" type="xs:string"/>
<xs:element name="Price" type="xs:double" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="CustomerKey" gfdata:isPrimaryKey="true">
<xs:selector xpath=".//mstns:Customer" />
<xs:field xpath="mstns:CustomerId" />
</xs:unique>
<xs:unique name="OrderKey" gfdata:isPrimaryKey="true">
<xs:selector xpath=".//mstns:Order" />
<xs:field xpath="mstns:OrderId" />
</xs:unique>
<xs:unique name="ProductKey" gfdata:isPrimaryKey="true">
<xs:selector xpath=".//mstns:Product" />
<xs:field xpath="mstns:ProductId" />
</xs:unique>
<xs:keyref name="CustomerOrderdKey" refer="CustomerKey">
<xs:selector xpath=".//mstns:Order" />
<xs:field xpath="mstns:CustomerId" />
</xs:keyref>
<xs:keyref name="ProductOrderKey" refer="ProductKey">
<xs:selector xpath=".//mstns:Order" />
<xs:field xpath="mstns:ProductId" />
</xs:keyref>
</xs:element>
</xs:schema>Save the file with Ctrl+S.
Right-Click on the DataModel.xsd in the Solution Explorer and click Copy. Now right-click on the Controllers folder and click Paste.
Give each of the schema files a custom tool to execute. Select the DataModel.xsd in the root directory and enter ServerDataModelGenerator as the Custom Tool:
Select the DataModel.xsd in the Controllers folder and enter RestApiGenerator as the Custom Tool. Your project should now look like this:
At this point we have a complete Web Service with a RESTful API. The next step is to connect it to a database. For this step, you'll need access to a local or remote version of SQL Server.
Cut and paste the following code into Startup.cs:
namespace WebApplication1
{
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataModelContext>(
options => options.UseSqlServer(this.Configuration.GetConnectionString("SqlServerConnection")),
ServiceLifetime.Transient,
ServiceLifetime.Transient);
services.AddSingleton<DataModel>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
}
}
}This instructs the Web Service's Dependency Injection container how to build and instantiate our data model and the DbContext we'll use to communicate with the database. We'll also need an SQL connection string. Place the following in your appSettings.json file (this assumes you have a local Db):
{
"ConnectionStrings": {
"SqlServerConnection": "Data Source=.;Initial Catalog='WebApplication1';Integrated Security=True"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}Build the solution using Ctrl+Shift+B.
The generated code contains a complete description of the entities and their relations that Entity Framework can use to build the persistent database. Open up the Package Manager Console with Tools > NuGet Package Manager > Package Manager Console and type:
When that task has completed, update the database with this new migration with:
Now, update your debugger settings to display the Customer records by default when you start debugging. Right click on your WebApplication1 project in the Solution Explorer and click on Properties. Select the Debug tab on the right and enter "api/customers" in the Launch browser setting:
That's it! You now have a fully functional, cached Web Service you can access through a RESTful API. Just hit F5.
Now let's import some data to our web service using our generated RESTful API. Open up some HTTP Utility Tool like Postman (you can download that here.) Set the HTTP verb to be POST and copy the URL from the browser that the debugger opened (https://localhost:PORT#/api/customers) and paste it into the Enter request URL box.
Click on the Body tab and select RAW and JSON (application/json) from the drop-down. Now take the following JSON data and paste it into the body of the message:
{
"name": "Marry Shelly"
}Your Postman screen should look like this:
Great! Now hit the Send button. You should get back a 200 OK status. Now go to your web browser and hit F5. You'll see your record stored in the cache and on the database server. Feel free to repeat this step with other customers that you make up. For the last step, we're going to add a product. Select a new tab in PostMan and select POST for the request type using the products URL: https://localhost:PORT#/api/products. Again, click on the Body tab and select RAW and JSON (application/json). Cut and past this batch of products into the body.
{
"name": "Dog Brush",
"price": 23.49
}Your PostMan form should look like this:
Hit the Send button and you should get back a 200 OK again. Verify this by going to the browser started by the IDE and selecting the products URL from the exercise above. Your browser should look like this:
Verify to yourself that this is persistent by shutting down the application and starting it back up again.
It would be nice to finish off this demonstration by adding some orders, but there's a problem: unless we know the internal identifiers given to our records when we added them (e.g. customerId, productId), there's no way to construct a JSON message that references a customer or product. Though we could query the database now and write down those numbers, it's a bad idea to expect auto-generated numbers to be the same each time you load a database.
In our second lesson, we'll cover the basics of creating external keys and importing data.

















