Wednesday, May 15, 2019

How to integrate Google reCAPTCHA with Angular And Asp.Net MVC

Choosing the type of reCAPTCHA

There are four types of reCAPTCHA to choose from when creating a new site.


Selecting second method reCAPTCHA V2 -
The "I'm not a robot" Checkbox requires the user to click a checkbox for verifying that the user is not a robot. This will either pass the user immediately (with No CAPTCHA) or challenge them to validate whether or not they are human. This is simple way to integrate and requires two lines of html code.

How to generate secret key and site key

Sign up for a google reCAPTCHA and add your site domain 

Asp.Net Implementation for google reCaptcha

With asp.net we use server side implementation to validate for google recaptcha with the secret key. We  need to do server-side validation with the secret key.

For documentation about google reCAPTCHA visit url - https://developers.google.com/recaptcha/docs/verify.

Here is a simple Asp.net mvc method that helps to validate g-recaptcha-response which I have referred from stackoverflow questions.

public bool Validate(string encodedResponse)
    {
if (string.IsNullOrEmpty(encodedResponse)) return false; var secret = **your secret**;
if (string.IsNullOrEmpty(secret)) return false; var client = new System.Net.WebClient(); var googleReply = client.DownloadString(
string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, encodedResponse )); return JsonConvert.DeserializeObject(googleReply).Success; }
}

Here RecaptchaResponse is a simple class we have in added Asp.Net MVC model.


public class RecaptchaResponse
{
    [JsonProperty("success")]
    public bool Success { get; set; }

    [JsonProperty("error-codes")]
    public IEnumerable ErrorCodes { get; set; }

    [JsonProperty("challenge_ts")]
    public DateTime ChallengeTs { get; set; }

    [JsonProperty("hostname")]
    public string Hostname { get; set; }
}

Each reCAPTCHA user response token is valid for two minutes, and can only be verified once to prevent replay attacks. If you need a new token, you can re-run the reCAPTCHA verification.

API Request
URL: https://www.google.com/recaptcha/api/siteverify

METHOD: POST

REQUEST PARAMETER:

secret Required. The shared key between your site and reCAPTCHA.
response Required. The user response token provided by the reCAPTCHA client-side integration on your site.
remoteip Optional. The user's IP address.

Sunday, May 5, 2019

Upload files with AngularJS in Asp.Net MVC 5 controller

AngularJS file upload using Asp.Net MVC and angular directive having ngFileSelect attribute.

While I was working to build a web application using ASP.NET MVC 5 and AngularJS, I have to build a  file upload functionality. I then stumbled upon a couple of AngularJS directives for File upload using Angular. Here I will explain how to upload file with AngularJS and Asp.Net MVC using jQuery formData.

Add new action into your controller for upload File functionality.

 public ActionResult SaveApplicationFile(HttpPostedFileBase httpPostedFile, string applicantName,
            string applicantEmail)
{
string fileSavePath = string.Empty;
try
{
if (System.Web.HttpContext.Current.Request.Files.AllKeys.Any())
{
if (httpPostedFile == null)
{
//return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
return Json(new { Valid = false, ErrorMessage = "No file is selected. Please select the file and try again." });
}
//Is the file too big to upload?
int fileSize = httpPostedFile.ContentLength;
var maxSizeMBs = 2;
var maxFileSize = maxSizeMBs * 1024 * 1024;
if (fileSize > (maxFileSize))
{
return Json(new { Valid = false, ErrorMessage = "Filesize of image is too large. Maximum file size permitted is " + maxSizeMBs + "MB" });
}

string contentType = httpPostedFile.ContentType; var dirFolder = applicantName;
dirFolder = RemoveWhitespace.RemoveWhitespaceLinq(dirFolder);
// server path
string tempFolderName = Server.MapPath("~/" + ConfigurationManager.AppSettings["Application.DocumentFolderName"] + "/" + dirFolder); string fileName = Path.GetFileName(httpPostedFile.FileName).Trim();
fileName = RemoveWhitespace.RemoveWhitespaceLinq(fileName);
fileSavePath = Server.MapPath("~/" + ConfigurationManager.AppSettings["Application.DocumentFolderName"] + "/" + dirFolder + "/" + fileName);
string filePath = "/" + ConfigurationManager.AppSettings["Application.DocumentFolderName"] + "/"
+ dirFolder + "/" + fileName; //db path if (!Directory.Exists(tempFolderName))
{
Directory.CreateDirectory(tempFolderName);
} TestApp.DataModel.FileContent fileContent = new TestApp.DataModel.FileContent();
fileContent.FileName = fileName;
fileContent.FilePath = filePath;
fileContent.ContentType = contentType;
fileContent.CreatedBy = applicantName; // save in db fileContent
var result = serviceHelper.SaveApplicationFile(fileContent); if (!result.IsExceptionOccured)
{
//save file image & pdf
string fileExt = Path.GetExtension(httpPostedFile.FileName).ToUpper(); if (httpPostedFile != null && httpPostedFile.ContentLength > 0 &&
(fileExt == ".PDF" || fileExt == ".DOC" || fileExt == ".DOCX"))
{
httpPostedFile.SaveAs(fileSavePath);
}
return Json(new { Valid = true, FilePath = fileSavePath });
}
else
{
return Json(new { Valid = false, ErrorMessage = result.ErrorMessage });
}
}
else
{
return Json(new
{
Valid = false,
ErrorMessage = "Please select file to upload"
});
}
}
catch (FileNotFoundException ex)
{
//NLogger.LogWrite().Info(ex.Message);
return Json(new
{
Valid = false,
ErrorMessage = ex.Message + " " + fileSavePath
});
}
catch (Exception ex)
{
//NLogger.LogWrite().Info(ex.Message);
return Json(new
{
Valid = false,
ErrorMessage = ex.Message + " " + fileSavePath
});
}
}

AngularJS Controller

Add a new js File for add a new AngularJS controller and a Directive. The file input type does not support 2 way binding, so we need to find an own solution for file uploads with AngularJS.
How to upload file using ng-file-Select attribute in angular. And save using Asp.Net MVC method on sever. We need to add headers in  angular $http post method.

$scope.SaveFile = function () {


            var formData = new FormData();
            formData.append("httpPostedFile", $scope.SelectedFileForUpload);

            //We can send more data to server using append to formData object.     
            formData.append("applicantName", $scope.applicantName); 
            formData.append("applicantEmail", $scope.applicantEmail); 

            $http.post("/Home/SaveApplicationFile", formData, {
                withCredentials: true,
                headers: { 'Content-Type': undefined },
                transformRequest: angular.identity
            }).success(function (response) {

                alert(response.ErrorMessage);
                
                $("#btnUpload").hide();
                //$("#btnUpload").prop('disabled', true);
                $scope.clearForm();
            }).error(function (error) {
                alert(error);
            })

        }

Angular Directive
ng-file-Select directive applying attribute to the html input file control, and also add $timeout for dependency injection in angularjs.

  .directive("ngFileSelect", ['$timeout', function ($timeout) {
        return {
            link: function ($scope, el) {
                el.bind("change", function (e) {
                    $scope.SelectedFileForUpload = (e.srcElement || e.target).files[0];
                   
                    var filename = $scope.SelectedFileForUpload.name; //$('input[type=file]').val().replace(/.*(\/|\\)/, '');
                    $scope.$apply(function () {
                        $scope.filename = filename;
                    });
                });
            }
        }
    }]);

How to Unit Test in Asp.Net C#

Unit Testing in DotNet C# Testing Frameworks in DotNet XUint - Most Popular testing framework is xUnit, which is now part of the open source...