Handler method not firing when called by form in Razor Pages - forms

I've gone through dozens of articles, docs, and stack overflow questions (even the one with a similar intro)regarding the same issues but it still persists.
I've tried this with putting the functions in the .cshtml.cs page and on the .cshtml page, named and unnamed handler names, different framework for sending emails, and adding an empty action field in the form along with other fixes but the issue seems to be that the handler method itself is not firing while the form is submitting. Any and all help is appreciated and please let me know if more information is needed.
My HTML form:
<form method="POST" asp-page-handler="email">
<!-- Name input-->
<div class="form-floating mb-3">
<input class="form-control" name="clientName" type="text" placeholder="Enter your name..." required/>
<label for="name">Full name*</label>
</div>
<!-- Email address input-->
<div class="form-floating mb-3">
<input class="form-control" name="clientEmail" type="email" placeholder="name#example.com" required/>
<label for="email">Email address*</label>
</div>
<!-- Phone number input-->
<div class="form-floating mb-3">
<input class="form-control" name="clientPhone" type="tel" placeholder="(123) 456-7890"/>
<label for="phone">Phone number</label>
</div>
<!-- Message input-->
<div class="form-floating mb-3">
<textarea class="form-control" name="clientMessage" type="text" placeholder="Enter your message here..." style="height: 10rem" required></textarea>
<label for="message">Message*</label>
</div>
<!-- Submit Button-->
<div class="d-grid"><button class="btn btn-primary btn-xl" type="submit" value="submit">Submit</button></div>
</form>
My functions as they are currently:
public void OnPostEmail()
{
var clientEmail = Request.Form["clientEmail"];
var clientName = Request.Form["clientName"];
var clientPhone = Request.Form["clientPhone"];
var clientMessage = Request.Form["clientMessage"];
sendEmail(clientEmail, clientName, clientPhone, clientMessage);
}
public void sendEmail(string clientEmail, string clientName, string clientPhone, string clientMessage)
{
var errorMessage = "";
try
{
// Initialize WebMail helper
WebMail.SmtpServer = "smtp.google.com";
WebMail.SmtpPort = 587;
WebMail.UserName = "***#gmail.com";
WebMail.Password = "MYPASSWORD";
WebMail.From = "***#gmail.com";
WebMail.EnableSsl = true;
// Send email
WebMail.Send(to: clientEmail,
subject: $"Request from: + {clientName}",
body: $"{clientMessage}\nPhone: {clientPhone}\nEmail: {clientEmail}"
);
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
}

Related

Spring boot controller not redirecting correctly

I am experiencing a problem with the redirect of the method below in my controller class.
When I click on the submit button it does not redirect me to http://localhost:8080/manager/customers but it redirects to http://localhost:8080/customer/1/manager/customers
Note: the 1 is the customer id that I choose to add orders to
Am I doing something wrong??
#PostMapping(value = "/customer/{id}/orders")
public String projectAddOrders(#PathVariable("id") Long customerId, #RequestParam Long orderId, Model model) {
Order order = orderService.findOrderById(orderId);
Customer customer = customerService.findCustomerById(customerId);
if (customer != null) {
if (!customer .hasOrder(order)) {
customer .getOrders().add(order);
}
customerService.saveCustomer(customer );
model.addAttribute("customer", customerService.findCustomerById(customer Id));
model.addAttribute("orders", orderService.getAllOrders());
return "redirect:manager/customers";
}
return "redirect:manager/customers";
}
This is the HTML from:
<form th:action="#{/customer/{id}/orders(id=${customer.id})}" method="post">
<div class="row">
<div class="col-25">
Customer name: <b th:text="${customer.name}" /><br/>
</div>
</div>
<div class="row">
Customer orders:
<b><span th:each="order, iterStat : ${customer.orders}">
<span th:text="${order.name}"/><th:block th:if="${!iterStat.last}">,</th:block>
</span></b>
</div>
</div>
<br/>
<div class="row">
<div class="col-25">
<label for="user">Add Order</label>
</div>
<div class="col-75">
<select name="orderId">
<option th:each="order: ${orders}"
th:value="${order.id}"
th:text="${order.name}">
</option>
</select>
</div>
</div>
<div class="row">
<input type="submit" value="Add Order">
</div>
</form>
Try turning
return "redirect:manager/customers";
into
return "redirect:/manager/customers";
Mind the slash between 'redirect:' and 'manager'.
Does it work?
I fixed it by adding
registry.addViewController("**/manager/customers").setViewName("redirect:/manager/customers");
in my ApplicationWebMvcConfigurerAdapter implements WebMvcConfigurer class

Pass pre populated values to SQL Server database table (using Blazor)

I'm trying to make a booking function, where there are a set of buttons to click depending on for how long you want to book a room; 15 min, 30 min, 60 min.
I need the function to send a set of data items (like AppointmentStart, AppointmentEnd, RoomId etc.) to the data table upon a button click. I've tried to figure hidden fields out but getting nowhere.
The code for one of the buttons (which isn't working because I can't choose what to populate the fields with as I can't have both the #bind and a value="x"):
#if (#schedule.AppointmentDateStart >= ChooseTimeSlot.AddMinutes(15))
{
<div class="col">
<EditForm class="" Model="#schedule" OnValidSubmit="#ValidSubmit">
<button class="btn btn-primary form-control">15 min</button>
<input type="hidden" #bind="#schedule.Room.Id" class="form-control" />
<input type="hidden" #bind="#schedule.AppointmentHeading" class="form-control" />
<input type="hidden" #bind="#schedule.AppointmentDateStart" class="form-control" />
<input type="hidden" #bind="#schedule.AppointmentDateEnd" class="form-control" />
<input type="hidden" #bind="#schedule.BookerId" class="form-control" />
</EditForm>
</div>
}
#onclick=#( () => AppointmentChosen(15) )
from #MistMagoo got me back on track, so this is the solution:
<div class="col"><button class="btn btn-primary form-control" #onclick=#(() => TimeSlot(15, TRoomId))>15 min</button></div>
#code{
[Parameter] public int TRoomId { get; set; }
newSchedule = new Schedule();
{
var SlotAdd = RoundUp(DateTime.Now, TimeSpan.FromMinutes(NextTimeSlot));
newSchedule.RoomId = roomId;
newSchedule.AppointmentHeading = "Snabb";
newSchedule.AppointmentDateStart = DateTime.Now;
newSchedule.AppointmentDateEnd = SlotAdd;
newSchedule.BookerId = 1007;
newSchedule.IsConfirmed = true;
}
}

How to pass data from using POST/form leaf template?

I have a couple of major gaps in my understanding of vapor/leaf/html. I am working from the "todo" example that is created using the beta branch of vapor.
First, I made my own fluent model (no problems that I know of):
import FluentSQLite
import Vapor
final class affordatmodel: SQLiteModel {
var id: Int?
var propertyCost: String
var targetEquity: String
var interestRate: String
var amortization: String
var sponsor1: String
var sponsor2: String
var rent: String
var rentInflation: String
var propertyTaxes: String
var propertyTaxesInflation: String
var strataFees: String
var strataFeesInflation: String
init(propertyCost: String, targetEquity: String, interestRate: String, amortization: String, sponsor1: String, sponsor2: String, rent: String, rentInflation: String, propertyTaxes: String, propertyTaxesInflation: String, strataFees: String, strataFeesInflation: String) {
self.propertyCost = propertyCost
self.targetEquity = targetEquity
self.interestRate = interestRate
self.amortization = amortization
self.sponsor1 = sponsor1
self.sponsor2 = sponsor2
self.rent = rent
self.rentInflation = rentInflation
self.propertyTaxes = propertyTaxes
self.propertyTaxesInflation = propertyTaxesInflation
self.strataFees = strataFees
self.strataFeesInflation = strataFeesInflation
}
}
/// Allows to be used as a dynamic migration.
extension affordatmodel: Migration { }
/// Allows to be encoded to and decoded from HTTP messages.
extension affordatmodel: Content { }
/// Allows to be used as a dynamic parameter in route definitions.
extension affordatmodel: Parameter { }
Then I make an instance and send it to a leaf template:
let defaultData = affordatmodel(propertyCost: "700000", targetEquity: "300000", interestRate: "1", amortization: "20", sponsor1: "500000", sponsor2: "200000", rent: "1200", rentInflation: "1", propertyTaxes: "8000", propertyTaxesInflation: "1", strataFees: "0", strataFeesInflation: "0")
return leaf.render("welcome", ["affordat": defaultData])
And my Leaf template successfully populates the html with the default data (body shown here):
<body class="container">
<h1>Payment and Principal Calculations</h1>
<form action="/affordat" method="POST">
<div class="form-group">
<label for="propertyCost">Property Cost</label>
<input type="number" class="form-control" name="propertyCost" placeholder="#(affordat.propertyCost)">
</div>
<div class="form-group">
<label for="targetEquity">Target Equity</label>
<input type="number" class="form-control" name="targetEquity" placeholder="#(affordat.targetEquity)">
</div>
<div class="form-group">
<label for="interestRate">Interest Rate</label>
<input type="number" class="form-control" name="interestRate" placeholder="#(affordat.interestRate)">
</div>
<div class="form-group">
<label for="amortization">Amortization (years)</label>
<input type="number" class="form-control" name="amortization" placeholder="#(affordat.amortization)">
</div>
<div class="form-group">
<label for="sponsor1">Sponsor 1 Funds</label>
<input type="number" class="form-control" name="sponsor1" placeholder="#(affordat.sponsor1)">
</div>
<div class="form-group">
<label for="sponsor2">Sponsor 2 Funds</label>
<input type="number" class="form-control" name="sponsor2" placeholder="#(affordat.sponsor2)">
</div>
<div class="form-group">
<label for="rent">Rent</label>
<input type="number" class="form-control" name="rent" placeholder="#(affordat.rent)">
</div>
<div class="form-group">
<label for="rentInflation">Rent Inflation (will be used exactly)</label>
<input type="number" class="form-control" name="rentInflation" placeholder="#(affordat.rentInflation)">
</div>
<div class="form-group">
<label for="propertyTaxes">Property Taxes (first year est.)</label>
<input type="number" class="form-control" name="propertyTaxes" placeholder="#(affordat.propertyTaxes)">
</div>
<div class="form-group">
<label for="propertyTaxesInflation">Property Taxes Inflation (est.)</label>
<input type="number" class="form-control" name="propertyTaxesInflation" placeholder="#(affordat.propertyTaxesInflation)">
</div>
<div class="form-group">
<label for="strataFees">Strata Fees (first year est.)</label>
<input type="number" class="form-control" name="strataFees" placeholder="#(affordat.strataFees)">
</div>
<div class="form-group">
<label for="strataFeesInflation">Strata Fees Inflation (est.)</label>
<input type="number" class="form-control" name="strataFeesInflation" placeholder="#(affordat.strataFeesInflation)">
</div>
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<button type="submit" class="btn btn-primary">Refresh Calculations</button>
</form>
</body>
Great, so I know how to get fluent data to HTML. My problem is I don't know how to get it back. When the "Post" occurs, the data does not seem to get passed to the controller. My route is:
router.post("affordat", use: affordatController.create)
And the relevant part of my controller looks like this:
import Vapor
final class AffordatController {
func create(_ req: Request) throws -> Future<affordatmodel> {
return try req.content.decode(affordatmodel.self).flatMap(to: affordatmodel.self) { affordatmodel1 in
return affordatmodel1.save(on: req)
}
}
}
Which shows me one of my models, with an ID #, but no data. And I kind of understand why because I didn't really seem to send the post data to the controller. How I am supposed to send the POST data to the controller? Is the problem in my leaf template, my route, or my controller?
It looks like it should work. You can inspect the data being sent to your server in the network inspector in your browser. Make sure you preserve logs and you'll be able to see the POST request and the data sent to the server.
If you breakpoint at each point in the request you can see what the data is.
As an aside, it looks like you're submitting an empty form, so it's just filling everything in as blank strings. Do you mean to use value instead of placeholder in the form inputs? Value will pre-populate the data for the user, placeholder will show the value to the user as a suggestion but won't send the data in the form submission.

Facing an issue to send IP to input class which is inside <div>

I tried these ... none of them worked, any hints pls ...
this.title = 'Diagnostic Tools';
it('should have a title', function() {
browser.driver.get('https://URL');
browser.ignoreSynchronization = true;
browser.driver.findElement(by.id('username')).sendKeys('user');
browser.driver.findElement(by.id('password')).sendKeys('pass123');
browser.driver.findElement(by.name('login')).click();
browser.waitForAngular();
expect(browser.getTitle()).toContain('Diagnostic Tools');
element(by.linkText("TOOLS")).click();
element(by.name('server_ip')).sendKeys('1.1.1.1');
});
});
Tried 3 ways after clicking "TOOLS". Adding sleep btw click & send also didn't help.
element(by.name('server_ip')).sendKeys('1.1.1.1');
element(by.cssContainingText('input[name="server_ip"]')).sendKeys('1.1.1.1');
element(by.css('server_ip')).sendKeys('1.1.1.1');
Input class:
<i><div class="form-group required ng-scope" ng-repeat="(param_key, param_value) in selectedTool.params">
<label class="col-sm-2 control-label ng-binding">IP (s)</label>
<div class="col-sm-4">
<input style="" required="required" pattern="[ ]*((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})( (25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3})*[ ]*"
class="form-control ng-valid-pattern ng-valid-maxlength ng-dirty ng-valid-parse ng-valid ng-valid-required ng-touched"
name="server_ip" ng-model="toolInput[param_key]" ng-required="true" ng-attr-pattern="{{param_value.pattern}}" ng-attr-type="{{param_value.type}}" ng-attr-min="{{param_value.min}}" ng-attr-max="{{param_value.max}}" ng-attr-maxlength="{{param_value.maxlength}}">
</div>
<div class="col-sm-6">
<span class="help-block ng-binding">Can be multiple space separated ips.</span>
</div>
You need to explicitly wait for the element to be visible prior to sending keys:
var EC = protractor.ExpectedConditions;
var serverIP = element(by.name("server_ip"));
browser.wait(EC.visibilityOf(serverIP), 5000);
serverIP.sendKeys("1.1.1.1");

