skip to Main Content

I’ve hit a wall while trying to do something and I hope someone can help me understand what I’m doing wrong. Here is the situation. I have a partial view with a form in it, and when I submit that form I want it to go to a POST method in the code-behind of my Index page. To achieve that I have written a jQuery POST request which should be calling the abovementioned method – but it isn’t doing that.

Here is the code-behind of my Index page:

[BindProperty]
public NotificationFormModel NotificationFormModel { get; set; }

public async Task<PartialViewResult> OnGetFormPartial()
{
    NotificationFormModel.Types = await notificationTypeService.GetTypesForDropdownSelectAsync();

    return Partial("~/Pages/Partial/_FormPartial.cshtml", NotificationFormModel);
}

public async void OnPostFormPartial()
{
    string userId = User.GetId()!;
    await notificationController.CreateNotificationAsync(NotificationFormModel, userId);
}

My form model has a dropdown menu, thus the reason for using a service. The Index page itself:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div id="overlay-background">
    <div id="notification-form" class="row input-field notification">
    </div>
</div>

<button id="notification-form-button" onclick="showNotificationForm()">Click me for new form</button>

I am also using a simple overlay effect that puts the focus on the form. The scripts:

function overlayOff() {
    document.getElementById("overlay-background").style.display = "none";
}

function overlayOn() {
    document.getElementById("overlay-background").style.display = "block";
}

function showNotificationForm() {
    overlayOn();

    $(document).on("click", "#notification-form-button", function () {
        $.ajax({
            type: "GET",
            url: "/Index?handler=FormPartial",
            success: function (data) {
                $("#notification-form").html(data);
            }
        });
    });
}

function postNotificationForm() {
    $(document).on("click", "#notification-submit", function () {
        $.post("/Index?handler=FormPartial", $("form").serialize(), function () {
            overlayOff();
        });
        //$.ajax({
        //    type: "POST",
        //    url: "/Index?handler=FormPartial",
        //    contentType: "application/json; charset=utf-8",
        //    success: function () {
        //        overlayOff();
        //    }
        //});
    });
}

And lastly, the partial view itself:

@using HomeNotifications.Web.Models.Notification
@model NotificationFormModel

<form method="post">
    <div class="form-group">
        <label asp-for=Content>Content</label>
        <input asp-for="Content" class="form-control">
        <span asp-validation-for="Content" class="small text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for=TypeId>Type</label>
        <select asp-for="TypeId" class="form-control">
            @foreach (var type in Model.Types)
            {
                <option value="@type.Id">@type.Name</option>
            }
        </select>
        <span asp-validation-for="TypeId" class="small text-danger"></span>
    </div>
    <div class="text-center">
        <input id="notification-submit" class="btn btn-primary mt-3" type="submit" value="Create" onclick="postNotificationForm()" />
    </div>
</form>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

I thank in advance to anyone that offers words of advice.

UPDATE: Thanks to mmm’s comment I was able to figure out what exactly is wrong with my code.

The issue was with the form in the partial view. Yet another reminder that pasting code from previous projects without double-checking it is not a smart idea. I removed the method attribute from the form tag and changed the type of the button from ‘submit’ to ‘button’. In the previous project that I used the form, it was part of an entirely separate view, thus the need to have a way to submit the form to the relevant POST method. In the current project all of that is handled with the jQuery script, so I learned that the form doesn’t need to send anything anywhere anymore.

The other change that I made is in the code-behind of the Index page. I changed the OnPostFormPartial method from async void to async Task. The reason for that is because leaving it as async void was preventing my controller and service methods to work as intended.

Thanks again to mmm for the assistance. I’m still new to jQuery and Javascript as a whole, finding out about the Network tab was a game-changer.

2

Answers


  1. Chosen as BEST ANSWER

    As per the update of the original post, here is the altered code.

    The partial view:

    <form>
        <div class="form-group">
            <label asp-for=Content>Content</label>
            <input asp-for="Content" class="form-control">
            <span asp-validation-for="Content" class="small text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for=TypeId>Type</label>
            <select asp-for="TypeId" class="form-control">
                @foreach (var type in Model.Types)
                {
                    <option value="@type.Id">@type.Name</option>
                }
            </select>
            <span asp-validation-for="TypeId" class="small text-danger"></span>
        </div>
        <div class="text-center">
            <input id="notification-submit" class="btn btn-primary mt-3" type="button" value="Create" onclick="postNotificationForm()" />
        </div>
    </form>
    

    The code-behind of the Index page:

    public async Task OnPostFormPartial()
    {
        string userId = User.GetId()!;
        await notificationController.CreateNotificationAsync(NotificationFormModel, userId);
    }
    

  2. Here is the updated code:

    Partial View:

    @using HomeNotifications.Web.Models.Notification
    @model NotificationFormModel
    
    <form id="notification-form">
        <div class="form-group">
            <label asp-for="Content">Content</label>
            <input asp-for="Content" class="form-control">
            <span asp-validation-for="Content" class="small text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="TypeId">Type</label>
            <select asp-for="TypeId" class="form-control">
                @foreach (var type in Model.Types)
                {
                    <option value="@type.Id">@type.Name</option>
                }
            </select>
            <span asp-validation-for="TypeId" class="small text-danger"></span>
        </div>
        <div class="text-center">
            <input id="notification-submit" class="btn btn-primary mt-3" type="button" value="Create" onclick="postNotificationForm()" />
        </div>
    </form>
    
    @section Scripts {
        <partial name="_ValidationScriptsPartial" />
    }
    

    jQuery Code:

    function postNotificationForm() {
        $(document).on("click", "#notification-submit", function () {
            $.ajax({
                type: "POST",
                url: "/Index?handler=FormPartial",
                data: $("#notification-form").serialize(),
                success: function () {
                    overlayOff();
                },
                error: function () {
                    alert('Failed to submit the form.');
                }
            });
        });
    }
    

    Index page:

    [BindProperty]
    public NotificationFormModel NotificationFormModel { get; set; }
    
    public async Task<PartialViewResult> OnGetFormPartial()
    {
        NotificationFormModel.Types = await notificationTypeService.GetTypesForDropdownSelectAsync();
        return Partial("~/Pages/Partial/_FormPartial.cshtml", NotificationFormModel);
    }
    
    public async Task<IActionResult> OnPostFormPartial()
    {
        string userId = User.GetId()!;
        await notificationController.CreateNotificationAsync(NotificationFormModel, userId);
        return new JsonResult(new { success = true });
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search