action not found on alternate builds - c#

I have a form like the following.
<form method="post" action="paste">
The page rendering the form and the action the form points to are both part of the same controller.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Paste()
{ // some field operations here.}
}
Now, in first build the form submission causes a 404 with a message The resource cannot be found. I edit the cshtml file and replace paste in the form tag with itself, build again and deploy and the form works fine. Why is it happening so and how can I correct the behaviour ?

It should work by adding the [HttpPost] attribute to your action.
[HttpPost]
public ActionResult Paste()
{ // some field operations here.}

Related

Returning a method for a form

I have a form which after clicking Submit should call the AddProduct method
View
#using (Html.BeginForm("AddProduct", "Home", FormMethod.Post))
The problem is the controller. Has a specified Route.
In this situation, when I click Submit, AddProduct is not called, but Index
HomeController
[Route("{name?}/{adminCode?}")]
public IActionResult Index(string name, string adminCode)
[HttpPost]
public ActionResult AddProduct(string productName)
How to call the AddProduct method correctly?
Because of the optional route parameters and the lack of a HTTP Verb on the Index action you most are most likely encountering a route conflict.
First option would be to use the appropriate route attribute on the action.
[Route("[controller]")]
public HomeController {
[HttpGet("{name?}/{adminCode?}")]
public IActionResult Index(string name, string adminCode) {
//...
}
[HttpPost]
public ActionResult AddProduct(string productName) {
//...
}
}
That way when the post is made it will only consider actions that can handle POST requests.
Another option I would suggest is moving AddProduct to a separate controller (like ProductController).
HomeController
[Route("[controller]")]
public HomeController {
[HttpGet("{name?}/{adminCode?}")]
public IActionResult Index(string name, string adminCode) {
//...
}
}
ProductController
[Route("[controller]")]
ProductController {
[HttpPost]
public ActionResult AddProduct(string productName) {
//...
}
}
and updating the view accordingly
#using (Html.BeginForm("AddProduct", "Product", FormMethod.Post))
Apart from that, there is not enough details about what you are actually trying to achieve here, so I would also suggest adding more details about the main goals so that a more target answer can be provided.
Because of a wrong route config, controller can't see you that you have AddProduct action, and uses default Index action with AddProduct
as a name parameter. So try to add a route to AddProduct too
[Route("~/Home/AddProduct")]
public ActionResult AddProduct(string productName)
if the problem continues with another actions. Pls post your controller header and config routes code. Probably it needs to be fixed.

custom form with method="POST" isn't getting displayed in task module ms teams

I am unable to to get a custom form to display in Task Module. It's a form with few input elements and method="POST" attribute. When I remove "method" attribute the task module displays custom form correctly.
I just want to post input field values to controller.
PS: Everything works when I run those forms in browser. I have also added valid domains in teams and task module renders perfectly without method="POST" attribute in form tag.
This is my .cshtml page with form method.
Here is Controller class
public class HomeController : Controller
{
public SuspectRegistration registration;
public HomeController()
{
registration = new SuspectRegistration();
}
// GET: /<controller>/
public IActionResult Index()
{
return View();
}
public IActionResult CustomForm()
{
return View();
}
public IActionResult PRFPDetailsForm()
{
return View();
}
// This is the method where I need to get values, it works in browser without any issues.
[HttpPost]
public IActionResult PRFPDetailsForm(SuspectRegistration formData)
{
HttpContext.Session.SetString("formdata", JsonConvert.SerializeObject(formData));
return View("PRFPDetailsForm");
}
public IActionResult PRFPRegistrationConfirmation()
{
var value = HttpContext.Session.GetString("formdata");
var suspectRegistration = JsonConvert.DeserializeObject<SuspectRegistration>(value);
ViewBag.SuspectRegistration = suspectRegistration;
return View();
}
}
I missed to respond here. Your back end code has no issues. On frontend, you need to submit your frontend input values to "microsoftTeams.tasks.submitTask(youJSObject)" in js object and same thing you can receive in turnContext of the "OnTeamsTaskModulesSubmitAsync" method.

Razor form not passing back to controller method

I am trying to pass a textbox's text back to a method in my controller, but the data is not being passed in the parameter
I am genuinely confused, i'm following another example but i'm getting a different result, ie - my method behaving as if no parameter is passed
Code
public ActionResult Index(string searchString)
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
var listOfAnimals = db.Animals.ToList();
if (!String.IsNullOrEmpty(searchString))
{
listOfAnimals = listOfAnimals.Where(a => a.AnimalName.ToLower().Contains(searchString.ToLower())).ToList();
}
return View(listOfAnimals);
}
and here is my razor form from my view page
#using(Html.BeginForm("Index", "Home"))
{
#Html.TextBox("searchString")
<input type="submit" id="Index" value="Index" />
}
Can anybody spot why this isn't working?
If more code is needed, please let me know but i think the issue is isolated to here
You code is correct.
Since you didn't add [HttpGet] or [HttpPost] before index method.
This method was called twice.
The first call ran when producing the page with form via url http://server/Home/Index. This call was an http get and searchString mapped from URL was null, which is correct.
The second call ran when you clicked submit button. Correct value would be mapped by MVC correctly.
You need to have 2 Index actions (two methods), one without decorations (GET verb) and another one decorated with HttpPost (POST verb). Basically, when you go to the index page, the GET action is executed. When you submit the form, a POST request is executed and the Index decorated with HttpPost is executed.
// GET
public ActionResult Index() { ... }
// POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
Francisco Goldenstein wrote the recommended way. It means you can have two Index() actions:
// for GET
public ActionResult Index() { ... }
// for POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
However it is possible to have one Index() method for handling both (GET and POST) requests:
public ActionResult Index(string searchString = "")
{
if(!string.IsNullOrEmpty(searchString)
{ /* apply filter rule here */ }
}
You wrote, your code is not working. Do you mean, your action method is not requested after click on the button? Consider to allow empty value Index(string searchString = "")
If your action method is fired but variable is empty, check the name on the View() side. Textbox must not be disabled, of course.

How should I setup Registration controller action?

I am fairly new to MVC and i'm looking for advice on how to setup a particular registration controller.
I have a controller called AccountController which has a Register method and I have a Register.cshtml.
Now, one of the biggest problems I seem stuck on is that I have 2 dropdowns that I need to populate based on the response from a service as these values change depending on location and other various parameters.
I have my page started and loading but I'm not sure what to do once a user click 'register'.
#model Adw.Models.RegisterModel //This is my model
#Html.DropDownListFor(m => m.States, new SelectList(Model.States)); // I load my dropdowns here
[AllowAnonymous]
public ActionResult Register(RegisterModel model)
{
model.States = Services.GetStates().Payload;
model.Countries = Services.GetCountries().Payload;
return View(model);
}
So my question is, when a user submits the form, should it come back to this same method? If so what would be the best way to validate that this is a submit rather than an initial load?
Also i haven't done much in the way of error handling and could use a suggestion on that, such as if either of the above service calls fail, then a registration cannot be completed, should that direct to a new page or is there a easy way to build that kind of error into the same page?
You should create two different method. One for GET and second for POST request:
[AllowAnonymous]
[HttpGet]
public ActionResult Register()
{
...
}
[AllowAnonymous]
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// create user
return this.RedirectToAction("SignIn");
}
else
{
return View(model);
}
}
You can review sample from default template.

