Remote attribute does't work properly

2033

Member
Joined
May 11, 2025
Messages
7
Programming Experience
1-3
I have a viewModel for the Index view. The problem is that when remote attribute is trying to do it's job the IsUnique method in my controller receives name = null, though i expext it to be a value that I put inside input field.

It works with another view, model of which is just SetViewModel. And here i have this vm inside another vm. On the index page I have sets in total as well as a button to create a new one. So I decided to create a vm, that contains everything for the view.

This is a viewModel for the index view. Here I want you to notice the SetViewModel vm, that contains validation attributes (Remote as well):
public class IndexViewModel
{
    public IEnumerable<SetViewModel> Sets { get; set; }

    public SetViewModel NewSet { get; set; }

    public IndexViewModel()
    {
        Sets = [];
        NewSet = new();
    }
}

SetViewModel itself with the property Name:
public class SetViewModel
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Name is required.")]
    [Display(Name = "Name of the set")]
    [MaxLength(2, ErrorMessage = "The name of the set must be with a maximum length of {0} characters")]
    [Remote(action: "CheckSet", controller: "Home", areaName: "Sets", HttpMethod = "POST", AdditionalFields = "Id", ErrorMessage = "Set with this name already exists")]
    public string Name { get; set; } = null!;
}

Method IsUnique in a cotroller. The parameter name is null from index view, but it's working in another view with just SetViewModel as a model.:
[HttpPost]
public async Task<IActionResult> CheckSet(string name, int id)
{
    return Json(!await IsSetUnique(name, id));
}

What am I doing wrong in this scenario? Why is it null? When I fill the input field and submit the form it shouldn't be null. In the POST method it comes with a name, but not here.
 
What is the model that you set in the view?
 
What is the model that you set in the view?

As I said in the beginning the viewModel of a view Index is IndexViewModel. There I have a form. When I submit it, it goes in the next method.
C#:
[HttpPost]
public async Task<IActionResult> AddSet(IndexViewModel vm)
{
    await dataManager.SetRepository.AddAsync(mapper.Map<Set>(vm.NewSet));

    TempData["success"] = "The new set has been successfully added";
    return RedirectToAction("Index");
}

Well, not entirerly. Firstly it goes to check the remote action, that I have in SetViewModel, but the name in the CheckSet method is null for some strange reason. Because after the CheckSet method it goes in to the AddSet method and there I can see that property Name is populated from an input.
 
@Skydiver To be honest it seems like I must use ajax if I want to achieve anything good (though i was trying not to). Just need to get rid of the remote attribute (doesn't work with ajax for some reason)
 
My question was meant to prompt you to show us your CSHTML. Basically what did you have for your @model line in the CSHTML?

Anyway, Razor has no way of knowing that the name parameter of your CheckSet() method maps to the the Name property of the NewSet property of your IndexViewModel model. The typical way to get Razor to know this is to use partial views. Within the partial view, you would set the model to be the SetViewModel.
 
My question was meant to prompt you to show us your CSHTML. Basically what did you have for your @model line in the CSHTML?

Bro, as I said IndexViewModel:
@model IndexViewModel
@{
    ViewData["Title"] = "Flashcards";
}

<div class="row pt-4 pb-3">

    <h2 class="text-light mb-0 col-6 align-content-center">
        Your library
    </h2>

    <div class="col-6 text-end">
        <a class="btn btn-primary border-1 border-dark-subtle text-bg-dark" title="Create new set" data-bs-toggle="modal" data-bs-target="#newset">
            <i class="bi bi-plus-lg"></i> Add new set
        </a>
    </div>

    <!-- Modal for add set action -->
    <form asp-area="Sets" asp-controller="Home" asp-action="AddSet" method="post">

        <input hidden asp-for="NewSet.UserId" />

        <div class="modal fade" id="newset" tabindex="-1" aria-labelledby="lableIMG" aria-hidden="true" data-bs-theme="dark">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title text-light" id="lableIMG">New set</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <div class="input-group row m-0 p-0">
                            <label asp-for="@Model.NewSet.Name" class="input-group-text bg-dark text-light"></label>
                            <input asp-for="@Model.NewSet.Name" class="form-control bg-dark text-light">
                            <span asp-validation-for="@Model.NewSet.Name" class="text-danger"></span>
                        </div>
                    </div>
                    <div class="modal-footer justify-content-center">
                        <button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button>

                        <button type="submit" class="btn btn-primary">
                            Create new set
                        </button>

                    </div>
                </div>
            </div>
        </div>
    </form>
 
Interesting that this blog post says that the property being validated by Remote needs to be a direct descendant, but I can't find corresponding MS documentation to back it up. I wonder if it was hard earned experience that led the author to that statement.

 
Back
Top Bottom