ASP.NET Core MVC invoke function through button on razor page

36 Views Asked by At

I have a .cshtml page that displays some information about a racing session. At the bottom I want to add a button that invokes a function getting drivers of that session to the database and redirects me to a page displaying them in a list.

My code is as follows:

@page
@model WebApplication1.Pages.Sessions.DetailsModel

@{
    ViewData["Title"] = "Details";

    @functions {
        PlatformyProgramistyczneAPI.DbManager dbman = new PlatformyProgramistyczneAPI.DbManager();
        public void OnPost()
        {
            dbman.ReplaceDriversDbBySession(Model.SessionDb.session_key);
            Response.Redirect("/Drivers");
        }
    }
}

<h1>@Html.DisplayFor(model => model.SessionDb.country_name)</h1>

<div>
    <h4>@Html.DisplayFor(model => model.SessionDb.circuit_short_name) @Html.DisplayFor(model => model.SessionDb.year)</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            Start date
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.SessionDb.date_start)
        </dd>
        <dt class="col-sm-2">
            End date
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.SessionDb.date_end)
        </dd>
    </dl>
</div>

<form asp-page-handler="post">
    <button onclick="" class="btn btn-default">Show drivers</button>
</form>

I created a form at the bottom that only contains a submit button in hopes I could invoke the OnPost() function, but when I click it, all data related to the model disappears from the page and none of the operations in OnPost are performed. When I comment out every line related to the model it works as intended.

Why can't I use buttons with models in this way? What is the proper way to invoke C# on press of a button?

Here is my DetailsModel code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using PlatformyProgramistyczneAPI.F1Api;

namespace WebApplication1.Pages.Sessions
{
    public class DetailsModel : PageModel
    {
        private readonly PlatformyProgramistyczneAPI.F1Api.DriversDatabase _context;

        public DetailsModel(PlatformyProgramistyczneAPI.F1Api.DriversDatabase context)
        {
            _context = context;
        }

        public SessionDb SessionDb { get; set; } = default!;

        public async Task<IActionResult> OnGetAsync(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var sessiondb = await _context.Sessions.FirstOrDefaultAsync(m => m.id == id);
            if (sessiondb == null)
            {
                return NotFound();
            }
            else
            {
                SessionDb = sessiondb;
            }
            return Page();
        }
        
        public IActionResult OnPost(int session_key)
        {
            PlatformyProgramistyczneAPI.DbManager dbman = new PlatformyProgramistyczneAPI.DbManager();
            dbman.ReplaceDriversDbBySession(session_key);
            return Redirect("/Drivers");
        }
    }
}
2

There are 2 best solutions below

0
Akip On

I somehow managed to get it to work by replacing the form from the original code with this:

<form method="post">
<fieldset>
    <div>
        <label>&nbsp;</label>
        <input type="submit" value="Submit" class="submit" />
        <input type="hidden" name="session_key" value=@key />
    </div>
</fieldset>

If anybody knows why this works and my first approach doesn't, I'd be very thankful for an explanation as I don't really get the difference between those two ways. If in general there is a better way to invoke C# code with a button I would also much appreciate any and all tips for future reference.

0
Md Farid Uddin Kiron On

Why can't I use buttons with models in this way? What is the proper way to invoke C# on press of a button?

If you would like to call IActionResult OnPost(int session_key) method from your cshtml button click, all you need a asp-page-handler which you already have. I am not sure, what did you mean by invoke C#.

According to your scenario, if you want to call your Details.cshtml.cs post method, you can simply do call it as following and can pass parameters using input field. I have tried as following and the OnPost(int session_key) has invoked accordingly.

I have modifed your code slidely in order to test that:

Details.cshtml.cs

public class DetailsModel : PageModel
{
    public string SessionKey { get; set; } = "This is my default key";
    public void OnGet()
    {
    }

    public IActionResult OnPost(string session_key)
    {
        var submittedKey = session_key;
        //PlatformyProgramistyczneAPI.DbManager dbman = new PlatformyProgramistyczneAPI.DbManager();
        //dbman.ReplaceDriversDbBySession(session_key);
        return Redirect("/Drivers");

    }
}

Details.cshtml:

@page
@model RazorPageApp.Pages.DetailsModel

<form method="post" asp-page-handler="OnPost">
    <input type="hidden" name="session_key" value="@Model.SessionKey" />
    <button type="submit" class="btn btn-primary">Show drivers</button>
</form>

Note: Point to keep in mind, button type is submit and paramters should pass in input field.

Output:

enter image description here

enter image description here

Note: I have tried this way and it has invoked the method you want to hit.