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

Viewed 11398

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?

4 Answers

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

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.

In my case, I updated the login view with this line of code. that's fixed.

<form method="post" asp-controller="account" asp-action="login">

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

Related