Recaptcha in Angular JS - angularjs

I am implementing recaptcha in Angular JS, I am using "https://github.com/VividCortex/angular-recaptcha" url as reference. I have referred the Usage section and followed the instructions of code but still not able to get recaptcha in registration page.
Steps I have followed -
1. Generated a public key.
2. Added
3. Added div for recaptcha
Added the anular-recaptcha.js in page - downloded form github code of above url.
Can anyone please let me know what I am missing in it? Can anyone can give me demo example link for recaptcha?
Thanks in advance.

example that woked for me
register.cshtml:
<div vc-recaptcha key="'domain-key'" on-success="setResponse(response)"></div>
app.js:
var app = angular.module('myApp', ['ngRoute','vcRecaptcha']);
controller.js:
var ctrl = function ($rootScope, $scope, $location, $routeParams, registrationService) {
$scope.reCaptchaResponse = "";
$scope.setResponse = function (response) {
$scope.reCaptchaResponse = response;
};
$scope.register = function () {
var registration = {
...
reCaptchaResponse: $scope.reCaptchaResponse
}
$http.post(serviceBase + 'Register', registration).then(function (results) {
//return result
});
}
}
Controller.cs:
[HttpPost]
public JsonResult Register(UserDTO registration)
{
string responseFromServer = "";
WebRequest request = WebRequest.Create("https://www.google.com/recaptcha/api/siteverify?secret=mysecret&response=" + registration.ReCaptchaResponse);
request.Method = "GET";
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream);
responseFromServer = reader.ReadToEnd();
}
}
if(responseFromServer != "")
{
bool isSuccess = false;
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseFromServer);
foreach (var item in values)
{
if (item.Key == "success" && item.Value == "True")
{
isSuccess = true;
break;
}
}
if(isSuccess)
{
//do something
}
else
{
//return reCaptcha error
}
}
return Json(result);
}

Sorry if you have already checked this...
They have a demo file here.
They also mention ..."Keep in mind that the captcha only works when used from a real domain and with a valid re-captcha key, so this file wont work if you just load it in your browser."
I followed their instructions and it worked okay for me.

Step1: Include captcha directive in form.html
<body ng-app="angularRecaptcha">
<div class="col-md-6 col-md-offset-3 signupform" ng-controller="recapCtrl as recap">
<form name="recap.signupForm" ng-submit="recap.signup()">
.....
..
<!--Recaptcha Widget--->
<div vc-recaptcha key="recap.publicKey"></div>
...
.....
</form>
</div>
<body>
Step2: Next is the App.js
The angular-recaptcha library provides us with the vcRecaptchaService that has a getResponse() method, which provides us with g-captcha-response string after the user has successfully solved the captcha.
angular.module(‘angularRecaptcha’,[‘vcRecaptcha’])
.controller('recapCtrl',['vcRecaptchaService','$http',function(vcRecaptchaService,$http){
var vm = this;
vm.publicKey = "----YOUR------SITE--------KEY---";
vm.signup = function(){
/* vcRecaptchaService.getResponse() gives you the g-captcha-response */
if(vcRecaptchaService.getResponse() === ""){ //if string is empty
alert("Please resolve the captcha and submit!")
}else {
var post_data = { //prepare payload for request
'name':vm.name,
'email':vm.email,
'password':vm.password,
'g-recaptcha-response':vcRecaptchaService.getResponse() //send g-captcah-response to our server
}
/* MAKE AJAX REQUEST to our server with g-captcha-string */
$http.post('http://sitename.com/api/signup',post_data).success(function(response){
if(response.error === 0){
alert("Successfully verified and signed up the user");
}else{
alert("User verification failed");
}
})
.error(function(error){
})
}
}
}])
Step 3: Handle the POST request at api endpoint using SLIM PHP framework
<?php
$app->post('/signup',function() use($app){
$req = $app->request()->getBody(); //get request pramans
$data = json_decode($req, true); //parse json string
//Should be some validations before you proceed
//Not in the scope of this answer.
$captcha = $data['g-recaptcha-response']; //Captcha response send by client
//Build post data to make request with fetch_file_contents
$postdata = http_build_query(
array(
'secret' => '-----YOUR SECRET KEY-------', //secret KEy provided by google
'response' => $captcha, // g-captcha-response string sent from client
'remoteip' => $_SERVER['REMOTE_ADDR']
)
);
//Build options for the post request
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
//Create a stream this is required to make post request with fetch_file_contents
$context = stream_context_create($opts);
/* Send request to Googles siteVerify API */
$response=file_get_contents("https://www.google.com/recaptcha/api/siteverify",false,$context);
$response = json_decode($response, true);
if($response["success"]===false) { //if user verification failed
/* return error scenario to client */
echo json_encode(array(
"error" => 7,
"message" => "Robots Not allowed (Captcha verification failed)",
"captchaResult" => $response["success"],
"captcahErrCodes" => $response["error-codes"] //error codes sent buy google's siteVerify API
));
} else {
//Should be some Datatbase insertion to sign up the user
//before you return the success response
//Not in the scope of this answer.
/* return success scenario to client */
echo json_encode(array(
"error" => 0,
"message" => "Successfully signed up!",
"email" => $data['email'],
"captchaResult" => $response["success"]
));
}
});
?>

