Search code examples
c#asp.net-core-mvchttp-post

Can't POST value from view to controller in ASP.NET Core MVC


I need to post a value from a dropdownlist in form to my HomeController.

Here is the view:

@{
    
List<SelectListItem> listItems= new List<SelectListItem>();
listItems.Add(new SelectListItem
    {
      Text = "Title",
      Value = "@SortsMethods.Title",
    });
listItems.Add(new SelectListItem
    {
        Text = "DeadLineDate",
        Value = "@SortsMethods.DeadLineDate",
    });
listItems.Add(new SelectListItem
    {
        Text = "IsComplete",
        Value = "@SortsMethods.IsComplete"
    });
}

<form asp-controller="Home" asp-action="Index">
    
    <select asp-for="SortsMethods" asp-items="listItems">
    </select>
    
    <input type="submit" >
</form>

Here is the HomeController:

public readonly ITasksCommands _tasksCommands;
private readonly TasksDbContext _tasksDbContext;

public HomeController(ITasksCommands tasksCommands, TasksDbContext tasksDbContext)
{
    _tasksCommands = tasksCommands;
    _tasksDbContext = tasksDbContext;
}    

[Route("/")]
public async Task<ViewResult> Index()
{
    return View(new SortTypeModel()
    {
        Tasks = await _tasksCommands.GetTasks().ToListAsync(),
        SortsMethods = SortsMethods.Title
    });
}

[HttpGet]
public async Task<SortTypeModel> Index(SortsMethods sortsMethods)
{
    var obj = _tasksCommands.GetTasks();
    switch (sortsMethods)
    {
        case SortsMethods.Title:
            obj = obj.OrderByDescending(x => x.Title);
            break;
        case SortsMethods.DeadLineDate:
            obj = obj.OrderByDescending(x => x.DeadlineDate);
            break;
        case SortsMethods.IsComplete:
            obj = obj.OrderByDescending(x => x.IsCompleted);
            break;
    }
    return new SortTypeModel()
    {
        Tasks = await obj.ToListAsync(),
        SortsMethods = SortsMethods.Title
    };
}

And these are the model classes:

namespace TasksApplication.Domain;

public class Tasks 
{
    [Required]
    public Guid Id { get; set; }
    public string Title { get; set; }
    public string Details { get; set; }
    public bool IsCompleted { get; set; }
    public DateTime DeadlineDate { get; set; }
}

namespace WebApplication1.Models;

public class SortTypeModel 
{
    public SortsMethods SortsMethods { get; set; }

    public List<Tasks> Tasks { get; set; }

}

namespace TasksApplication.Application.Enum;

public enum SortsMethods
{
    Title, 
    DeadLineDate,
    IsComplete
}

My problem is that the controller doesn't receive sortsMethods, so it executes a default Index.

I've tried different dropdownlist forms, from manual <select><option>... where I write what is what, to this what I currently have.

Does anyone know what I'm doing wrong?


Solution

  • In your routing configuration, [Route("/")] will cause the method you submit to only enter the get method. Therefore, you need to ensure that the GET and POST methods are clearly distinguished. You can use [HttpGet] and [HttpPost] to mark them or specify different routing templates for them. In addition, you can get the value of the drop-down list through asp-items="Html.GetEnumSelectList<SortsMethods>()". Here is an example for your reference:

    <form asp-controller="Home" asp-action="Index"> 
        <select asp-for="SortsMethods" asp-items="Html.GetEnumSelectList<SortsMethods>()">
            <option value="">-- Select sort by --</option>
        </select>
        <input type="submit" value="Submit">
    </form>
    

    Controller:

      [HttpGet("/")]
    public async Task<ViewResult> Index()
    {
        //code in method
    }
    
    
    [HttpPost]
    public async Task<SortTypeModel> Index(SortsMethods sortsMethods)
    {
       // code in method
    }
    

    when I submit data:

    enter image description here

    Controllers can accept requests as well as data: enter image description here