How to pass an argument(id) from page view to page model - c#

let me explain a problem first.
I've got a page.
Page is basket representation with multiple records (items).
Every item has a delete button. What I want to achieve is to delete item from that basket (actually from database). But first I need to pass item id to page-model post method.
Right now that is what i got at Page view.(cshtml, dont really sure how to call it)
<form method="post">
<div class="form-group">
<input type="submit" class="btn btn-danger" value="Delete" asp-page-handler="Delete"/>
</div>
</form>
And here is a page model.
public IActionResult OnPostDelete(int itemId)
{
memberData.DeleteFromBasket(itemId);
return RedirectToPage("./Basket");
}
How can i pass item id to the method?

You need to add a route parameter to the button that matched the parameter name. For example:
<input type="submit" class="btn btn-danger" value="Delete"
asp-page-handler="Delete"
asp-route-itemId="#model.ItemId" />

Related

Routing from View to a Razor Page action Asp.Net Core 3

I have an UnderConstruction page which is being handled by MVC. The view has the following code to route a user, after entering their email address to the registration page which is part of the identity scaffolded razor area. The intent is to bring up the register page with their email already populated in the email input.
<!-- route to Register Form -->
<form class="form-inline push-10" method="get">
<div class="form-group">
<label class="sr-only text-white" asp-for="Email">Email Address</label>
<input class="form-control" type="email" asp-for="Email" placeholder="Your Email..">
</div>
<div class="form-group">
<button class="btn btn-default" type="submit" asp-area="Identity" asp-page="/Account/Register" asp-page-handler="WithEmail">
<i class="fa fa-plus"></i> Register
</button>
</div>
<div class="form-group">
<a class="btn btn-default" asp-controller="Home" asp-action="Index">
<i class="fa fa-home"></i> Home
</a>
</div>
and the pages view model
public class UnderConstructionViewModel
{
public string Email { get; set; }
}
Clicking the Register button after entering an email address produces this url
https://localhost:44367/Identity/Account/Register?Email=testemail#mydomain.com
This brings you to the register page with the email address NOT populated in the email input.
Here is the method in register.cshtml.cs (scaffolded razor area for identity)
public IActionResult OnGetWithEmail(string email)
{
return RedirectToPage("Register", new InputModel{ Email = email });
}
The problem is, the method never gets hit. The handler is following convention, and the model is following convention, so I am not sure why the method is not getting hit.
I also tried the asp- tag helpers in the form call, but that produces the same result.
Any help sorting this out would be appreciated.
Any query string values that are appended to the form's action attribute, or in this case the formaction attribute are wiped out by the routing system when the form is submitted. This appears to be by design: https://github.com/aspnet/Mvc/issues/8621
You can resolve this by adding "{handler?}" to the #page directive in the Register page. Then the handler name is appended to the URL as a segment rather than as a query string value.

Get table cell value and submit to a delete function

