How to implement reCaptcha "v2" in ASP.NET Core MVC? - asp.net-core-mvc

I want to add Recaptcha, the second version, not another version, and I want it to be in ASP.NET Core, not MVC, and I searched a lot and did not find the solution.. I hope for help
I have a login controller :
public IActionResult Login([Bind("Username , Password")] User userLogin)
{
const string id = "id";
var auth = _context.Users.Where(x => x.Username == userLogin.Username &&
x.Password == userLogin.Password).SingleOrDefault();
var x = _context.Users.Where(x => x.Username == userLogin.Username && x.Password
== userLogin.Password).Select(i => i.UserId).FirstOrDefault();
if (auth != null)
{
// 1 > admin
// 2 > Accountant
// 3 > customer
switch (auth.RoleId)
{
case 1: // admin
HttpContext.Session.SetInt32(id, (int)x);
return RedirectToAction("Index", "Home");
case 2:
HttpContext.Session.SetInt32(id, (int)x);
return RedirectToAction("AccountantDashboard", "Home");
case 3:
HttpContext.Session.SetInt32(id, (int)x);
return RedirectToAction("Home", "Home");
}
}
return View();
}
and another for view (head and body)
<form asp-action="Login" enctype="multipart/form-data">
<div class="input-group">
<label asp-for="Username" class="input--style-2" placeholder="username"></label>
<input asp-for="Username" class="input--style-2" />
<span asp-validation-for="Username" class="text-danger"></span>
</div>
<div class="input-group">
<label asp-for="Password" class="input--style-2" placeholder="Password"></label>
<input asp-for="Password" type="password" class="input--style-2" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="p-t-30">
<button class="btn btn--radius btn--green" type="submit" value="Create">Login</button>
</div>
<div style="position: relative ; left: 350px ; bottom: -50px">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Home">Or back to home page</a>
</div>
</form>