Meteor - Data saving issue

I have this template:
<Template name="nuevoEjercicio">
<div class="container-fluid">
<div class="form-group">
<input type="text" class="form-control input-lg" name="ejercicio" placeholder="Ejercicio?"/>
<input type="number" class="form-control" name="repeticiones" placeholder="Repeticiones?" />
<input type="number" class="form-control" name="peso" placeholder="Peso?" />
<button type="submit" class="btn btn-success" >
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</Template>
that I use to capture and save to the database.
Then on my .js file I am trying to get the data and save it:
Template.nuevoEjercicio.events({
'click .btn btn-success': function (event) {
var ejercicio = event.target.ejercicio.value;
var repeticiones = event.target.repeticiones.value;
var peso = event.target.peso.value;
ListaRutina.insert({
rutina:"1",
ejercicio:ejercicio,
repeticiones:repeticiones,
peso:peso,
});
// Clear form
event.target.ejercicio.value = "";
event.target.repeticiones.value = "";
event.target.peso.value = "";
// Prevent default form submit
return false;
}
});
}
as I understand, when I click on any object that has the btn btn-success style....but is not the case. For some obscure reason -for me- is not working.
Can you check it and give me some advice?
Thanks!
First of all, there's an error in you selector. It's 'click .btn.btn-success', not 'click .btn btn-success'.
Also you can't do that event.target.ejercicio.value thing. event.target is the element that was clicked. You'll have to do something like this:
'click .btn.btn-success': function (event, template) {
var ejercicio = template.$('[name=ejercicio]').val()
...
OK
What after wasting hours and hours the solution is:
1- on the html file give your input an id:
<input type="number" class="form-control" **id="peso"** placeholder="Peso?" />
<button type="submit" class="btn .btn-success" id="**guardar**" />
so now you want to save data on the input when the button is clicked:
2- You link the button with the funcion via the id
Template.TEMPLATENAMEONHTMLFILE.events({
'click **#guardar**': function (event, template) {
var ejercicio = template.$("**#peso**").val();
and get the value linking using the input id.