In this article I am going to explain how to implement digital
signature in asp.net application.
Description:
Recently I have got a requirement to implement digital
signature functionality in application. To fulfill this requirement I have use
Signature pad jquery. It is HTML5 canvas based.
Implementation:
You can download Signature pad script from here. Download
Javascript and add reference to web form.
HTML
Markup of webform
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Signature.aspx.cs" Inherits="Signature" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>digital signature</title>
<link rel="stylesheet" href="css/signature-pad.css" />
</head>
<body>
<form id="form1" runat="server" style="width:100%;height:100%">
<asp:HiddenField ID="hfimg" runat="server" />
<div id="signature-pad" class="signature-pad">
<div class="signature-pad--body">
<canvas></canvas>
</div>
<div class="signature-pad--footer">
<div class="description">Sign above</div>
<div class="signature-pad--actions">
<div>
<button type="button" class="button
clear"
data-action="clear">Clear</button>
</div>
<div>
<asp:Button ID="Button1" runat="server" Text="Save
signature"
data-action="save" OnClick="Button1_Click" />
</div>
</div>
</div>
</div>
<script src="js/signature_pad.js"></script>
<script src="js/app.js"></script>
</form>
</body>
</html>
You need to make some changes in app.js file.
Code of
App.js file after changes
var wrapper = document.getElementById("signature-pad");
var clearButton = wrapper.querySelector("[data-action=clear]");
var canvas = wrapper.querySelector("canvas");
var signaturePad = new
SignaturePad(canvas);
// save button
var saveButton = wrapper.querySelector("[data-action=save]");
// Adjust canvas coordinate space taking
into account pixel ratio,
// to make it look crisp on mobile
devices.
// This also causes canvas to be cleared.
function resizeCanvas() {
// When zoomed out
to less than 100%, for some very strange reason,
// some browsers
report devicePixelRatio as less than 1
// and only part of
the canvas is cleared then.
var ratio = Math.max(window.devicePixelRatio || 1, 1);
// This part causes
the canvas to be cleared
canvas.width = canvas.offsetWidth * ratio;
canvas.height
= canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio,
ratio);
// This library does
not listen for canvas changes, so after the canvas is automatically
// cleared by the
browser, SignaturePad#isEmpty might still return false, even though the
// canvas looks
empty, because the internal data of this library wasn't cleared. To make sure
// that the state of
this library is consistent with visual state of the canvas, you
// have to clear it
manually.
signaturePad.clear();
}
// On mobile devices it might make more
sense to listen to orientation change,
// rather than window resize events.
window.onresize = resizeCanvas;
resizeCanvas();
function download(dataURL, filename) {
var blob =
dataURLToBlob(dataURL);
var url =
window.URL.createObjectURL(blob);
var a =
document.createElement("a");
a.style = "display: none";
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
}
// One could simply use Canvas#toBlob
method instead, but it's just to show
// that it can be done using result of
SignaturePad#toDataURL.
function dataURLToBlob(dataURL) {
//
Code taken from https://github.com/ebidel/filer.js
var parts =
dataURL.split(';base64,');
var contentType =
parts[0].split(":")[1];
var raw =
window.atob(parts[1]);
var rawLength =
raw.length;
var uInt8Array = new
Uint8Array(rawLength);
for (var i = 0; i <
rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array],
{ type: contentType });
}
clearButton.addEventListener("click", function (event) {
signaturePad.clear();
});
saveButton.addEventListener("click", function (event) {
if
(signaturePad.isEmpty()) {
alert("Please provide signature first.");
} else {
document.getElementById("hfimg").value = signaturePad.toDataURL();
}
});
Add
namespace
C# Code
using System.Drawing.Imaging;
using System.IO;
VB.net Code
Imports System.Drawing.Imaging
Imports System.IO
Save image to folder
On button click write the below given code:
C# Code
protected void Button1_Click(object sender, EventArgs e)
{
string signature =
hfimg.Value;
string concat =
signature.Replace("data:image/png;base64,", "");
byte[] imageBytes = Convert.FromBase64String(concat);
MemoryStream
ms = new MemoryStream(imageBytes,
0,imageBytes.Length);
//
Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
System.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
//save
image
image.Save(Server.MapPath("~/ScreenShot/"+Guid.NewGuid()+".png"), ImageFormat.Png);
}
VB.net Code
Protected Sub
Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim signature As String = hfimg.Value
Dim concat As String =
signature.Replace("data:image/png;base64,", "")
Dim imageBytes As Byte() = Convert.FromBase64String(concat)
Dim ms As New MemoryStream(imageBytes, 0,
imageBytes.Length)
' Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length)
Dim image As System.Drawing.Image = System.Drawing.Image.FromStream(ms, True)
'save
image
image.Save(Server.MapPath("~/ScreenShot/" + Guid.NewGuid.ToString()
+ ".png"),
ImageFormat.Png)
End
Sub
Hi there, thanks for the source code. However, I'm getting an exception at the following line:
ReplyDeleteSystem.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
The exception is System.ArgumentException: Parameter is not valid.
Could you please help? Thanks!
Code is tested and working fine.
DeleteIm having this problem too...
Deleteit said "Parameter is not valid". Can you help us? Btw thanks for the code
System.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
ReplyDeleteParameter is not valid.
Could you please help? Thanks!
funciona solo tuve que hacer ajustes en el codigo JS:
ReplyDeletesaveButton.addEventListener("click", function (event) {
if (signaturePad.isEmpty()) {
alert("Please provide signature first.");
} else {
//document.getElementById("hfimg").value = signaturePad.toDataURL(); reemplace esto
var base64 = signaturePad.toDataURL();
$("[id$=TextBox1]").val(base64 ); //por esto, coloque un textbox para verlo
}
});
el problema que no carga el hfimg(hidden) porque no lo encuentra de esa forma net.
de la forma que lo hice funcionó.
Saludos desde Argentina
funciona solo hay que retocar el Javascript en la parte de guardar como llamar el objeto que guardara el valor en base 64:
ReplyDeletedocument.getElementById("<%=hfimg.ClientID%>").value = signaturePad.toDataURL();//cambiar esto.
var base64 = signaturePad.toDataURL();
$("[id$=TextBox1]").val(base64); // por esto Textbox1 cambiarlo por el que ustedes usen.
can you update it in razor view
ReplyDeleteIn hidden filed control set client id mode static.
ReplyDeleteAdd client id mode to Static for hidden filed control.
ReplyDeleteunable to draw signature on canvas. Please help...
ReplyDeleteAny body please share the code or link of how we can add signatures in pdf using ASP .Net Core MVC.
ReplyDeleteThanks!