As far as I know, the reCaptcha "v2" is build based on js and we could directly use it inside the html page.
We could use it like this, firstly put below codes inside your view and it is used to put the g-recaptcha and it contains a callback method, if this method is called that means the user has passed the validation and you could show the button by using JQuery or javascript.
<div class="g-recaptcha" data-callback="recaptcha_callback" data-sitekey="xxxxx"></div>
Like this:
<script type="text/javascript">
function recaptcha_callback(){
$('#login).show();
}
</script>
More details, you could refer to this article.

Related

Why has my unobtrusive ajax stopped updating my partial view in ASP.NET Core 3.1?

I'm using unobtrusive ajax inside a kendo window to update a form once it's been filled in. The form should update the Id's of the DOM elements dynamically and also show the relative data inside the form as returned from the controller.
Let's start, here is the window element that houses the partial view which is a form:
#model Requirement
#{
int localId = Model.Id;
}
<div class="window-content">
<form method="post" data-ajax-url="/Home/Process_Requirement" data-ajax="true" data-ajax-method="post" data-ajax-loading="#spinner" data-ajax-update="#update-form-requirement" data-ajax-success="form_requirement_success">
<div id="update-form-requirement">
<partial name="_Form_Requirement" />
</div><!--/update-panel-->
<div class="window-footer">
<div class="container">
<div class="row no-gutters">
<div class="col">
<button type="submit" class="input-submit float-right">Save</button>
</div>
</div>
</div>
</div>
</form>
</div>
_Form_Requirement
#model Requirement
#{
int localId = Model.Id;
}
<div class="tab-content">
<div class="tab-pane fade show active" id="form-requirement-basic-#localId" role="tabpanel" aria-labelledby="requirement-tab">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="text" id="Id_#localId" name="Id" asp-for="Id" readonly />
<input type="text" id="CreatedUser_#localId" asp-for="CreatedUser" readonly />
<div class="container">
<div class="row">
<div class="col">
<div class="form-group">
<label>Vessel Type</label>
<kendo-dropdownlist name="VesselType"
for="VesselType"
id="VesselType_#localId"
datatextfield="TypeName"
datavaluefield="Id"
min-length="3"
style="width: 100%"
value-primitive="true"
option-label="Select vessel type"
footer-template="<button class='dropdown-button k-icon k-i-plus-outline' data-object-title='Add vessel type' data-object-function='_Window_Vessel_Type' onclick='open_data_window(this, event)'></button>"
filter="FilterType.Contains">
<datasource type="DataSourceTagHelperType.Ajax" page-size="80">
<transport>
<read url="/Vessel/ReadVesselTypes" />
</transport>
</datasource>
<popup-animation>
<open duration="300" effects="fadeIn" />
<close duration="300" effects="fadeOut" />
</popup-animation>
</kendo-dropdownlist>
</div>
</div>
</div>
</div>
</div>
</div>
When the form is submitted the controller action does the following:
/Home/Process_Requirement
public IActionResult Process_Requirement(Requirement model)
{
//Define the partial view we want
string modal = "_Form_Requirement";
//If the Id is 0 then create a new requirement
if (model.Id == 0)
{
if (ModelState.IsValid)
{
try {
_requirementService.InsertRequirement(model);
var getData = _requirementService.GetRequirement(model.Id);
return PartialView(modal, getData);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
else
{
try
{
_requirementService.UpdateRequirement(model);
return PartialView(modal, model);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return PartialView(modal);
}
So, when you first open a window to create a new requirement the localId is 0 because you're not editing one, that's expected behavior.
When you then fill in all the details and submit the form, the data is posted to the database and saved correctly but the model doesn't seem to update with the new data, for example the input for the Id remains as 0:
<input type="text" id="Id_#localId" name="Id" asp-for="Id" readonly />
yet the id for the input updates to the newly created id number. Why is this happening and can I do anything about it?
you have a bug. fix the last return
return PartialView(modal,model);
Is the Id primary key? If so, it is not recommend to change the primary key, you should add a new column to be the key.
the data is posted to the database and saved correctly but the model doesn't seem to update with the new data
This could be caused by the concurrency issues. I can't see your update code now, but you can
try to change your update code like this:
public async Task<IActionResult> Process_Requirement(Requirement model)
{
string modal = "_Form_Requirement";
if (model.Id == 0)
{
//....
}
else //to update
{
await TryUpdateModelAsync<Requirement>(_context.Requirements.FirstOrDefault(x => x.RId ==model.RId),"",c => c.Id, c => c.CreatedUser);
_context.SaveChanges();
return PartialView(modal, model);
}
return PartialView(modal);
}
My Model:
public class Requirement
{
[Key]
public int RId { get; set; } //new column
public int Id { get; set; }
public string CreatedUser { get; set; }
}
And in partial, pass the key with a hidden field:
<input type="text" asp-for="RId" hidden/>
<input type="text" id="Id_#localId" name="Id" asp-for="Id" />
<input type="text" id="CreatedUser_#localId" asp-for="CreatedUser" />
Result:

Razor Pages Net Core auto reload partial view on set frequency

I am still trying to get to grips with Razor Pages for Net Core and seem to be a bit stuck on this. I have my Index.cshtml:
#page
#model IndexModel
<input type="hidden" name="hdnPageSelector" id="hdnIndexPage" />
<div class="text-center">
<p>Welcome to</p>
<h1 class="display-4">"My Web App"</h1>
</div>
<div class="form-row">
<div class="form-group col-md-2">
<partial name="IndexPartials/_Navigation" />
</div>
<div class="form-group col-md-1">
</div>
<div class="form-group col-md-6">
<partial name="IndexPartials/_Body" />
</div>
<div class="form-group col-md-1">
</div>
<div id="refreshMembers" class="form-group col-md-2">
<partial name="IndexPartials/_Members" />
</div>
</div>
Note the last div has an id="refreshMembers".
The partial view (_Members) that is loaded there looks like this:
#model IndexModel
<label>Members</label>
<br />
#{
foreach (ApplicationUser user in Model.AppUsersList)
{
if (user.IsLoggedIn)
{
<label>#user.FirstName #user.LastName </label>
<span class="dot"></span>
}
else
{
<label>#user.FirstName #user.LastName</label>
}
}
}
Within the controller I have a property called:
public IList<ApplicationUser> AppUsersList { get; set; }
And this is populated on OnGetAsync() as follows:
AppUsersList = _userManager.Users.OrderBy(x => x.FirstName).Where(y => y.UserName != currentUser.UserName).ToList();
This is fine, the page loads with the partial view populated as expected. I now want the partial to refresh every 5 seconds so I have put this piece of Javascript/JQuery in place:
$(function () {
setInterval(function () {
$("#refreshMembers").load("/Index?handler=RefreshMembers");
}, 5000);
});
with the following method setup:
public async Task<IActionResult> OnGetRefreshMembers()
{
var currentUser = await _userManager.GetUserAsync(User);
AppUsersList = _userManager.Users.OrderBy(x => x.FirstName).Where(y => y.UserName != currentUser.UserName).ToList();
return new PartialViewResult
{
ViewName = "_Members",
ViewData = new ViewDataDictionary<List<ApplicationUser>>(ViewData, AppUsersList)
};
}
However the partial view doesn't get refreshed. If I put a breakpoint within this method I can see it is being hit every 5 seconds, despite Devtools stating there is an error on each attempt:
In a nut shell, I just can't seem to get my partial view to be reloaded every 5 seconds. It feels like I am close but just missing something and don't know what that is.
Having been reminded to check the Output window in VS a bit better, I found the cause of my problems... Well two things actually. This is the corrected method:
public async Task<IActionResult> OnGetRefreshMembers()
{
var currentUser = await _userManager.GetUserAsync(User);
AppUsersList = _userManager.Users.OrderBy(x => x.FirstName).Where(y => y.UserName != currentUser.UserName).ToList();
return new PartialViewResult
{
ViewName = "IndexPartials/_Members",
ViewData = new ViewDataDictionary<IndexModel>(ViewData, this)
};
}
Where...
I didn't include the folder that the partial lives in when naming it on the PartialViewResult
I need to return the entire IndexModel object - having updated the AppUserList property, and not just the list of AppUsers.

How to solve " No mapping for GET HTTP URL"

I am working on webapp using spring mvc + hibernate. I am getting a warning as
WARN [org.springframework.web.servlet.PageNotFound] (default task-1) No mapping for GET /ProjectFE/deleteproducts/
here's my code for Controller mapped deleteproducts:
#DeleteMapping(value="/deleteproducts/{productId}")
public String deleteProduct(#PathVariable("productId")int productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(productId);
if(b)
return "success";
else
return "deleteproducts";
}
jsp view:
<body>
<form id="update product form" action="${pageContext.request.contextPath}/deleteproducts" style="display: none;">
<div class="form-group row">
<label for="product Id" class="col-sm-2 col-form-label">Id</label>
<div class="col-sm-10">
<input type="text" name="productId" class="form-control" id="productId" placeholder="Enter the product Id you want to delete">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</div>
</div>
</form>
</body>
DAOImplementation for delete method call:
public boolean deleteProduct(int productId)
{
boolean b = true;
try
{
sess.beginTransaction();
Products p = (Products)sess.load(Products.class, new Integer(productId));
sess.delete(p);
sess.getTransaction().commit();
}catch(Exception ex)
{
sess.getTransaction().rollback();
b = false;
}
return b;
}
can this issue be occurring because of the /{productId} part ? Please some one help!!
Thankyou.
First, create a controller to go to deleteproduct.jsp page. So write a controller like
#GetMapping(value="/delete")
public String deleteProduct() {
return "deleteproducts";
}
So hit /delete to got to page then do as you want.
Change your #DeleteMapping to #GetMapping. And use #RequestParam instead of #PathVariable. So your controller will be like
#GetMapping(value="/deleteproducts")
public String deleteProduct(#RequestParam(value="productId")String productId) {
IProductsDAO ip = new ProductsDAOImpl();
boolean b = ip.deleteProduct(Integer.parseInt(productId));
if(b)
return "success";
else
return "deleteproducts";
}
And write your form like
<form id="searchForm" class="form-horizontal" action="${pageContext.request.contextPath}/deleteproducts">
<div class="input-group">
<input name="productId" placeholder="Delete product with id" class="form-control productId"
type="text">
<span class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
</form>
You are trying to get an endpoint which doesn't exists. Why?
When you specify an endpoint /some_end_point and you trying to reach it with http protocol, it will expect you to specify the request method (GET / POST / PUT / DELETE / etc...).
When you have those 2 parameters /some_end_point + POST you need to map it in your server side like this -> #PostMapping("/some_end_point").
If the client (or another server) will try to reach /some_end_point + GET it will fail because it doesn't exists, only /some_end_point + POST exists, therefor you have to add another endpoint which will be #GetMapping("/some_end_point") and so on.
You are sending a GET request,
but you annotated with #DeleteMapping - which expects a DELETE request.

Redirect in POST method in Iris Framework

I'm trying to redirect from the login page to the home page in the POST method, but the form doesn't redirect to any page after clicking on the submit button.
I'm using the MVC structure of Iris Framework and the Ctx.Redirect method to redirect to the desired page, but it's not working.
// login_controllers.go
package controllers
import (
"github.com/kataras/iris/mvc"
"github.com/kataras/iris"
"fmt"
)
type LoginFormData struct {
Email string
Password string
}
type LoginController struct {
mvc.C
}
func (c *LoginController) Get() mvc.Result {
return mvc.View{
Name: "login.html",
}
}
func (c *LoginController) Post() {
userLoginData := LoginFormData{}
err := c.Ctx.ReadForm(&userLoginData)
if err != nil {
c.Ctx.StatusCode(iris.StatusInternalServerError)
c.Ctx.WriteString(err.Error())
}
if userLoginData.Email == "teste#teste.com" && userLoginData.Password == "123" {
c.Ctx.Redirect("/", iris.StatusSeeOther)
fmt.Printf("UserInner: %#v", userLoginData)
c.Ctx.Writef("UserInner: %#v", userLoginData)
}
}
The form HTML code is:
<form class="m-login__form m-form" action="/login" method="post">
<div class="form-group m-form__group">
<input class="form-control m-input" type="text" placeholder="Email" name="Email" autocomplete="off">
</div>
<div class="form-group m-form__group">
<input class="form-control m-input m-login__form-input--last" type="password" placeholder="Password" name="Password">
</div>
<div class="row m-login__form-sub">
<div class="col m--align-left">
<label class="m-checkbox m-checkbox--focus">
<input type="checkbox" name="remember">
Remember me
<span></span>
</label>
</div>
<div class="col m--align-right">
<a href="javascript:;" id="m_login_forget_password" class="m-link">
Forgotten password ?
</a>
</div>
</div>
<div class="m-login__form-action">
<button id="m_login_signin_submit" class="btn btn-focus m-btn m-btn--pill m-btn--custom m-btn--air">
Login
</button>
</div>
</form>
Isn't possible to redirect in a POST method in Iris Framework/Go?
As #mkopriva said you have to call .Redirect and return from the function body, Redirect should be the last call because it sends the status code and a header location back to the client, you don't have to write anything else, browser/client will redirect and write the content of the redirect path.
Although iris.StatusSeeOther (http status code: 303) works on the mvc examples the iris repository has, you may want to try other statuses and check if that works (clear your browser's cache on each try for any case), for example iris.StatusTemporaryRedirect (http status code: 307) or search on google for the correct redirect status code that suits your needs better.
Please take a look at the https://github.com/kataras/iris/tree/master/_examples as well.

CakePHP ajax with Js Helper loads the page rather than the template for success, why?

I am trying to make a form submit through ajax and the JsHelper from CakePHP 1.3
I try to make a call to /eng/feedbacks/submit_feedback but instead in the console, i see a post to http://lang/eng/pa/homepage instead. The result returned is another instance of that page, rather than anything else.
This seems to be irrelevant to whether such submit_feedback exists or not. I have started that action with die("test"); and it doesn't change anything.
why is that, what is going on?
the form is in my layout (as i want it to be in my footer). Runs when the url is /eng/pa/homepage
Form code:
echo $this->Form->create('Feedback', array('url'=>array( 'controller'=>'feedbacks', 'action'=>'submit_feedback')));
echo $this->Form->input('Feedback.content', array('label'=>false, 'type'=>'textarea'));
echo $this->Js->submit('Save', array('class'=>'button blue',
'before'=>$this->Js->get('#sending')->effect('fadeIn'),
'success'=>$this->Js->Get('#sending')->effect('fadeOut'),
'update'=>'#success'
));
echo $this->Form->end();?>
<div id="success">xx</div>
In that #success DIV i get a related full page, rather than what I have defined in the controller action
Controller method:
function submit_feedback(){
if(!empty($this->data)){
$this->Feedback->set($this->data);
if($this->Feedback->validates()){
if($this->Feedback->save($this->data)){
// AJAX
if($this->RequestHandler->isAjax()){
$this->render('/feedbacks/success', 'ajax');
}else{
die('not ajax');
}
}
}
}
}
And the success template is:
<p style="background: lightgreen">Purple cow!</p>
What am i doing wrong?
NOTE: If I run the same form from the /eng/feedbacks/submit_feedback page, It works exactly as it should through ajax, and my database gets updated, i get the necessary 'success' template loaded and all is shiny and happy.
UPDATE: FORM SOURCE COUDE GENERATED:
<form accept-charset="utf-8" action="/eng/feedbacks/submit_feedback" method="post" id="FeedbackReadForm">
<div style="display: none;">
<input type="hidden" value="POST" name="_method">
</div>
<input type="hidden" id="FeedbackUserId" value="141" name="data[Feedback][user_id]">
<div class="input radio">
<input type="hidden" value="" id="FeedbackType_" name="data[Feedback][type]">
<input type="radio" value="suggestion" id="FeedbackTypeSuggestion" name="data[Feedback][type]">
<label for="FeedbackTypeSuggestion">Suggestion</label>
<input type="radio" value="problem" id="FeedbackTypeProblem" name="data[Feedback][type]">
<label for="FeedbackTypeProblem">Poblem</label>
<input type="radio" value="opinion" id="FeedbackTypeOpinion" name="data[Feedback][type]">
<label for="FeedbackTypeOpinion">Other Opinion</label>
</div>
<div class="input textarea">
<textarea id="FeedbackContent" rows="6" cols="30" name="data[Feedback][content]"></textarea>
</div>
<div style="margin-top: 17px; margin-right: 50px;" class="right">
<a onclick="javascript: closeFeedbackPuller(); return false;" href="#">Cancel</a>
</div>
<div class="submit">
<input type="submit" value="Save" id="submit-396027771" class="button blue">
</div>
</form>
UPDATE 2: JS generated:
$(document).ready(function () {
$("#submit-396027771").bind("click", function (event) {
$.ajax({
beforeSend:function (XMLHttpRequest) {
$("#sending").fadeIn();
},
data:$("#submit-396027771").closest("form").serialize(),
dataType:"html",
success:function (data, textStatus) {
$("#sending").fadeOut();
$("#success").html(data);
},
type:"post",
url:"\/eng\/pa\/homepage"
});
return false;
});
});
I see that the url is wrong, even thought the form url was right. How can this be resolved?
echo $this->Js->submit('Save', array('class'=>'button blue',
'before'=>$this->Js->get('#sending')->effect('fadeIn'),
'success'=>$this->Js->Get('#sending')->effect('fadeOut'),
'url' => '/eng/feedbacks/submit_feedback',
'update'=>'#success'
));
That may fix your problem, but I am not 100% sure. It seems that the Js->submit() method accepts a lot of the Form helper methods.

Resources