I have an ASP.NET Core MVC project and I am trying to send a model and some other parameter from JavaScript to a controller action. First I fill the model from view fields whose names match the model properties.
var model = {}; //global variable
function updateModel()
{
for(const element of document.querySelectorAll("input.account-property-input"))
{
if(element instanceof HTMLInputElement && typeof element.name === "string" && element.name.trim().length > 0)
{
model[element.name] = element.value;
}
}
let checkbox = document.querySelector("input#enable-two-factor-checkbox");
if(checkbox instanceof HTMLInputElement)
{
model[checkbox.name] = checkbox.checked;
}
if(checkbox.checked)
{
radio = document.querySelector("input#two-factor-by-phone-radio");
model.TwoFactorMethod = radio.checked ? "TwoFactorByPhoneNumber" : "TwoFactorByEmail";
}
}
Data sending:
model = updateModel();
const urlAction = window.location.origin + "/UserAccount/ConfirmContact";
const jqXHR = $.ajax({
method: "POST",
url: urlAction,
data: { model: model, contactType: contactType },
contentType: "application/json; charset=utf-8"
});
await jqXHR?.then(
async function(data, textStatus, jqxhr)
{
alert(`request to ${urlAction} is successed`);
},
function(jqxhr, textStatus, errorThrown)
{
alert(`request to ${urlAction} is failed; status: ${textStatus}; error: ${errorThrown}`);
});
My model:
public enum ContactType : int
{
EMail = 0,
PhoneNumber
}
public class AccountViewModel : ModelBase
{
public string? UserId { get; set; }
public string? UserName { get; set; }
public string Password { get; set; }
public string PasswordConfirmation { get; set; }
public bool TwoFactorEnabled { get; set; }
public TwoFactorMethod TwoFactorMethod { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
public ContactConfirmationState EmailConfirmationState { get; set; }
public ContactConfirmationState PhoneConfirmationState { get; set; }
public string Name { get; set; }
public string? EsiaLogin { get; set; }
public string? EsiaPassword { get; set; }
public string EsiaPasswordConfirmation { get; set; }
public AccountViewModel()
{
}
}
On the controller side:
[HttpPost]
public async Task<IActionResult> ConfirmContact(AccountViewModel model, ContactType contactType)
{
if(model != null)
{
if(contactType == ContactType.PhoneNumber)
{
if(await PhoneConfirmationService.SendVerificationCode(model))
{
model.PhoneConfirmationState = ContactConfirmationState.AwaitingConfirmation;
}
}
else
{
if(await EmailConfirmationService.SendVerificationCode(HttpContext, model))
{
model.EmailConfirmationState = ContactConfirmationState.AwaitingConfirmation;
}
}
}
return View("Register", model ?? new AccountViewModel());
}
But the action parameters are not initialized from the request, but with a default value.
How to send the data correctly?
My project repo
modelJS variable?var model = updateModel();:updateModel()doesn't return anything, so of coursemodelis null.model = updateModel()overwrites whatever was in that variable. BecauseupdateModel()doesn't return anything. When you observe the AJAX request in your browser's debugging tools, what data is sent in that request? When you observe themodelvariable in your debugger at the$.ajax({operation, what does that variable contain? Don't assume. Debug and observe.