Can I use an AntiForgeryToken without AcceptVerbs tag?

I would like to use the AntiForgeryToken function but the AcceptVerbs post does not apply. I am getting the anti forgery error. Is there a way to do this without the post method?
public ActionResult Page1(string data)
{ //code with view that includes link to Edit }
public ActionResult Page2(string data)
{ //code with view that includes link to Edit }
public ActionResult Edit(string pageName)
{ //execution then redirect to Page1/Page2 }
The anti forgery token works by a cookie and a hidden input field in the form. They both hold the same encrypted value. When the controller handles an action decorated with [ValidateAntiForgeryToken] it checks if the values in the cookie and the hidden input field match. If they don't - you get a nice exception.
You can use code like this
View:
<% using (var form = Html.BeginForm("DoSomething", "Default")) { %>
<%:Html.ValidationMessageFor(x => x) %>
<%:Html.AntiForgeryToken() %>
<%:Html.Hidden("a", 200) %>
<input type="submit" value="Go"/>
<%}%>
Controller:
public class DefaultController : Controller
{
public ActionResult Index()
{
return View();
}
[ValidateAntiForgeryToken]
public ActionResult DoSomething(int a)
{
return View("Index");
}
}
But then the form generated gets an method="post" attribute. On the controller side you don't need to specify [AcceptVerbs(HttpVerbs.Post)]. So the answer to your question is that you can use AntiForgeryToken without the AcceptVerbs attribute. You just need to use the POST method in the form.
To continue with the sample, if you specify [AcceptVerbs(HttpVerbs.Get)] on the action and Html.BeginForm("DoSomething", "Default", FormMethod.Get), the example won't work, because the GET request does not contain the cookie only the hidden input value gets encoded in the query string.

Categories