MVC5 form not routing correctly - c#

I have this snippet of code;
<form action="#Url.Action("Index", "MyController")" method="post" >
<button class="btn btn-large btn-primary" id="btnNext">Click Here</button>
</form>
But when the button is clicked it redirects to http://<domain>:2024/MyController and I get a http error
405.0 Directory listing is not allowed.
If I manually change the url to http://<domain>:2024/MyController/Index I get my page.
When I change the form code to the below it works.
<form action="#Url.Action("MyAction", "MyController")" method="post" >
...
index method declaration is;
public async Task<ActionResult> Index()
{
...
}
So it's an inconvenience, and this is the only place it happens. I can work round it by not using the Index action, but how can I track this down and fix it?

In addition to checking your routing rules, you can use the Html.BeginForm helper method to create forms properly.
#using(Html.BeginForm("Action", "ControllerName"), HttpMethod.Post)
{
//form controls
}

Related

Razor : asp-page-handler doesn't trigger handler and throw 400 Error

I need to remove an item in Cart with razor page. For this i used a form with asp-page-handler.
Cart.cshtml :
<td class="text-center">
<form asp-page-handler="Remove" method="post">
<input type="hidden" name="id" value="#line.Product.Id" />
<input type="hidden" name="returnUrl" value="#Model.ReturnUrl" />
<button type="submit" class="btn btn-sm btn-danger">
Remove
</button>
</form>
</td>
And my Cart.html.cs has a OnPostRemove method like this:
public IActionResult OnPostRemove(int id, string returnUrl)
{
Cart.RemoveLine(Cart.Lines.First(cl =>
cl.Product.Id == id).Product);
return RedirectToPage(new { returnUrl = returnUrl });
}
When i cliked remove button i got a 400 Error and my OnPostRemove method doesn't trigger.
Update
I included tag helper in my _ViewImports.cshtml and issue resolved.
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Put the page handler inside the submit button tags.
<form method="post">
...
<button type="submit" asp-page-handler="Remove">
Remove
</button>
</form>
The code snippet that you shared seems ok, which work well with testing data on my side.
When i cliked remove button i got a 400 Error and my OnPostRemove method doesn't trigger.
To troubleshoot the issue, please check the actual request with the posted data in F12 developer tool Network tab.
And please note that if the antiforgery token validation is enabled, but the request does not include a valid antiforgery token or something wrong with the antiforgery cookies, which would also cause 400 Bad Request error.
For testing purpose, you can try to skip antiforgery token validation by applying IgnoreAntiforgeryTokenAttribute on page model class, then check if the request can be handled as expected.
[IgnoreAntiforgeryToken]
public class CartModel : PageModel
{

C# Razor Submitted form on Success Refresh Errors

I have a contact form that is in C# - Razor and built into the Umbraco Scaffold CMS.
Everything almost works .. except after a successful submission - if I refresh the page the web declares I must resubmit the information - clicking ok then causes the page to attempt a refresh but instead of looking for the page as a page it looks for the action method that was called.
How do I get it to refresh the proper location
<button class="btn btn-primary"
id="btnSubmit"
type="submit"
value="submit"
data-action='CreateMessage'
style="height: 75px;">
<h2>Submit</h2>
</button>
function onSubmit(token) {
document.getElementById("form-outer").submit();
}
EDIT
if (ViewBag.Contact != null)
{
[mxmissile THIS SHOULD BE A REDIRECT? instead of simple content ..]
var viewModel = (MyWeb.ContactModel)ViewBag.Contact;
<div id="form-outer" class="contact-confirmation">
<div>
<h2>
<p>Thank you for your message.</p>
</h2>
<p>We will be in touch soon.</p>
</div>
</div>
}
else
{
Html.RenderPartial("/Views/Partials/ContactView.cshtml");
}

c# razor, how to use html button to run a method?

I want to use the button to run a c# method how to do that? Now if i make a button with
<button type="button" onclick="#class.method()" >execute method</button>
it just executes that method on page load but doesnt do that on button click.
This can be done using standard form or ajax form.
Option 1 - Standard form:
add asp-page-handler attribute to the button and specify the relevant method name, and on the back end create the relevant method with OnPost prefix.
<form method="post">
<button type="button" asp-page-handler="RunMethod">execute method</button>
</form>
Backend method:
public IActionResult OnPostRunMethod()
{
//do whatever...
}
Option 2 - ajax form:
Use data-ajax-url="?handler=RunMethod" directly inside the form attributes or you can use a script to assign the relevant method handler to the form, with this approach you can use multiple buttons inside the same ajax form:
<form method="post" id="myForm"
data-ajax="true"
data-ajax-method="post"
data-ajax-loading="#loading"
data-ajax-failure="failed"
data-ajax-update="#updateMsg">
<button type="submit" id="RunMethod">execute method</button>
</form>
#section Scripts{
<partial name="_ValidationScriptsPartial" />
<script src="~/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.min.js"></script>
<script>
failed = function (xhr) {
alert('Status: {xhr.status}, Status text: {xhr.statusText}');
}
$("#RunMethod").on("click", function () {
$("#myForm").attr("data-ajax-url", "?handler=RunMethod");
});
});
</script>
}
Backend method:
public IActionResult OnPostRunMethod()
{
//do whatever...
}
see samples here
You need to create a handler method in the Razor page and use asp-page-handler attribute. See here for more information.

