Preventing resubmission of form data Laravel 5.5 - laravel

I am working on Laravel 5.5 framework.
I have a form home page like this:
<form action = "/result" method = "post">
<input type = "hidden" name = "_token" value = "<?php echo csrf_token() ?>">
<table>
<tr>
<td>Name or Nickname</td>
<td><input type = "text" name = "name_nickname" autofocus /></td>
</tr>
<tr>
<input type = "submit" value = "LuckyNumber" />
</td>
</tr>
</table>
The controller looks like this:
class SixGetController extends Controller
{
public function luckyNumber(Request $request){
$nameNickname = $request->input('name_nickname');
$luckyNumber = rand (1,10);
DB::table('visitor')->insert(
['name_nickname' => $nameNickname, 'luckyNumber' => $luckyNumber]);
return view('result', ['nameNickname' => $nameNickname, 'luckyNumber' =>
$luckyNumber]);
}
The result page looks like this:
<p><?php echo $nameNickname; ?> </p>
<p>Your lucky number is <?=$result?> .</p>
If the user presses the reload F5 button the scrip will reroll the random number generator and resubmit the data with the rerolled number. I've read about the PGR pattern which i dont know how to use and something about manipulating history which i dont understand either. Can somebody point out what kind of code do i put somewhere to prevent the reroll and the resubmission. Thanks.

For laravel implementation, you can use Session Flash Data.
Sometimes you may wish to store items in the session only for the next
request. You may do so using the flash method. Data stored in the
session using this method will only be available during the subsequent
HTTP request, and then will be deleted. Flash data is primarily useful
for short-lived status messages:
In this case, when someone make a post request, you should store the useful data to session, and redirect them to other route. The other route can then retrieve the useful data to display to the view, and user no longer resubmit the form when refresh the page.
public function luckyNumber(Request $request) {
...
$request->session()->flash('nameNickname', $nameNickname);
$request->session()->flash('luckyNumber', $luckyNumber);
return redirect()->action('SixGetController#resultView');
}
public function resultView(Request $request) {
$nameNickname = $request->session()->get('nameNickname');
$luckyNumber = $request->session()->get('luckyNumber');
return view('result', ['nameNickname' => $nameNickname, 'luckyNumber' => $luckyNumber]);
}

Related

ASP.NET Core MVC - VIew is not updated correctly - Ajax?

I have an ASP.NET Core 6 MVC application.
On one page I have a table; I want to support drag'n'drop for its rows. Afterwards the User is able to click on "Submit" and make the changes permanent.
The changes are sent to the controller and persisted to the database, however when I redirect to the GET to show the page again, a part of it is wrong!
#model MyViewModel
<form>
#Html.HiddenFor(y=>y.Id)
<table id="orderTable" class="table">
<thead>
<tr>
<th>
Name
</th>
<th>
Order
</th>
</tr>
</thead>
<tbody>
#foreach (var data in Model.Data)
{
<tr id='#data.Id'>
<td>#data.Name</td>
<td>#data.Order</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<input type="submit" value="Save" id="SaveOrderButton" />
</div>
</form>
<script>
$(document).ready(function() {
$('#orderTable tbody').sortable();
$("#SaveOrderButton").click(function(e) {
e.preventDefault();
var newOrder = $('#orderTable tbody').sortable('toArray');
$.ajax({
url: '/Controller/Update',
type: 'POST',
data: { rowOrder: newOrder, id: #Html.Raw(Model.Id) },
success: function(response) {
console.log(response);
},
error: function(xhr,status, error){
console.log("An error occurred: " + xhr.responseText);
}
});
});
});
</script>
Backend:
[HttpGet]
public async Task<IActionResult> Order(int id)
{
var data= await context.Data
.AsNoTracking()
.Where(x => x.Id== id)
.ToListAsync();
data = data.OrderByDescending(y => y.Order.HasValue)
.ThenBy(y => y.Order)
.ToList();
var viewModel = new MyViewModel()
{
Data = data,
Id = id,
};
ModelState.Clear(); // found on SO, but does not change anything
return View(viewModel);
}
[HttpPost]
public async Task<IActionResult> Update(int[] rowOrder, int id)
{
var data= await context.Data
.Where(y => rowOrder.Contains(y.Id))
.ToListAsync();
for (int i = 0; i < rowOrder.Count(); i++)
{
data.First(y => y.Id == rowOrder[i]).Order = i;
}
try
{
context.UpdateRange(data);
await context.SaveChangesAsync();
}
catch (Exception ex)
{
logger.LogError("..........");
return Json(500, "Could not update new order.");
}
return RedirectToAction(nameof(Controller.Order), new { id= id});
}
Okay, so I go the the view with GET and everything is shown correctly, then I change something and click on "Save". Everything in the POST will be correctly done. The database is updated.
I then redirect to the GET method again, there everything is loaded correctly from the database and in the correct order.
Then I set a breakpoint in the View and there the stuff in the for is correct too.
However, when I look in the browser, the "Order" column is wrong. The table still shows the data how it looked like after I reordered it and before I clicked on "Save".
What is happening here? Is the sortable lib using a cache in the background that I have to invalidate?
I don't use a cache anywhere in my project, btw.
Also, when I go to the console after a POST, the whole website's HTML is in there.
When I now reload the page with the GET, everything is shown how it is supposed to be.
Has it something to do with Ajax? I have already removed the success and error events, which doesn't change anything.
Has it something to do with Ajax? I have already removed the success
and error events, which doesn't change anything.
Yes, the issue relates the Ajax method.
As we all known, when we use Ajax to update the part of view page, after calling the action method, it will return the response result to the success function, then in the success function, we get the updated data from the response, and then dynamic populate the table to update the page and achieve the part of page refresh behaviors.
So, in your scenario, you can try to use the following methods to display the updated data.
Method 1:
In the Update Action method, return the updated data as result, instead of redirect to another action result. Then, in the Ajax success function, get the data from response, then clear the table content first and re-populate it using the response data.
Method 2:
In the Ajax success function, use location.reload(); method to reload current page, or use window.location.href to refresh the current page.

Livewire - updated hook without render of complex data

I'm using Livewire for data table with a complex database query with pagination. In table are also checkboxes and after check/uncheck is quite annoying to wait for render method with fetching all necessary data witch are required only for first component load.
I know I can use defer flag for checkboxes but I need also do some action when is any checkbox checked/unchecked so I cannot use that flag. So my question is if I can use updated hook method for checkbox without loading data in render.
Here is my example code:
class LivewireComponent extends Component
{
public $arrayOfCheckboxes = [];
public function render(SomeService $service)
{
$data = $service->fetchComplexData->paginate();
return view('livewire.some-component', ['data' => $data]);
}
public function updatedArrayOfCheckboxes($value)
{
// if value is true/false then do some action
// do I really need to call render and fetch complex data again?
}
}
// livewire.some-component.blade.php
<div>
<table>
#foreach($data as $row)
<input type="checkbox" wire:model="arrayOfCheckboxes" value="{{ $row->someValue }}">
#endforeach
</table>
</div>

How can i solve my this issue in MVC grid Delete Controller

Controller:
public ActionResult Delete(int id)
{
Student _std = new Student();
var abc = _dbcon.StudentList.Where(c => c.Roll_ID.Equals(id)).SingleOrDefault();
_dbcon.StudentList.Remove(abc);
_dbcon.SaveChanges();
return View("Test");
}
This is my view and the error comes at foreach loop
View:
#foreach (StudentViewModel _EachStd in #Model.StudentList)
{
<tr>
<td> #_EachStd.Roll_ID</td>
<td> #_EachStd.Name</td>
<td> #_EachStd.Maths</td>
<td> #_EachStd.Urdu</td>
<td> #_EachStd.English</td>
<td>#_EachStd.ObtainNumber</td>
<td>#_EachStd.Percentage</td>
<td> #_EachStd.Grade</td>
<td>#Html.ActionLink("Edit", "Edit", "Home", new {id= #_EachStd.Roll_ID },null)</td>
<td>#Html.ActionLink("Delete", "Delete", "Home", new { id = #_EachStd.Roll_ID }, null)</td>
</tr>
}
</tbody>
</table>
I got Null Error exception, but after refresh i got the record delete. But why the error occur I dont get It.Whenever i run this code my Edit controller is working correctly but my Delete controller is not working correctly, and error is occur like there is "Null erroe exception"
error is occur like there is "Null erroe exception"
You mean a NullReferenceException? That would mean something is null that you're trying to use as though it has a value.
This is my view and the error comes at foreach loop
So then something on this line is null?:
#foreach (StudentViewModel _EachStd in #Model.StudentList)
The only thing you're trying to dereference on that line is Model. So it follows that Model is null. Are you passing a model to your view?
return View("Test");
No, you are not. You need to pass a model to your view in order to use that model within your view.
As an aside, returning a view from this delete operation probably isn't the way to go in the first place. Consider that the user would now be on the URL /Home/Delete and viewing it as a page. This would quickly get confusing for both the user and your code.
Instead of returning a view, especially one without a model, redirect the user to the action which builds the model and displays the view. Which in your code could be something as simple as:
return RedirectToAction("Test");

Redirect in ASP.Net MVC4

I'm using ASP.Net MVC4 Razor. I'm having a problem with redirection. I wanna redirect the user to the Home controller at the user login(if login is valid).
But my problem is it always come back to the login page even the redirect meythod also fired.
Here is my code..
public class LoginController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult LoginAccess()
{
return RedirectToAction("Index", "Home");
}
}
Login page..
<div class="body_wraper">
<div id="cloud" style="background:url('#Url.Content("~\\Content\\cloud.png")');">
<div id="login_form">
<div class="Three-Dee">Login here..</div>
<table>
<tbody>
<tr>
<td>#Html.Label("Username")</td>
<td></td>
<td>#Html.TextBox("txtUsername")</td>
</tr>
<tr>
<td>#Html.Label("Password")</td>
<td></td>
<td>#Html.Password("txtPassword")</td>
</tr>
<tr>
<td></td>
<td></td>
<td style="text-align:right;"><button class="k-button" id="login" onclick="Login()">Login</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
function Login() {
$.ajax({
url: '#Url.Content("~/Login/LoginAccess")',
type: 'POST'
});
}
Home Controller..
public ActionResult Index()
{
Session["UserName"] = "Administrator";
string menu = this.GetMenu();
ViewBag.ManueItems = menu;
return View("User");
}
After click on the login button it comes to LoginAccess in Login controller and then comes to Home controller Index method, but doesn't view the "user view".
But when i check with typing url >>(host__/Login/LoginAccess">http://__host__/Login/LoginAccess) Its working properly.
Please help me to slove this problem.
Thank you.. :)
You may misuse the Ajax function here
You should use #Html.ActionLink("Login", "LoginAccess", "Login") instead
Ajax is originally used to get something from server side other than affecting currently browsing page.
When you are doing Ajax calls, you cannot force redirect from controller. You can fix this by 2 ways:
Replace ajax call with regular get.
Return a json from the action and use redirect from javascript
try this instead
return redirect("/Home/Index")
You can try this
var result = new ControllerName().YourAction();

How to open cshtml file in new tab from controller's method?

I'm working on a Nopcommerce, and need to generate Invoice (custom made not as what they already provide, because it just doesn't solve our purpose). We need to generate Invoice
in new tab(using another cshtml file) using Controller's method also I'm passing model data on view.
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.ProbableDeliveryDate):
</td>
<td class="adminData">
#Html.EditorFor(model=>model.ProbableDeliveryDate)
</td>
</tr>
<tr>
<td>
#if(Model.CanGenrateInvoice)
{
<input type="submit" name="generateinvoice" value="#T("Admin.Orders.Fields.generateinvoice")" id="generateinvoice" class="adminButton" />
}
</td>
</tr>
I've to post data to get value of probableDeliveryDate to controller method and after that want to open view in new tab.
How can i do this?
If you are getting to the action from the first page via an Html.ActionLink you can do this:
Html.ActionLink("Open Invoice", "ActionName","ControllerName", new { id = Model.InvoiceID }, new { target = "_blank" });
Specifying target = "_blank" will open in the new tab
Update
Since you are posting the model to the controller (I was hoping RedirectToAction could help open a new window/tab but that doesn't look to be the case)
My spidy sense is tingling on the flow you have tho... This is just me but I would do something a little different.. such as
Post the model to the controller
Save the data that generates the invoice
Return the InvoiceID to the action
Add the InvoiceID to the model
Send the model back to the view
Inform the user that
the invoice was generated and show a link - like above - that allows the user to open the invoice OR
this provides the perfect clean solution to show model errors if there were any
Your view could have a piece of razor code that did that:
#{
if(Model.InvoiceID != null && Model.InvoiceID !=0) {
#Html.ActionLink("Open Invoice", "ActionName","ControllerName", new { id = Model.InvoiceID }, new { target = "_blank" });
}
}

Resources