I have a table which displays data from my database. I want to provide a button which will delete data from a table based on the row selected. Specifically based on the value of a specific cell of that table.
I've tried wrapping a button inside a form element as an extra element inside of each row, but this doesn't seem to work for 2 reasons. 1, it triggers the OnGet() function in my controller and 2 it doesn't seem to bind the cell data value to my 'SourceTable' property.
The following is my front-end table:
<table class="table">
<thead>
<tr>
<td>OrderIdentifier</td>
<td>Step Number</td>
<td>CreateDate</td>
<td>Step Status</td>
<td>Source Table</td>
</tr>
</thead>
#foreach (var order in Model.order.Steps)
{
<tr>
<td>#order.OrderIdenfitier</td>
<td>#order.Name</td>
<td>#order.CreateDate</td>
<td>#order.StepStatus</td>
<td>#order.SourceTable</td>
<td>
<a class="btn btn-dark"
asp-page="./OrderDetail"
asp-route-orderId="#order.OrderIdenfitier">
<i class="glyphicon glyphicon-zoom-in"></i>
Details
</a>
</td>
<td>
<form method="delete">
<input type="hidden" class="form-control" asp-for="SourceTable" />
<button type="submit" class="btn btn-dark">
<i class="glyphicon glyphicon-zoom-in"></i>
Delete
</button>
</form>
</td>
</tr>
}
And on the backend, I'd like to be passing in the SourceTable cell value of whatever row the button is clicked on into this function:
public IActionResult OnDelete(string SourceTable)
{
//Take SourceTable parameter, pass to data access layer, and delete from database.
return Page();
}
I would like to have the value of the SourceTable cell passed to my OnDelete function, but this doesn't occur. Additionally, my 'OnGet()' function is triggered when I click my delete button, not the 'OnDelete()' function. The I form I embedded the button in has action="delete", so I would think that it would go to the OnDelete() function, but that doesn't seem to be the case.
HTTP DELETE method is currently not supported by <form> element. That's why you hit OnGet() in your Razor page. You are still able to use OnPost() for that purpose with binding form values (e.g. hidden inputs) to action method parameters.
The second issue is with your asp-for input tag helper. By default it evaluates its expression against PageModel. You can use # to override that behaviour, especially when you're in a foreach loop. Your form then could look like this:
<form method="post">
<input type="hidden" asp-for="#order.SourceTable"/>
<input type="submit" vaue="Delete"/>
</form>
and action method:
public IActionResult OnPost(string SourceTable)
{
// delete record here
return RedirectToPage();
}
Maybe you don't like the idea to delete records in OnPost handler, which you would like to reserve for some other action.Then you can use named handler method like OnPostDelete(string SourceTable). All you have to do is to add attribute asp-page-handler="delete" to the <form> element:
<form asp-page-handler="delete" method="post">
<input type="hidden" asp-for="#order.SourceTable"/>
<input type="submit" value="Delete"/>
</form>
And maybe you don't like the idea of having a separate form for each row in the table. Then wrap the form around the table and use asp-route- prefix on each delete button to specify parameter binding:
<form method="post">
<table class="table">
<thead>
<!-- ... -->
</thead>
<tbody>
#foreach (var order in Model.order.Steps)
{
<tr>
<!-- ... -->
<td>
<input type="submit" value="delete" asp-page-handler="delete" asp-route-sourcetable="#order.SourceTable" />
</td>
</tr>
}
</tbody>
</table>
</form>
You can find more valuable information in artice Introduction to Razor Pages in ASP.NET Core.

Pass value from field to querystring

