skip to Main Content

I am trying to save a ViewModel object from a partial view in a modal, and I get a 404 error when I try to post it. The url is being called, but the ViewModel data isn’t being sent. I have been reading similar questions on here and on MSN for hours and nothing I’ve tried fixes the problem. I took out the repetitive days of the week code for brevity, but I can
add them back in if anyone wants a complete working example. Here is the code

EmployeeViewModel

public class EmployeeViewModel
    {
        public bool Monday { get; set; } = false;
        //...bool properties for Tuesday through Sunday
        public Employee Employee { get; set; } 
    }

Employee/ _AddEmployeeModalPartial

@model JSarad_C868_Capstone.ViewModels.EmployeeViewModel

@Html.AntiForgeryToken()
<div class="modal modal-fade" id="addEmployee">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title" id="addEmpoyeeLabel">Add Employee</h4>
                <button type=button class="close" data-bs-dismiss="modal">
                    <span>x</span>
                </button>
            </div>
            <div class="modal-body">
                <form action="Add">
                   
                    <div class="form-group">
                        <input asp-for="Employee.Id" class="form-control" />
                        <input asp-for="Employee.Availability" class="form-control" />
                        <label asp-for="Employee.Role"></label>
                        <select asp-for="Employee.Role" class="form-control">
                            <option value="Bartender">Bartender</option>
                            <option value="Server">Server</option>
                        </select>
                        <span asp-validation-for="Employee.Role" class="text-danger"></span>
                    </div>
                    
                    @*<div class="mb-3">*@
                    <div class="form-group">
                        <label asp-for="Employee.Name"></label>
                        <input asp-for="Employee.Name" class="form-control" />
                        <span asp-validation-for="Employee.Name" class="text-danger"></span>
                    </div>
                    
                   @* <div class="mb-3">*@
                    <div class="form-group">
                        <label asp-for="Employee.Phone"></label>
                        <input asp-for="Employee.Phone" class="form-control" />
                        <span asp-validation-for="Employee.Phone" class="text-danger"> 
                        </span>
                    </div>
                    
                    @*<div class="mb-3">*@
                    <div class="form-group">
                        <label asp-for="Employee.Email"></label>
                        <input asp-for="Employee.Email" class="form-control" />
                        <span asp-validation-for="Employee.Email" class="text-danger"> 
                        </span>
                    </div>
                    
                    @*<div class="mb-3">*@
                    <div class="form-group">
                        <label asp-for="Employee.Address"></label>
                        <input asp-for="Employee.Address" class="form-control" />
                        <span asp-validation-for="Employee.Address" class="text-danger"> 
                        </span>
                    </div>
                    
                   @* <div class="mb-3">*@
                    <div class="form-group">
                        <label>Availabiliy</label>
                    </div>
                    
                    <div class="row pb-4">
                        <div class="col">
                            <div class="form-check">
                                <input asp-for="Monday" class="form-check-input" 
                                       type="checkbox" />
                                <label asp-for="Monday" class="form-check-label"></label>
                            </div>
                            <!--...//form check boxes for Tuesday trough Sunday -->
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" 
                        data-bs-dismiss="modal">Cancel</button>
                <button type="button" class="btn btn-primary" 
                        data-bs-save="modal">Save</button>
            </div>
        </div>
    </div>
</div>

EmployeeController.cs

[HttpGet]
public IActionResult Add()
{
    EmployeeViewModel viewModel = new EmployeeViewModel();
    return PartialView("_AddEmployeeModalPartial", viewModel); ;
}

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Add(EmployeeViewModel viewModel) //code never reaches this Action
{
    viewModel.Employee.Availability = ConvertDaysToChar(viewModel.Employee.Availability)
    
    if (ModelState.IsValid)
    {
        _db.Employees.Add(viewModel.Employee);
        _db.SaveChanges();
        return RedirectToAction("Index");
    }
    else
    {
        return PartialView("_AddEmployeeModelPartial", viewModel);
    }
}

site.js

$(function () {
    var PlaceHolderElement = $('#PlaceHolderHere');
    $('button[data-bs-toggle="ajax-modal"]').click(function (event) {
       /* event.preventDefault();*/
        var url = $(this).data('url');
        console.log(url)
        $.get(url).done(function (data) {
            PlaceHolderElement.html(data);
            PlaceHolderElement.find('.modal').modal('show');

        })
    })
    PlaceHolderElement.on('click', '[data-bs-save="modal"]', function (event) {
        event.preventDefault();
        var form = $(this).parents('.modal').find('form');
        var actionUrl = form.attr('action');
        console.log(actionUrl);
        var sendViewModel = form.serialize();
        console.log(sendViewModel);
        
        //$.post(actionUrl, sendViewModel).done(function (data) {
        //    PlaceHolderElement.find('.modal').modal('hide');
        /*above is the code from a tutorial for modals. It also doesn't send the object to 
         post action*/
        
        $.ajax({
            type: 'POST',
            url: actionUrl,
            dataType: 'json',
            contentType: 'application/json',
            data: JSON.stringify(sendViewModel),
            success: function (result) {
                console.log('Data received: ');
                console.log(result);
            }
        })
    })
})

When I click the save button on the model, the console.log(sendViewModel) returns the correct Serialization with all of the properties and their correct names. And the properties change correctly when there is input.


Employee.Id=&Employee.Availability=&Employee.Role=Bartender&Employee.Name=&Employee.Phone=&Employee.Email=&Employee.Address=&Monday=false&Tuesday=false&Wednesday=false&Thursday=false&Friday=false&Saturday=false&Sunday=false

But I get an error "Failed to load resource: the server responded with a status of 404 ()"
and when I check it the page says "No webpage was found for the web address: https://localhost:44313/Add HTTP ERROR 404" as if it’s trying to get a post. It is also missing the controller, but if I change my form action to "Employee/Add" in the _Partial view it still doesn’t send the data along with the url, which is causing an entirely different problem. I would greatly appreciate any help or guess or input of any kind. I’m about five seconds away from throwing my laptop out the window on this one. Thanks.

2

Answers


  1. Chosen as BEST ANSWER

    First, I had to change the form action from "Add" to "Employee/Add". ThenI had to remove the antiforgery token from my post action. The first code that is commented out actually works fine otherwise. In my defense I did remove the antiforgery token when I had the wrong URL, but I forgot to retest that when I had the correct one.


  2. 1.Remove the @Html.AntiForgeryToken() inside your form,like below:

     <form action="Add"  >
      @Html.AntiForgeryToken()
      ....
    

    Then after you serialize the form you can get the AntiForgeryToken, like below:

    enter image description here
    Because when you don’t add @Html.AntiForgeryToken()inside form, after you serialize the form you don’t get the AntiForgeryToken, like below:

    enter image description here

    Besides, if you use <form asp-action="Add" > In ASP.Net Core anti forgery token is automatically added to forms, so you don’t need to add @Html.AntiForgeryToken(),you can find in the below :

    enter image description here

    2.change your ajax like below:

    $.ajax({
                type: 'POST',            
                url:'/Employee/Add',            
                contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
                data: sendViewModel,
                success: function (result) {
                    console.log('Data received: ');
                    console.log(result);
                }
            })
    

    result:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search