I have a viewmodel class that called "LoginIndexViewModel" for use on login razor page, containing login, signin & forget password forms. It contains several properties, each of which is a viewmodel separately. Here is the "LoginIndexViewModel" viewmodel:
public class LoginIndexViewModel
{
public LoginViewModel Login { get; set; }
public SignUpViewModel SignUp { get; set; }
public ForgetPasswordViewModel ForgetPassword { get; set; }
}
On "SignUpViewModel" there is a property that has remote validation and I want to check anti-forgery-token before action method call. Here is the body of the "SignUpViewModel":
public class SignUpViewModel
{
.
.
.
[Display(Name = "Email *")]
[DataType(DataType.EmailAddress)]
[Required(ErrorMessage = "The Email Is Required.")]
[EmailAddress(ErrorMessage = "Invalid Email Address.")]
[RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "Invalid Email Address.")]
[Remote("CheckUsername", "Account", ErrorMessage = "The Email Address Have Already Registered.", HttpMethod = "POST", **AdditionalFields = "__RequestVerificationToken")]
public string Username { get; set; }
.
.
.
}
I used [ValidateAntiForgeryToken] attribute above the action method "CheckUsername" and @Html.AntiForgeryToken() on the razor view such as the following:
[HttpPost]
[AjaxOnly]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public virtual async Task<JsonResult> CheckUsername([Bind(Prefix = "SignUp.UserName")]string userName)
{
return Json(await _userManager.CheckUsername(username), JsonRequestBehavior.AllowGet);
}
razor view:
@using (Html.BeginForm(MVC.Account.ActionNames.Register, MVC.Account.Name, FormMethod.Post, new { id = "RegisterForm", @class = "m-login__form m-form", role = "form" }))
{
@Html.AntiForgeryToken()
.
.
.
<div class="form-group">
@Html.TextBoxFor(m => m.SignUp.UserName, new { @class = "form-control", placeholder = "Email *", autocomplete = "off", @Value = "" })
<span class="helper">@Html.ValidationMessageFor(model => model.SignUp.UserName)</span>
</div>
.
.
.
}
The problem is that remote validation call throws the exception: 'The required anti-forgery form field "__RequestVerificationToken" is not present.'
According to the Mozilla debugger tool, I found that CheckUsername calls with 'SignUp.__RequestVerificationToken' parameter instead of '__RequestVerificationToken' therefore it raise an exception.
Anyone knows that what happened and why __RequestVerificationToken is not providing ?