ASP.NET Core 2.1 Razor Form, Post not reaching Controller

asp.net core form submit
asp.net form submit example
asp net core ajax form post
how to post data in asp.net core
razor form post to controller
asp.net core post
asp net core form builder
asp-action not working

I spent a good margin of time searching and working through this problem yesterday without coming up with a solution. Here is the guide I used as reference.

The problem is that the data from the form is not reaching my controller. My goal is to take the form data and pass it to my controller/ model so that I can use the values throughout my code and store them in the database. Below is what I have so far...

In my Browse.cshtml (View)

@model Collect

<form asp-action="Collect" asp-controller="Collect" method="post">
<input type="hidden" asp-for="GameId" name="@game.id"/>
<button type="submit" class="dropdown-item btn btn-block">Default</button>
</form>

In my CollectController.cs (Controller)

using System;
using GameLibrary.me.Models;
using Microsoft.AspNetCore.Mvc;

namespace GameLibrary.me.Controllers
{
public class CollectController  : Controller
{
    [HttpGet]
    public IActionResult Collect()
    {
        return View();
    }

    [HttpPost, ValidateAntiForgeryToken]
    public IActionResult Collect(Collect model)
    {

        Console.WriteLine("**********\n"+model.GameId+"\n**********");

        return Content($"Hello {model.GameId}");
    }    
  }
}

In my Collect.cs (Model)

namespace GameLibrary.me.Models

{
public class Collect
{
    public int GameId { get; set; }
  }
}

EDIT: Here is what my IDE is telling me...

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
  Request starting HTTP/1.1 POST https://localhost:5001/browse?game=eevee application/x-www-form-urlencoded 7

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
  Request finished in 1.0139ms 200

info: Microsoft.AspNetCore.Server.Kestrel[32]
  Connection id "0HLJHIUOU6AKO", Request id "0HLJHIUOU6AKO:00000003": the application completed without reading the entire request body.

Any guidance on what I am doing wrong would be great appreciated... Also can I send multiple values through the hidden field type, or should I make a new hidden field type for each value?

There was a lot of different help here, thanks especially to Kirk Larklin! There were three issues that was preventing my controller from picking up the data.

  1. Browse.cshtml was missing the @addTagHelpers... I added the following:

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @addTagHelper *, AuthoringTagHelpers
    
  2. My CollectController.cs was missing a route... I added the following:

    [HttpPost, ValidateAntiForgeryToken]
    [Route("Index/Collect")] 
    
  3. Finally, I renamed my controller post method from 'Collect' which conflicting with another method to Index and updated the asp-action in my Browse.CSHTML file to match.

    public IActionResult Index(Collect model)
    

Thanks for all the help!

-Travis W

Handle requests with controllers in ASP.NET Core MVC, The [Controller] attribute is applied to the class. A controller class must not have an associated [NonController] attribute. Controllers should follow  Tag Helpers in forms in ASP.NET Core. 12/05/2019; 18 minutes to read +12; In this article. By Rick Anderson, N. Taylor Mullen, Dave Paquette, and Jerrie Pelser. This document demonstrates working with Forms and the HTML elements commonly used on a Form. The HTML Form element provides the primary mechanism web apps use to post back data to the

First I would pass in the model to the view with the Id initialised:

    public IActionResult Collect()
    {

        return View(new Collect { GameId = "5"});
    }

Inside your view update the form to the following:

<form asp-action="Collect" asp-controller="Collect" method="post">
    @Html.HiddenFor(m => m.GameId)
    <button type="submit" class="dropdown-item btn btn-block">Default</button>
</form>

The Html helper will create the html coded for the field. Once you click submit the value will be correct.

Routing to controller actions in ASP.NET Core, ASP.NET Core controllers use the Routing middleware to match the URLs of use the same action name when they're part of a show form, submit form workflow. reserved route parameter names when using Controllers or Razor Pages: Actions that define attribute routes cannot be reached through the  Submit your form with the developer tools open (F12) and you’ll see the form post in the network tab. Click the relevant request and check out the Form Data section. In this example you can see that firstName has been submitted as form data and so should be available to ASP.NET Core.