How do I set the value to the query string
<form asp-route="TalkMessageBoardSearch" asp-route-talk_query="[need value from "talk_query" field]" method="post" class="form" role="form">
<input type="hidden" />
<div class="input-group">
<input class="form-control" id="talk_query" name="talk_query" placeholder="Search Talk" />
<div class="input-group-btn">
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>
</div>
</div> </form>
When the button is clicked on POST, it is redirecting to "/message_board_search" but it doesn't have the querystring. I want it to show "/message_board_search?talk_query=query1" How do I get the value from the id="talk_query" field and put it in the querystring when the POST is clicked. Right now "asp-route-talk_query" can be hardcoded like asp-route-talk_query="hardcoded"
I used the "asp-route" because the view is in /talk/message_board_search" but I want it to be in the root path "/message_board_search" so that is why I used the route "TalkMessageBoardSearch."
You are trying to use the < form > method attribute with POST. The "method" you specify changes the behavior:
POST method does not affect the query string
GET method affects the query string.
HTTP Methods: GET vs. POST
HTML < form > method Attribute
If you need to use POST but also modify the query string to contain dynamic data, you must use Javascript. You cannot use the < form > method by itself in that case. (see Vinay's comment, he has a link for this!)

FormCollection missing submit button values [duplicate]

This question already has answers here:
How do you handle multiple submit buttons in ASP.NET MVC Framework?
(35 answers)
Closed 9 years ago.
This code was working at one point. I'm not sure what broke it, but basically on postback I'm looking for the existence of a submit button key in the FormsCollection. Depending on the existence, I perform different operations. The custom attribute to handle this is getting hit. When I step through it and look at the FormsCollection, I can see all key/values from the form except for the submit button which submitted the form.
Looking at the submission via Fiddler2, it doesn't even look like the submit button is being sent to the server with the rest of the values. If I put in a hidden field with the same name I am looking for (and hard coded value) I can successfully hit the "if exists" logic branch because the hidden field's value is sent to the server.
Here's my form:
#using (Html.BeginForm("Respond", "AccountInvitations", new {id = Model.Invitation.InvitationCode, ReturnUrl = Request.QueryString["ReturnUrl"] ?? string.Empty}, FormMethod.Post, new {#class = "invitation-details-form"}))
{
<div class="modal-body">
<div class="status-message info">
<i></i>
You have been invited to join <strong>#Model.Invitation.AccountName</strong>.
Create your profile below to join this account.
</div>
#Html.AntiForgeryToken()
#Html.ServerValidationSummary()
#Html.EditorFor(model => model.InvitationResponse, "InvitationResponseDto", "")
</div>
<div class="modal-footer">
<div class="button-container clearfix">
<input type="submit" name="accept" value="Accept Invitation" class="btn btn-secondary" />
<input type="submit" name="decline" value="Decline Invitation" class="btn btn-link cancel" />
</div>
</div>
}
Neither "accept" nor "decline" shows up in the FormsCollection when I press on either (the form is submitted and all fields from the editor template show, but not the submit inputs).
I do not want to handle this with javascript setting a hidden field value.
Wow, it's been a long couple nights coding. This post led me to the answer. A couple weeks back a script was added to prevent double clicking on some form entries. The form disabled the inputs immediately upon form submission. A simple setTimeout() to delay the disabling did the trick.
OR you can using
<div class="modal-footer">
<div class="button-container clearfix">
#using (Html.BeginForm("Your_ActionResult", "Your_controller"}, FormMethod.Get/Post))
{
#Html.AntiForgeryToken()
<input type="submit" name="accept" value="Accept Invitation" class="btn btn-secondary" />
}
#using (Html.BeginForm("Your_ActionResult", "Your_controller"}, FormMethod.Get/Post))
{
#Html.AntiForgeryToken()
<input type="submit" name="decline" value="Decline Invitation" class="btn btn-link cancel" />
}
</div>
</div>
you must specify the submit button that call the ActionResul method in your Controller is

Can't get input type="text" value in action on form submit?

In a Razor view I have input type="text", a hidden field and a button. I can access hidden field from Form collection but its weird I cant access input type="text" value inside my action. I am not sure if my understanding is correct or not but I was thinking as all fields inside form should be available inside action.
Below is my code please:
#using (Html.BeginForm())
{
<div style="margin-top: 40px;">
<input id="txtDateFrom" class="span2" size="16" value="#Model.StartDate.ToString("dd/MM/yyyy") " readonly="readonly" type="text">
#Html.Hidden("currencyCode", (object)ViewBag.currencyCode)
</div>
<button onclick="#Url.Action("ExchangeRateDetails", "ExchangeRate")" class="btn btn-lg span2 ARML50px">
}
I highly appreciate your time, guidance and help.
The reason your hidden input works is that you render this with help from the Html helper #Html.Hidden. This helper render the input field with the name attribute.
Your <input type="text"> is missing the name attribute. So try writing like this:
<input id="txtDateFrom" name="txtDateFrom" class="span2" size="16" value="#Model.StartDate.ToString("dd/MM/yyyy") " readonly="readonly" type="text" />
The name="txtDateFrom" will make the value appear in your FormCollection.
Try this way
You don't need onclick="#Url.Action("ExchangeRateDetails", "ExchangeRate")" to the button
Change your button for below way
<button type="submit" class="btn btn-lg span2 ARML50px">
And Now your controller can get the input text
[HttpPost]
Public ActionResult ExchangeRateDetails(YourmodelClass xxx)
{
string dates=Model.StartDate;
}
This website have lot and lot of answers for how to send a model values from view to controllers by see the Related discussion on this page right corner .

Categories