When working with angularjs and google recaptcha, the library you have used is the best option.
But you have to take care of the following things for it to work.
Include the library as explained into your angular project.
Register your website and get the site keys.
Include the widget, use your Site Key.
Get the required g-captcha-response after the user solves the captcha.
Make an ajax request to your server with the G-captcha-reposnse.
On your backend verify the g-captcha-response using google's site verify API.
This link has a good explaination with a working example. Google recaptcha with angularJS

Related

Why can't I see API Key prompt when connecting to my own data source?

I'm having trouble figuring out why can't I see a prompt to enter API key. I can connect directly without any authentication. Why is the API key ignored?
auth.js file:
function getAuthType() {
return {
type: 'KEY'
};
}
function validateKey(key) {
var url = 'http://myapi.com/endpoint?api_key=' + key;
var options = {
"method": "post",
"contentType":"application/json"
};
var response = JSON.parse(
UrlFetchApp.fetch(url, options)
);
Logger.log(response.data.length > 0)
return response.data.length > 0;
}
function isAuthValid() {
var userProperties = PropertiesService.getUserProperties();
var key = userProperties.getProperty('dscc.key');
return validateKey(key);
}
function resetAuth() {
var userProperties = PropertiesService.getUserProperties();
userProperties.deleteProperty('dscc.key');
}
function setCredentials(request) {
var key = request.key;
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('dscc.key', key);
return {
errorCode: 'NONE'
};
}
function isAdminUser() {
return false;
}
The Logger.log output:
I was using a http url. We've moved our API to https and the problem is solved. Data Studio doesn't show any error messages and skips the auth step. This is very strange.
Edit: A month later, while reviewing the document I noticed that Data Studio is already asking for us an https url.
Each prefix must use https://, not http://. source

Submit form(ReactJS) to Google Spreadsheet - change the message validation