Based on your example I do not believe that you want custom actions, you should be able to achieve your goal with the default framework mapping.

public class CollectController : Controller
{
     [HttpGet]
     public IActionResult Index() => View();

     [HttpPost]
     public IActionResult Index([FromBody]CollectionModel model) => Content(...);
}

To clarify the magic, the declared Post method I utilize a HttpBody attribute, otherwise the framework will expect the parameter contents to be defined via Query String in the URL. The framework by default looks for Index when a Controller has been hit, if you do not need the URL to represent that, then do not use it.

The routing pattern usually follows:

routes.MapRoute(
                "Default",                         // Route name
                "{controller}/{action}/{id}",      // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

URL:

http://www.sample.com/Collect ---> Initial index Get would be hit

How to get data from an HTML form to your ASP.NET MVC Core , ASP.NET Core Tag Helpers make this trivial whilst saving you from making easy mistakes. <form method="POST"> <label for="firstName">Your first So, using default routing conventions, we could use a controller like this… ASP.​NET Core MVC can be pretty confusing. But fear not, you can skip the  The ASP.NET Core runtime delegates the responsibility of reading the body to an input formatter. Input formatters are explained later in this article . When [FromBody] is applied to a complex type parameter, any binding source attributes applied to its properties are ignored.

When ASP.NET Core can't find your controller: debugging , In this post I describe application parts, how ASP. a routing issue, so requests meant for the controllers were not reaching NET Core to discover controllers, view components, tag helpers, Razor NET Core 2.1 (16) ASP. The preceding code looks a lot like a Razor view file used in an ASP.NET Core app with controllers and views. What makes it different is the @page directive. @page makes the file into an MVC action - which means that it handles requests directly, without going through a controller.

Routing in Razor Pages, Routing in Razor Pages is the system that matches URLs to Razor page files. of Attribute Routes (familiar to anyone who has used them in ASP.NET MVC 5 or MVC Core) is constructed, using the file and folder paths NET Core 2.1. You may have a page called Post.cshtml in your root pages folder in  Areas provide a way to partition an ASP.NET Core Web app into smaller functional groups, each with its own set of Razor Pages, controllers, views, and models. An area is effectively a structure inside an app. In an ASP.NET Core web project, logical components like Pages, Model, Controller, and View are kept in different folders.

Areas in Razor Pages, Areas in Razor Pages can be used to divide the application up into functional area is a self-contained unit consisting of its own controller, views and model. the change that resulted in the introduction of Identity as a class library in ASP.​NET Core 2.1. Areas do not require much by way of configuration. By Rick Anderson. View or download sample code (how to download). An Application Part is an abstraction over the resources of an app. Application Parts allow ASP.NET Core to discover controllers, view components, tag helpers, Razor Pages, razor compilation sources, and more.

Comments
  • what is the value of the GameId hidden input when the page is first rendered? (the linked sample is using non-hidden inputs to gather data, also I believe you'll want to change the name value of your input to just GameId) Also, if you use the broswer debug tools, and look at the POST to your controller, is the GameId value being sent?
  • I imagine your routing has an issue because your controller is named Collect, the index method is named Collect, so when the framework is looking for a route your saying it should be /Collect/Collect. You also could use base name of index, like it is searching as a fallback and use HttpRoute to predefine a new name. Unless you correctly defined those custom route names elsewhere.
  • I think you're right @Greg ... Just added the response from my IDE to my post. So I would want to change the ASP-ACTION in the razor form and then in my controller change the method name to match?
  • @G_P It looks like it is going through. In this case gameID is an int being sent. In this case, if I change this to be a static value such as 5, the same problem occurs. I also just updated my question with the response from my IDE.
  • If you put a breakpoint in your Post controller method, and it gets hit when you debug, then it isn't a routing issue. If it does not get hit, then it is, try renaming the Post method (and updating your form asp-action). Then, if your breakpoint is being hit but the value isn't in your model variable, it is due to model binding not working. Try the rename I of your hidden input I mentioned earlier. Also, to your question about additional values, yes, just add additional hidden inputs if they are values that are needed but should not be edited by the user.
  • You did the custom Route definer I mentioned, I assume that fixed?