In this post, I will describe how to generate QR Code using Angular 4 & ASP.NET Web API
Technologies Used : Angular 4, ASP.NET Web API, HTML 5, Bootstrap
Pre-Requisites : Reader to have a fair understanding and experience in setting up & developing applications using Angular-4 and ASP.NET Web API, also installing packages using various package managers like Node Package Manager or ‘NPM’.
Use Case : Generate QR Code which can be scanned to download files stored on Azure Blob storage.
Tools needed : Visual Studio 2017. I hope the reader is familiar with setting up Angular 4 in Visual Studio.
External Libraries used : ZXing which can be used to generate QR code images. It can be found on GitHub : https://github.com/zxing Install this package using NuGet package manager.
Source Code : Complete source for the application can be found at GitHub repository :
Key Learnings :
(1) Setup Angular 4 in Visual Studio 2017
(2) Integrate Angular 4 with ASP.NET MVC and Web API
(3) Angular 4 routing
(4) Angular 4 HTTP Requests with Observables
(5) Angular 4 URL Search Params
(6) QR Code generation
(7) Downloading QR Code image from Base64 encoded string
(8) Using JavaScript BLOB object
(9) Loading spinner while fetching data asynchronously
Application Architecture :
Let’s proceed to code.
Step (1) : Create Visual Studio ASP.NET MVC Web API Solution
Create a new Visual Studio Project, select ‘ASP.NET Web Application(.NET Framework)’ and select the ‘MVC’ and ‘Web API’ check boxes.
Step (2) : Setup Angular 4 in Visual Studio 2017
Setup your Angular 4 development environment and install the dependencies using Node Package Manager (NPM). I have used ‘SystemJS’ in the Angular 4 setup.
Add
typings.json and package.json files. Add a folder named app at the application root and create various typescript files – app.component.ts, app.module.ts, app.router.ts, bootstrap.ts and a typescript configuration file named tsconfig.json
Under
app folder app subfolder home and add files home.component.html and home.component.ts. Add another subfolder under app folder and add files qrcode.component.html and qrcode.component.ts
You can find the code for these above mentioned files at GitHub repository mentioned at the start of this article.
Step (3) : Create ASP.NET Web API controller
The Web Api controller’s GET method will return a Base64 encoded string having the QR code image.
Non .NET/Microsoft audience can create any REST api using Node.js, PHP etc to generate and return a Base64 encoded string having the QR code image.
Create a GET method named ‘GetQRCode’ as shown below.
1
2
3
4
5
6
7
8
| [HttpGet]//GET:api/QRCode/GetQRCode/?content="www.google.com"&alt="QRght=200&width=200&margin=0public string GetQRCode(string content, string alt = "QR Code", int height = 500, int width = 500, int margin = 0){ HttpResponseMessage result = new HttpResponseMessage(); string qrResult = GenerateQRCode(content, alt, height, width, 0); return qrResult;} |
In the above code, ‘GetQRCode’ method calls a method named ‘GenerateQRCode’ which is as below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| public static string GenerateQRCode(string url, string alt = "QR code", int height = 500, int width = 500, int margin = 0){ var qrWriter = new BarcodeWriter() { Format = BarcodeFormat.QR_CODE, Options = new EncodingOptions() { Height = height, Width = width, Margin = margin } }; using (var q = qrWriter.Write(url)) { using (var ms = new MemoryStream()) { q.Save(ms, ImageFormat.Png); return Convert.ToBase64String(ms.ToArray()); } }} |
The above method call the ‘BarCode’ writer method of ‘ZXing’ library. The result is saved to a ‘MemoryStream’ and converted and returned as a Base64 encoded string.
Step (4) : Create Angular view for QRCode component
Create a HTML 5 page as a partial view. Add a button text-box which will enable the user to input the filename and button which when clicked will take the file name entered in the text-box and generate and display the QR code on the page.
HTML 5 code code snippet for text-box and button :-
1
2
3
4
5
6
| <input #filename placeholder="File Name" class="input-sm" style="width:100%;max-width:100%" /><div> <button class="btn btn-info" (click)="generateQRCode(filename.value)"> <span class="glyphicon glyphicon-barcode"></span> Generate QR Code </button></div> |
Step (5) : Create TypeScript for QRCode component
Typescript code for
qrcodecomponent.ts is shown below. In the below code, getQRCode(filename: string) method calls the ASP.NET Web API controller to generate the QR Code.downloadQRCode() method is used to download the generated QR code on click of Download QR Code button. In this method, Base64 encoded QRCode string is converted to JavaScript BLOB object and blob’s save method is called to save the QR Code image.
For browsers on which JavaScript BLOB object isn’t supported, an invisible
anchortag is created in the DOM body and the anchor tag’s click event is triggered to download the QR Code image.
For browsers like Safari where above two options aren’t supported, a
data:image tag is used to open the Base64 encoded QR Code image string in a new window using window.open() method.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
| import { Component } from '@angular/core';import { Http, RequestOptions, Headers, Response, URLSearchParams } from '@angular/http';import 'rxjs/Rx';import { Router } from '@angular/router';@Component({ templateUrl: './app/qrcode/qrcode.component.html'})export class QRCodeComponent{ b64b64toBlob: any; base64encodedQRImgString: any; qrResult: any; errorMessage: string; public isLoadingData: Boolean = false; blobPDFUri: any; constructor(private http: Http) { this.qrResult = ""; this.errorMessage = ""; } generateQRCode(fn) { //Clear previous QR Code result this.base64encodedQRImgString = ""; this.qrResult = ""; if (fn == '') { alert('Please enter File Name to generate QR Code'); } else { //Generate QR Code this.getQRCode(fn); } } getQRCode(filename: string) { let apiUri = "/api/QRCode/GetQRCode"; this.blobPDFUri = "https://myblob.blob.core.windows.net/myblobcontainertest/" + encodeURIComponent(filename) + "?st=2017-04-08T00%3A01%3A00Z&se=2099-12-31T23%3A59%3A00Z&sp=rwdl&sv=2015-12-11&sr=c&sig=nPeI%2Bd..."; // Parameters obj- let params: URLSearchParams = new URLSearchParams(); params.set('content', this.blobPDFUri); params.set('alt', 'QR Code'); params.set('height', '150'); params.set('width', '150'); params.set('margin', '0'); let requestOptions = new RequestOptions(); requestOptions.params = params; this.isLoadingData = true; this.http.get(apiUri, requestOptions) .map((res: Response) => res.json()) .subscribe ( data => { this.base64encodedQRImgString = data; console.log(data); this.qrResult = "<img src='data:image/png;base64," + data + "' />"; this.errorMessage = ""; }, err => { console.error(err); this.errorMessage = err; this.isLoadingData = false; }, () => { this.isLoadingData = false } ); } downloadQRCode() { var byteCharacters = atob(this.base64encodedQRImgString); var byteNumbers = new Array(byteCharacters.length); for (var i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); var blob: Blob; try { blob = new Blob([byteArray], { type: "image/png" }); if (window.navigator.msSaveOrOpenBlob) // IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx { window.navigator.msSaveBlob(blob, 'QR.png'); } else { var a = window.document.createElement("a"); a.href = window.URL.createObjectURL(blob); a.download = "QR.png"; document.body.appendChild(a); a.click(); // IE: "Access is denied"; see: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access document.body.removeChild(a); } } catch (err) { //Blob not supported for Safari window.open('data:image/png;base64,' + this.base64encodedQRImgString); } }} |
Above method makes an Angular HTTP GET request to the Web API which returns the Base64 encoded image data which is stored in a variable as an image tag using ‘data:image’ url.
The variable ‘isLoadingData’ in the above TypeScript code is used to display a loading spinner when the ‘Generate QR Code’ is clicked and till the QR code is generated and rendered.
Step (6) : Bind Typescript variable to Angular view
The resulting variable storing the image tag with Base64 encoded image data is then bound to the HTML view as shown below.
1
| <div [innerHtml]="qrResult"></div> |
Since the variable ‘qrResult’ in the TypeScript code holds an
tag, it has been bound in the ‘innerHtml’ of the ‘div’ element to render the contents as image.
1
| this.qrResult = "<img src='data:image/png;base64," + data + "' />"; |
Step (7) : Run the application
Before generating QR code, QR Code homepage view looks as below :
Enter the file name in the text box and click “Generate QR Code button”. While the application generates QRCode image, a loading spinner blocks the page preventing user form performing any other actions as can be seen below:
After generating QR code, result looks as below :
Click “Download QR Code” button to download and save the QR Code image as a .PNG file.
I hope you followed the article. If you have any comments, questions or suggestions, leave a message and I will try to respond at my earliest.


0 comments:
Post a Comment
Note: only a member of this blog may post a comment.