Skip to content

Commit 6ebfcb7

Browse files
committed
Added JSON & Dapper.ORM Integration sample
1 parent fe96972 commit 6ebfcb7

35 files changed

+2097
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.xproj.user
2+
.vs/*
3+
.vscode/*
4+
bin/*
5+
obj/*
6+
*.sln
7+
*.log
8+
*.lock.json
9+
appsettings.development.json
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using Dapper;
2+
using Microsoft.AspNetCore.Mvc;
3+
using System.Data;
4+
using System.IO;
5+
using System.Threading.Tasks;
6+
7+
// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
8+
9+
namespace ProductCatalog.Controllers
10+
{
11+
[Route("api/[controller]")]
12+
public class ProductController : Controller
13+
{
14+
IDbConnection connection = null;
15+
16+
public ProductController(IDbConnection connection)
17+
{
18+
this.connection = connection;
19+
}
20+
21+
// GET api/Product
22+
[HttpGet]
23+
public void Get()
24+
{
25+
var QUERY =
26+
@"select ProductID, Name, Color, Price, Quantity, JSON_VALUE(Data, '$.MadeIn') as MadeIn, JSON_QUERY(Tags) as Tags
27+
from Product
28+
FOR JSON PATH";
29+
30+
connection.QueryInto(Response.Body, QUERY);
31+
}
32+
33+
// GET api/Product/17
34+
[HttpGet("{id}")]
35+
public void Get(int id)
36+
{
37+
connection.QueryInto(Response.Body,
38+
@"select ProductID, Name, Color, Price, Quantity, JSON_VALUE(Data, '$.MadeIn') as MadeIn, JSON_QUERY(Tags) as Tags
39+
from Product
40+
where ProductID = @id
41+
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER", new { id }, defaultOutput: "{}");
42+
}
43+
44+
// POST api/Product
45+
[HttpPost]
46+
public async Task Post()
47+
{
48+
string product = new StreamReader(Request.Body).ReadToEnd();
49+
await connection.ExecuteAsync("EXEC dbo.InsertProductFromJson @product", new { product });
50+
}
51+
52+
// PATCH api/Product
53+
[HttpPatch]
54+
public async Task Patch(int id)
55+
{
56+
string product = new StreamReader(Request.Body).ReadToEnd();
57+
await connection.ExecuteAsync("EXEC dbo.UpsertProductFromJson @id, @product", new { id, product });
58+
}
59+
60+
// PUT api/Product/5
61+
[HttpPut("{id}")]
62+
public async Task Put(int id)
63+
{
64+
string product = new StreamReader(Request.Body).ReadToEnd();
65+
await connection.ExecuteAsync("EXEC dbo.UpdateProductFromJson @id, @product", new { id, product });
66+
}
67+
68+
// DELETE api/Product/5
69+
[HttpDelete("{id}")]
70+
public async Task Delete(int id)
71+
{
72+
string product = new StreamReader(Request.Body).ReadToEnd();
73+
await connection.ExecuteAsync("delete Product where ProductId = @id", new { id });
74+
}
75+
76+
[HttpGet("Report1")]
77+
public void Report1()
78+
{
79+
var QUERY =
80+
@"select [key] = ISNULL(Color,'N/A'), value = AVG(Quantity)
81+
from Product
82+
group by Color
83+
FOR JSON PATH";
84+
85+
connection.QueryInto(Response.Body, QUERY);
86+
}
87+
88+
// GET api/Product/Report2
89+
[HttpGet("Report2")]
90+
public void Report2()
91+
{
92+
connection.QueryInto(Response.Body, @"
93+
select ISNULL(Color,'N/A') as x,
94+
AVG (Price) / MAX(Price) as y
95+
from Product
96+
group by Color
97+
FOR JSON PATH");
98+
}
99+
}
100+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
5+
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
6+
</PropertyGroup>
7+
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
8+
<PropertyGroup Label="Globals">
9+
<ProjectGuid>7e230e5a-b0b6-4f56-9561-942fd1817b80</ProjectGuid>
10+
<RootNamespace>product_catalog</RootNamespace>
11+
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
12+
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
13+
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
14+
</PropertyGroup>
15+
<PropertyGroup>
16+
<SchemaVersion>2.0</SchemaVersion>
17+
</PropertyGroup>
18+
<ItemGroup>
19+
<DnxInvisibleFolder Include=".vscode\" />
20+
</ItemGroup>
21+
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" />
22+
</Project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using Microsoft.AspNetCore.Builder;
2+
using Microsoft.AspNetCore.Hosting;
3+
using System.IO;
4+
5+
namespace ProductCatalog
6+
{
7+
public class Program
8+
{
9+
public static void Main(string[] args)
10+
{
11+
var host = new WebHostBuilder()
12+
.UseKestrel()
13+
.UseContentRoot(Directory.GetCurrentDirectory())
14+
.UseIISIntegration()
15+
.UseStartup<Startup>()
16+
.Build();
17+
18+
host.Run();
19+
}
20+
}
21+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"iisSettings": {
3+
"windowsAuthentication": false,
4+
"anonymousAuthentication": true,
5+
"iisExpress": {
6+
"applicationUrl": "http://localhost:8929/",
7+
"sslPort": 0
8+
}
9+
},
10+
"profiles": {
11+
"IIS Express": {
12+
"commandName": "IISExpress",
13+
"launchBrowser": true,
14+
"launchUrl": "api/Product",
15+
"environmentVariables": {
16+
"ASPNETCORE_ENVIRONMENT": "Development"
17+
}
18+
},
19+
"ProductCatalog": {
20+
"commandName": "Project",
21+
"launchBrowser": true,
22+
"launchUrl": "http://localhost:5000/api/Product",
23+
"environmentVariables": {
24+
"ASPNETCORE_ENVIRONMENT": "Development"
25+
}
26+
}
27+
}
28+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Building Web Apps using Dapper ORM and SQL/JSON functionalities
2+
3+
This project contains an example implementation of ASP.NET REST Service/App that enables you to get or modify list of products in catalog and show reports.
4+
5+
## Contents
6+
7+
[About this sample](#about-this-sample)<br/>
8+
[Before you begin](#before-you-begin)<br/>
9+
[Run this sample](#run-this-sample)<br/>
10+
[Sample details](#sample-details)<br/>
11+
[Disclaimers](#disclaimers)<br/>
12+
[Related links](#related-links)<br/>
13+
14+
<a name=about-this-sample></a>
15+
16+
## About this sample
17+
18+
- **Applies to:** SQL Server 2016 (or higher), Azure SQL Database
19+
- **Key features:** JSON functions in SQL Server 2016/Azure SQL Database, Dapper ORM
20+
- **Programming Language:** C#, Transact-SQL
21+
- **Authors:** Jovan Popovic
22+
23+
<a name=before-you-begin></a>
24+
25+
## Before you begin
26+
27+
To run this sample, you need the following prerequisites.
28+
29+
**Software prerequisites:**
30+
31+
1. SQL Server 2016 (or higher) or an Azure SQL Database
32+
2. Visual Studio 2015+ or Visual Studio Code Editor with the ASP.NET Core 1.0 (or higher)
33+
34+
**Azure prerequisites:**
35+
36+
1. Permission to create an Azure SQL Database
37+
38+
<a name=run-this-sample></a>
39+
40+
## Run this sample
41+
42+
1. Create a database on SQL Server 2016 or Azure SQL Database and set compatibility level to 130+.
43+
44+
2. From SQL Server Management Studio or Sql Server Data Tools connect to your SQL Server 2016 or Azure SQL database and execute [sql-scripts/setup.sql](sql-scripts/setup.sql) script that will create and populate Product table and create required stored procedures.
45+
46+
3. From Visual Studio 2015, open the **ProductCatalog.xproj** file from the root directory. Restore packages using right-click menu on the project in Visual Studio and by choosing Restore Packages item. As an alternative, you may run **dotnet restore** from the command line (from the root folder of application).
47+
48+
4. Add a connection string in appsettings.json or appsettings.development.json file. An example of the content of appsettings.development.json is shown in the following configuration:
49+
50+
```
51+
{
52+
"ConnectionStrings": {
53+
"ProductCatalog": "Server=.;Database=ProductCatalog;Integrated Security=true"
54+
}
55+
}
56+
```
57+
58+
If database is hosted on Azure you can add something like:
59+
```
60+
{
61+
"ConnectionStrings": {
62+
"ProductCatalog": "Server=<<SERVER>>.database.windows.net;Database=ProductCatalog;User Id=<<USER>>;Password=<<PASSWORD>>"
63+
}
64+
}
65+
```
66+
67+
5. Build solution using Ctrl+Shift+B, right-click on project + Build, Build/Build Solution from menu, or **dotnet build** command from the command line (from the root folder of application).
68+
69+
6. Run the sample app using F5 or Ctrl+F5 in Visual Studio 2015, or using **dotnet run** executed in the command prompt of the project root folder.
70+
1. Open /api/Product Url to get all products from database,
71+
2. Open /api/Product/18 Url to get the product with id,
72+
3. Send POST Http request to /api/Product Url with JSON like {"Name":"Blade","Color":"Magenta","Price":18.0000,"Quantity":45} in the body of request to create new product,
73+
4. Send PUT Http request with JSON like {"Name":"Blade","Color":"Magenta","Price":18.0000,"Quantity":45} in the body of request to update the product with specified id,
74+
5. Send DELETE Http request /api/Product/18 Url to delete the product with specified id(18),
75+
6. Open index.html to see how JavaScript client-side app can use underlying REST API,
76+
7. Open report.html to see how you can create reports with pie/bar charts using D3 library and underlying REST API.
77+
78+
<a name=sample-details></a>
79+
80+
## Sample details
81+
82+
This sample application shows how to create REST API that returns list of products, single product, or update products in table.
83+
Dapper ORM framework is used for data access. Dapper-Stream extension is used to integrate Dapper with SQL/JSON functionalities.
84+
Server-side code is implemented using ASP.NET.
85+
SQL Server JSON functions are used to format product data that will be sent to front-end page.
86+
Client-side code is inplemented using various JavaScript components.
87+
88+
<a name=disclaimers></a>
89+
90+
## Disclaimers
91+
The code included in this sample is not intended demonstrate some general guidance and architectural patterns for web development. It contains minimal code required to create REST API, and it does not use some patterns such as Repository. Sample uses built-in ASP.NET Core Dependency Injection mechanism; however, this is not prerequisite.
92+
You can easily modify this code to fit the architecture of your application.
93+
94+
<a name=related-links></a>
95+
96+
## Related Links
97+
98+
The architecture is based on a samples presented in [Building REST API using SQL Server JSON functionalities](http://sqlblog.com/blogs/davide_mauri/archive/2017/04/30/pass-appdev-recording-building-rest-api-with-sql-server-using-json-functions.aspx) PASS AppDev webinar.
99+
You can find more information about the components that are used in this sample on these locations:
100+
- Server-side components
101+
- [ASP.NET](http://www.asp.net).
102+
- [JSON Support in Sql Server](https://msdn.microsoft.com/en-us/library/dn921897.aspx).
103+
- [Dapper](https://github.com/StackExchange/Dapper) framework is used for data access.
104+
- Front-end components used in this sample are:
105+
- [JQuery library](https://jquery.com/) that is used to define UI logic in the front-end application.
106+
- [JQuery DataTable plugin](https://datatables.net/) that is used to display list of products in a table.
107+
- [JQuery View Engine](https://jocapc.github.io/jquery-view-engine/) that is used to populate HTML form using JSON model object.
108+
- [Twitter Bootstrap](http://getbootstrap.com/) that is used to style application.
109+
- [D3 library](https://d3js.org/) that is use to display pie/bar charts.
110+
111+
## Code of Conduct
112+
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
113+
114+
## License
115+
These samples and templates are all licensed under the MIT license. See the license.txt file in the root.
116+
117+
## Questions
118+
Email questions to: [[email protected]](mailto: [email protected]).
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using Microsoft.AspNetCore.Builder;
2+
using Microsoft.AspNetCore.Hosting;
3+
using Microsoft.Extensions.Configuration;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Microsoft.Extensions.Logging;
6+
using System.Data;
7+
using System.Data.SqlClient;
8+
9+
namespace ProductCatalog
10+
{
11+
public class Startup
12+
{
13+
public Startup(IHostingEnvironment env)
14+
{
15+
var builder = new ConfigurationBuilder()
16+
.SetBasePath(env.ContentRootPath)
17+
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
18+
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
19+
.AddEnvironmentVariables();
20+
Configuration = builder.Build();
21+
}
22+
23+
public IConfigurationRoot Configuration { get; }
24+
25+
// This method gets called by the runtime. Use this method to add services to the container.
26+
public void ConfigureServices(IServiceCollection services)
27+
{
28+
string ConnString = Configuration["ConnectionStrings:ProductCatalog"];
29+
services.AddTransient<IDbConnection>(_ => new SqlConnection(ConnString));
30+
31+
// Add framework services.
32+
services.AddMvc();
33+
}
34+
35+
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
36+
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
37+
{
38+
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
39+
loggerFactory.AddDebug();
40+
41+
app.UseStaticFiles();
42+
app.UseMvc();
43+
}
44+
}
45+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<configuration>
2+
<runtime>
3+
<gcServer enabled="true"/>
4+
</runtime>
5+
</configuration>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"Logging": {
3+
"IncludeScopes": false,
4+
"LogLevel": {
5+
"Default": "Debug",
6+
"System": "Information",
7+
"Microsoft": "Information"
8+
}
9+
},
10+
"ConnectionStrings": {
11+
"ProductCatalog": "Server=.\\SQLEXPRESS;Database=ProductCatalog;Trusted_Connection=True;"
12+
}
13+
}

0 commit comments

Comments
 (0)