Form POST not doing anything

I have a webapplication made in ASP.NET Core (latest version) which needs to use a pop-up form where 1 value has to be filled in and then send it back to the controller to later use that value.
So the process is like this: Button > Click on button > Pop-up form pops up (Image: pop-up form which is a partial view) > Fill in value > Submit > Send result back to controller.
But whenever I press the submit button it sends me to a 400 error not found page. What could go wrong?
Here is the partial view pop-up form code:
#model IEnumerable<ApplicationName.Models.Moederblad>
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#addTagHelper *, AuthoringTagHelpers
#Html.AntiForgeryToken()
<div id="element_to_pop_up">
<a class="b-close">x</a>
//Actionresult > Controller
#using (Html.BeginForm("Incassodatum", "Moederblads", FormMethod.Post))
{
<br />
<div class="row">
<div class="col-md-6">
<label for="Incassodatum">Incassodatum</label>
<input class="form-control" placeholder="Bijvoorbeeld: 19-02-2020" type="text" data-val="true" data-val-regex="Dat is geen geldige datum" data-val-regex-pattern="^(0[1-9]|[12][0-9]|3[01])[/](0[1-9]|1[012])[/](19|20)[0-9]{2}$, " id="Incassodatum" name="Incassodatum">
</div>
</div>
<div class="row">
</div>
<br>
<input name="__RequestVerificationToken" type="submit" class="btn btn-primary submit" value="Toevoegen" id="submit">
}
</div>
Here is the corresponding controller:
[HttpGet]
public ActionResult Incassodatum()
{
return View();
}
//Automatisch de datum van vandaag in het Incassodatum veld zetten nadat er op een knop is gedrukt
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Incassodatum(string Incassodatum)
{
string date= "";
if (ModelState.IsValid)
{
date = Incassodatum;
}
else
{
date = "Something went wrong.";
}
TempData["Incassodatum"] = $"{Incassodatum}";
return RedirectToAction("Index");
}
Then later I can use the tempdata to read out the value but its not working at all so that is actually useless for now.
I tried adding the [Route("Moederblads/Incassodatum")] property above the post.
I tried it in a normal view (So not a partial view) and there I could see the value with F12.
Tried changing object names as I thought it might conflict with other names.
Don't know what to do now. Any of you have a guess?
But whenever I press the submit button it sends me to a 400 error not found page.
A 400 error is a Bad Request. A 404 is a Not Found. As such, I'm not sure which you're actually getting here. However, based on the fact that you have an input with __RequestVerificationToken as the name, and you're using it wrong at that, I'm leaning towards the 400.
Since you're trying to use this input as a button, you've set a value on it to apply that text to the button. However, that's going to actually post that value for __RequestVerificationToken, and it's not a valid token. As such, you're going to always get a 400 Bad Request because of the failed request verification.
The request verification token should be on a hidden input, so the simplest solution is to remove the name from that button and add a hidden input specifically for the request verification token: #Html.AntiForgeryToken().
Even better would be to use the built-in FormTagHelper instead, which automatically takes care handling antiforgery tokens:
<form asp-action="Incassodatum" asp-controller"Moederblads" method="post">
...
</form>
Finally, while it doesn't technically effect anything, using input for buttons is an anti-pattern that should be avoided. Use <button type="submit"> instead.
Was something very easy in the end: I just had to delete the: [HttpPost] tag above the method and the [HttpGet] method as it did nothing in the end. After that it hit my break point and could verify that the value is coming through fine :)

How to call a method from controller when a button from form is pressed?

The main problem is that a method from controller is not called when i press a button.
I have this in my Index view for MyController :
#using (Html.BeginForm())
{
#* .... *#
<form action="DoSomethingAction" method="post">
<input type="text" id="IdString" name="IdString" placeholder="Enter id"/>
<input id="Submit1" name="Submit1" type="submit" value="DoSomething1" />
<input id="Submit2" name="Submit2" type="submit" value="DoSomething2" />
</form>
#* ..... *#
}
In MyController I have DoSomethingAction method. I want to call this method and be able to see IdString when I press a button: DoSomething1 or DoSomething2. This is DoSomethingAction method from controller:
public ActionResult DoSomethingAction()
{
string id= Request.Form["IdString"];
//string button=...
// ...
}
When I put a breakpoint for DoSomethingAction method, I observed that it's never called.
I tried to put [Httppost] attribute for this method, but it didn't solve my problem.
What am I doing wrong?
After that, how can I see in DoSomethingAction method which button was pressed?
a HTML form can not nest a HTML form. Please read https://www.w3.org/TR/html5/forms.html#the-form-element
If you need multiple form you can define them as siblings.
Either use html.BeginForm or type="Submit". Next thing to keep in mind, html.BeginForm is a post method, so if u want to use it, give an attribute over Action and if u don't state what view action should return, he will assume that view is of the same name as action, in ur case DoSomethingAction, that's why u get server error. Either make that view or state in return View() which view u want to return (Index or some other).

Categories

Resources