I want to register data in a Google Sheet from a ReactJS form (2 fields if the user has possible suggestion or comments).
This is my feedback form in React :
import React,{useState,useEffect} from 'react';
import './App.css';
const formUrl = 'https://script.google.com/macros/s/AK.../exec'
export default function FrmTable(){
const [loading,setLoading] = useState(false)
return(
<div className="section-form">
<form name="frm"
method="post"
action={formUrl}
>
<div className="form-elements">
<div className="pure-group">
<label className="pure-group-label">Suggestion content pdf</label>
<input id="Suggestion content pdf" name="Suggestion content pdf" className="pure-group-text"
type="text"
/>
</div>
<div className="pure-group">
<label className="pure-group-label" >Comments</label>
<textarea id="Comments" name="Comments" rows="10" className="pure-group-text"
placeholder=""
maxLength="1000"
></textarea>
</div>
</div>
<p className="loading-txt">{loading == true ? 'Loading.....' : ''}</p>
<div className="pure-group pure-group-btn">
<button className="button-success pure-button button-xlarge btn-style" >Send</button>
</div>
</form>
</div>
)
}
The GSheet script in order to register the suggestion content and comments :
var SHEET_NAME = "Feedback";
// 2. Run > setup
// 3. Publish > Deploy as web app
// - enter Project Version name and click 'Save New Version'
// - set security level and enable service (most likely execute as 'me' and access 'anyone, even anonymously)
// 4. Copy the 'Current web app URL' and post this in your form/script action
//
// 5. Insert column names on your destination sheet matching the parameter names of the data you are passing in (exactly matching case)
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
// If you don't want to expose either GET or POST methods you can comment out the appropriate function
function doGet(e){
return handleResponse(e);
}
function doPost(e){
return handleResponse(e);
}
function handleResponse(e) {
// shortly after my original solution Google announced the LockService[1]
// this prevents concurrent access overwritting data
// we want a public lock, one that locks for all invocations
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
try {
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
// loop through the header columns
for (i in headers){
if (headers[i] == "Timestamp"){ // special case if you include a 'Timestamp(Date)' column
row.push(new Date());
} else { // else use header name to get data
row.push(e.parameter[headers[i]]);
}
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
} catch(e){
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
}
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
Everything works fine I can register the 2 fields(suggestion and comment) in the GSheet but I would like to have another view after submiting
I've followed some tutorials because I'm new into React. At the end after submiting you are sent to script.googleusercontent.... because in the GSheet script we have this code
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
I want just to show a simple message like a popup in order to say the submit form is ok. Any idea is welcomed :) thank you very much.
New Edit : I've changed my code (React + Google Script) but I have an CORB blocked cross-origin.
import React,{useState,useEffect} from 'react';
import './App.css';
const formUrl = 'https://script.google.com/macros/s/AKfycbz4hMELOHff2Yd_ozpOid2cAWFSWPm_7AOD15OIeQRdYrocv0wa/exec'
export default function FrmTable(){
const jsonp = (url, callback) => {
var callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random());
window[callbackName] = function(data) {
alert("Formulaire envoyé ");
delete window[callbackName];
document.body.removeChild(script);
callback(data);
};
var script = document.createElement('script');
script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName;
document.body.appendChild(script);
}
const mySubmitHandler = (event) => {
event.preventDefault();
jsonp(formUrl + '?La+FAQ+en+question=' + encodeURIComponent(faqName), (data) => {
// alert(data);
});
event.target.reset();
}
// const { register, errors, required ,handleSubmit } = useForm();
const [loading,setLoading] = useState(false)
const [faqName,setFaqName] = useState('')
const myChangeHandler1 = (event) => {
setFaqName(event.target.value);
}
return(
<div className="section-form" >
<form name="frm"
method="post"
onSubmit={mySubmitHandler}
>
<div className="form-elements">
<div className="pure-group ">
<label className="pure-group-label">La FAQ en question </label>
<input name="FAQ en question" className="pure-group-text"
type="text" onChange={myChangeHandler1}
/>
</div>
</div>
<input type='submit' />
</form>
</div>
)
}
The Google Script :
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
// If you don't want to expose either GET or POST methods you can comment out the appropriate function
function doGet(e){
return handleResponse(e);
}
function doPost(e){
//return handleResponse(e);
}
function handleResponse(e) {
// shortly after my original solution Google announced the LockService[1]
// this prevents concurrent access overwritting data
// [1] http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html
// we want a public lock, one that locks for all invocations
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
try {
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
// loop through the header columns
for (i in headers){
if (headers[i] == "Timestamp"){ // special case if you include a 'Timestamp(Date)' column
row.push(new Date());
} else { // else use header name to get data
row.push(e.parameter[headers[i]]);
}
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
var callback = e.parameter.callback;
// return json success results
// return ContentService
// .createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
// .setMimeType(ContentService.MimeType.JSON);
return ContentService.createTextOutput(callback+'('+ JSON.stringify({"result":"success", "row": nextRow})+')').setMimeType(ContentService.MimeType.JAVASCRIPT);
} catch(error){
// if error return this
//return ContentService
// .createTextOutput(JSON.stringify({"result":"error", "error": e}))
// .setMimeType(ContentService.MimeType.JSON);
var callback = e.parameter.callback;
return ContentService.createTextOutput(callback+'('+ JSON.stringify({"result":"error", "error": error})+')').setMimeType(ContentService.MimeType.JAVASCRIPT);
} finally { //release lock
lock.releaseLock();
}
}
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
I would like to propose the following 2 patterns.
Modification points:
In the current stage, there is no getPublicLock().
In your shared Spreadsheet, there is only one sheet of Sheet2. But at var SHEET_NAME = "Feedback";, no sheet name is used. By this, var sheet = doc.getSheetByName(SHEET_NAME); is null and an error occurs at var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].
At formUrl + "&Commentaires=" + encodeURIComponent(faqComment) in react side, in this case, the endpoint becomes https://script.google.com/macros/s/###/exec&Commentaires=test?callback=jsonp_callback_###.
Pattern 1:
In this pattern, your script is modified and JSONP is used.
React side: App.js
From:
jsonp(formUrl + "&Commentaires=" + encodeURIComponent(faqComment), data => {
// alert(data);
});
To:
jsonp(formUrl + "?Commentaires=" + encodeURIComponent(faqComment), data => {
// alert(data);
});
Google Apps Script side:
When you want to use your shared Spreadsheet, please modify as follows.
From:
var lock = LockService.getPublicLock();
To:
var lock = LockService.getDocumentLock();
And,
From:
var SHEET_NAME = "Feedback";
To:
var SHEET_NAME = "Sheet2";
In this case, you can also modify the sheet name from Sheet2 to Feedback instead of modifying the script.
Pattern 2:
In this pattern, your script is modified and fetch is used instead of JSONP. Because when above script is used, I could confirm that there is sometimes the error related to CORS. So as another pattern, I would like to propose to use fetch. When fetch is used, I could confirm that no error related to CORS occurs.
React side: App.js
From:
export default function FrmTable() {
const jsonp = (url, callback) => {
var callbackName = "jsonp_callback_" + Math.round(100000 * Math.random());
window[callbackName] = function(data) {
alert("Formulaire envoyé ");
delete window[callbackName];
document.body.removeChild(script);
callback(data);
};
var script = document.createElement("script");
script.src =
url + (url.indexOf("?") >= 0 ? "&" : "?") + "callback=" + callbackName;
document.body.appendChild(script);
};
const mySubmitHandler = event => {
event.preventDefault();
/* const request = new XMLHttpRequest();
const formData = new FormData();
formData.append("La FAQ en question", form.faqName);
formData.append("Suggestion contenu pdf", form.faqSuggest);
formData.append("Commentaires", form.faqComment);
request.open("POST", formUrl);
request.send(formData); */
jsonp(formUrl + "&Commentaires=" + encodeURIComponent(faqComment), data => {
// alert(data);
});
event.target.reset();
};
To:
export default function FrmTable() {
const mySubmitHandler = event => {
event.preventDefault();
fetch(formUrl + "?Commentaires=" + encodeURIComponent(faqComment))
.then(res => res.text())
.then(res => console.log(res))
.catch(err => console.error(err));
event.target.reset();
};
In this case, res.json() can be also used instead of res.text().
Google Apps Script side:
When you want to use your shared Spreadsheet, please modify as follows.
From:
var lock = LockService.getPublicLock();
To:
var lock = LockService.getDocumentLock();
And,
From:
var callback = e.parameter.callback;
return ContentService.createTextOutput(callback+'('+ JSON.stringify({"result":"success", "row": nextRow})+')').setMimeType(ContentService.MimeType.JAVASCRIPT);
} catch(error){
var callback = e.parameter.callback;
return ContentService.createTextOutput(callback+'('+ JSON.stringify({"result":"error", "error": error})+')').setMimeType(ContentService.MimeType.JAVASCRIPT);
} finally { //release lock
lock.releaseLock();
}
To:
return ContentService.createTextOutput(JSON.stringify({"result":"success", "row": nextRow})).setMimeType(ContentService.MimeType.JSON);
} catch(error){
return ContentService.createTextOutput(JSON.stringify({"result":"error", "error": error})).setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
And,
From:
var SHEET_NAME = "Feedback";
To:
var SHEET_NAME = "Sheet2";
In this case, you can also modify the sheet name from Sheet2 to Feedback instead of modifying the script.
Note:
When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be careful this.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script
Class LockService

How to delete an element from google datastore as well as my html page using delete method?

Iam currently using flask and google datastore and working on it
#app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
pass
return jsonify({'result': True})
Ive used get and post and also put method for inserting retrieving and updating now i need to delete using delete request
I tried to pass the respective id value by using href in my html page but I found it doesnt work that way !
def delete_method(task_id):
k = ndb.Key('ToDo', task_id)
k.delete()
return jsonify({"success":True})
The above code works fine and the ajax request is as follows
function delData(){
var id = this.id
//console.log(id)
var url = '/DELETE/todo/api/v1.0/task/';
var xhr = new XMLHttpRequest();
xhr.open("DELETE", url+id, true);
xhr.onload = function () {
var jsonResponse = JSON.parse(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == "200") {
console.log(jsonResponse);
var elem = document.getElementById(id).parentNode;
while (elem.firstChild) {
elem.removeChild(elem.firstChild);
}
}
else {
console.error(jsonResponse);
}
}
xhr.send(null);
}

API REST with CodeIgniter and AngularJS (get working; delete, save and update not working)

I'm building an API REST with CodeIgniter 3 and AngularJS following this video. The video is in Spanish, but it's a great material: https://www.youtube.com/watch?v=SjXpVJi6pHY.
I cannot figure it out why am I able to retrieve the books (it's a little books database that we are making as an example) from the database. But I'm not able to remove, edit or add them.
Focusing, at the moment only on deleting a book:
If I click on the first book from the list I get:
DELETE http://localhost/codeigniter/restangularjs/books/1 400 (Bad Request)
And if I click on the second book on the list I get the same error, just with number 2 at the end.
So the system knows which controller to call, and even passes it the correct id of the book (number 1 for the first book and number 2 for the second book).
Below I'm attaching all the relevant files that are needed for deleting a book. I don't know where to start and would appreciate some guidance.
I find it strange that in the factory named Book (the only factory in app.js) we only define update (used in the EditCtrl). But we do not for example define save (used in CreateCtrl), delete or get (both used in HomeCtrl).
On the other hand it seems to me that as we are dealing with a REST_Controller (Books.php is not a CI_Controller, but a REST_Controller) update could work for all the calls (so not just for update, but also for save, delete and get).
I'm even more inclined to that option as the function Books.get (inside HomeCtrl) ...
Books.get(function(data){
$scope.books = data.response;
});
... is the only function that is working properly, even though there is no get call inside the factory.
But I don't know. I really don't know. This is my first API REST.
My tree (on xampp/htdocs with the relevant folders and files only):
codeigniter
--restangularjs
----application
------controllers
--------Books.php
------models
--------Books_model.php
angularjs
--ciangularrest
----src
------index.html
------app.js
------components
--------list.html
CodeIgniter - extract from Books.php (controller)
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
require APPPATH . "/libraries/REST_Controller.php";
class Books extends REST_Controller
{
public function __construct()
{
// Ne vem, če je spodnjo vrstico header('Access-Control-Allow-Origin: *'); varno pisati - fora je v tem, da z zvezdico daš dostop vsem. Preveri.
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
$method = $_SERVER['REQUEST_METHOD'];
if($method == "OPTIONS") {
die();
}
parent::__construct();
$this->load->model('books_model');
}
public function index_get()
{
$books = $this->books_model->get();
if( ! is_null($books))
{
$this->response(array("response" => $books), 200);
} else
{
$this->response(array("error" => "No books available"), 404);
}
}
// Other functions here but not relevant for my post on StackOverflow
public function index_delete()
{
if( ! $id)
{
$this->response(NULL, 400);
}
$delete = $this->books_model->delete($id);
if( ! is_null($delete))
{
$this->response(array("response" => "Book deleted"), 200);
} else
{
$this->response(array("error" => "There was an error"), 400);
}
}
}
CodeIgniter - extract from User_model.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Books_model extends CI_Model {
public function __construct()
{
parent::__construct();
}
public function get($id = NULL)
{
if( ! is_null($id))
{
$query = $this->db->select("*")->from("books")->where("id", $id)->get();
if($query->num_rows() === 1)
{
return $query->row_array();
}
return NULL;
}
$query = $this->db->select("*")->from("books")->get();
if($query->num_rows() > 0)
{
return $query->result_array();
}
return NULL;
}
public function delete($id)
{
$this->db->where("id",$id)->delete("books");
if($this->db->affected_rows() === 1)
{
return TRUE;
}
return NULL;
}
}
AngularJS - extract from app.js
.controller('HomeCtrl', ['$scope', 'Books', '$route', function ($scope, Books, $route) {
Books.get(function(data)
{
$scope.books = data.response;
});
$scope.remove = function(id)
{
console.log("inside remove function; " + "deleting the book with id=" + id);
Books.delete({id:id}).$promise.then(function(data)
{
if(data.response)
{
$route.reload();
}
})
}
}])
.factory('Books', ["$resource", function($resource){
return $resource(
"http://localhost/codeigniter/restangularjs/books/:id",
{id:"#_id"},
{update: {method: "PUT", params: {id: "#_id"}}}
)
}])
AngularJS - extract from list.html
<a ng-click="remove(book.id)">Delete</a>

angular post request to a asp.net web API server

IN angular js i am trying to send a post request her is the controller.
.controller('ActivationController',['$http','$location','$routeParams','AuthService',
function($http, $location, $routeParams, AuthService){
var location = $location.path();
var activation_code = $routeParams.code;
var activationLink = "http://localhost:18678/api/User/ActivateUser";
console.log(activation_code);
if(activation_code){
$http({method:"post", url:activationLink, data:activation_code}).success(function(response){
console.log(response);
}).error(function(error){
console.log(error);
});
}
}]);
and in asp.net web API her is the method.
[HttpPost]
public HttpResponseMessage ActivateUser([FromBody]string activation_code)
{
if (!string.IsNullOrWhiteSpace(activation_code))
{
string decode_token = HttpUtility.UrlDecode(activation_code); ;
string token_string = Crypto.Decrypt(activation_code, passPhrase);
if (token_string != null)
{
User activateAcc = db.Users.Where(user => user.ConfirmToken == token_string).SingleOrDefault();
if (activateAcc != null)
{
activateAcc.IsActive = true;
try
{
db.SaveChanges();
var credential = new UserCredential();
credential.EmailAddress = activateAcc.UserMail;
credential.Password = activateAcc.UserPassword;
return Request.CreateResponse(HttpStatusCode.OK, credential);
}
catch
{
return Request.CreateResponse(HttpStatusCode.Ambiguous, "cannot confirm account");
}
}
else
{
return Request.CreateResponse(HttpStatusCode.NotAcceptable, "invalid account");
}
}
else
{
return Request.CreateResponse(HttpStatusCode.NoContent, "invalid token data");
}
}
else
{
return Request.CreateResponse(HttpStatusCode.NoContent, "missing activation code");
}
}
The problem is when the controller fire the request is made but without sending any data to the server. The [FromBody]string activation_codeis null
Wrap your parameter in quotes:
$http({method:"post", url:activationLink, data: '"' + activation_code + '"'});
Explanation
For Web API to bind to a simple string primitive, the body must be specified as:
"some string here"
For example:
POST http://localhost:5076/api/values HTTP/1.1
User-Agent: Fiddler
Host: localhost:5076
Content-Type: application/json
Content-Length: 7
"Alice"
The quotes are important. For more information, check this article.

Resources