Search code examples
jqueryasp.net-mvcasp.net-coremodel-binding

Populate input tags using jQuery and then submit to ASP.NET Core through model binding


I'm writing a part of an ASP.NET Core MVC 3.1 application where an Admin adds new users to the application. There can be domain users and local users, so the plan is to give the Admin a select tag (Domain/Local), an input tag with 3rd-party autocomplete library for search operations among eligible domain users, and a series of normal input tags for manually insert a new local user.

When the Admin searches through the domain users, a serialized json in used as a source and then the selected user Id, First Name and Second Name are copied from the autocomplete source to the manual input tags (which can also be directly used in case of a local user). Finally, the values of those input tags are used as binding source for the model sent to the action method.

I have a fairly simple ViewModel:

public class UserCreateModel
{
    [BindNever]
    public List<SelectListItem> AvailableDomains { get; }

    [BindNever]
    public string EligibleUsers { get; set; }

    [Required]
    public UserDomain SelectedDomain { get; set; }

    [Display(Name = "Id Utente")]
    [Required]
    public string Id { get; set; }

    [Required] 
    public string Nome { get; set; }

    [Required] 
    public string Cognome { get; set; }
}

The EligibleUsers property is the serialization of a List<EligibleUserModel> instance:

public class EligibleUserModel
{
    public string text { get; set; }
    public string link { get; set; }
    public string cognome { get; set; }
    public string nome { get; set; }
}

This is the associated View, in which I have retained just the basic html code, stripped of all tags, classes and attributes that aren't relevant to the issue:

@model UserCreateModel

<form method="post">
    <fieldset>
        <select asp-for="SelectedDomain" asp-items="Model.AvailableDomains"></select>
    </fieldset>
    <fieldset class="add-domain-user">
        <input type="search" class="autocomplete"
               id="autocomplete-users"
               name="autocomplete-users"
               data-autocomplete='@Model.EligibleUsers'
    </fieldset>
    <fieldset disabled>
            <input asp-for="Id" type="text" class="form-control"/>
            <input asp-for="Cognome" type="text" class="form-control"/>
            <input asp-for="Nome" type="text" class="form-control"/>
    </fieldset>
    <button asp-controller="Account" asp-action="AddUser" type="submit">Conferma</button>
</form>

The data-autocomplete attribute is part of a third-party library that receives a JSON of all the eligible users to be added and dynamically appends a list of anchor tags to the input tag. With some jQuery, I fill the Id, Cognome and Nome input tags. :

$('form .add-domain-user').on('click', '.autocomplete-list li a', function (event) {
    event.preventDefault();

    // the href attribute comes with the 3rd-party lib, and is the only way 
    // for me to get the selected user Id
    var id = $(this).attr('href');

    var userList = $('.add-domain-user input[type="search"]').data()["autocomplete"];
    var selectedUser = userList.find(el => el.link === id);

    $('#Id').val(selectedUser.link);
    $('#Cognome').val(selectedUser.cognome);
    $('#Nome').val(selectedUser.nome);
});

Now, the problem is that when I manually type text in the input tags, they are correctly bound and sent to the action method. When I try selecting a domain user from the autocomplete list I can see the values in the input tags, but no value is bound to the model.


Solution

  • In the end, it was just the disabled attribute that prevented the form to post anything. Changed to readonly and it works.