Vlad Radu
Vlad Radu

Reputation: 131

Asp.Net Core: How to properly pass data from view to controller?

I am trying to pass some data from a view to a controller, using a view model.

In view I have something like:

@model LoginRegisterViewModel
<input type="text" name="Email" id="Email" placeholder="Email">
<input type="password" class="form-control" name="Password" id="Password" placeholder="Password">

View Model:

 public class LoginModel
    {
        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }

        [DataType(DataType.Password)]
        public string Password { get; set; }

        [Display(Name = "Remember Me")]
        public bool RememberMe { get; set; }
        public string ReturnUrl { get; set; }
    }

    public class RegisterModel
    {
        public string Username { get; set; }

        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }

        [DataType(DataType.Password)]
        public string Password { get; set; }

        public string ReturnUrl { get; set; }
    }

    public class ResetModel
    {

        [DataType(DataType.EmailAddress)]
        public string Email { get; set; }
        public string ReturnUrl { get; set; }

    }

    public class LoginRegisterViewModel
    {
        public LoginModel Login { get; set; }
        public RegisterModel Register { get; set; }
        public ResetModel Reset { get; set; }
    }

And in controller:

 public async Task<IActionResult> Login(LoginRegisterViewModel model, string returnUrl = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");

            if (ModelState.IsValid)
            {                
                var userOrEmail = model.Login.Email;

               SignInResult result;

                if (userOrEmail.IndexOf('@') > 0)
                    result = await _signInManager.PasswordEmailSignInAsync(userOrEmail, model.Login.Password, model.Login.RememberMe, false);
                else

                result = await _signInManager.PasswordSignInAsync(userOrEmail, model.Login.Password, model.Login.RememberMe, lockoutOnFailure: false);
                if (result.Succeeded)
                {
                    return LocalRedirect(returnUrl);
                }

                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return View(model);
                }
            }

            return View(model);
        }

I am doing something wrong because I get the following error: NullReferenceException: Object reference not set to an instance of an object. referencing this line: var userOrEmail = model.Login.Email;

Upvotes: 0

Views: 354

Answers (2)

Mostafa Mohamed Ahmed
Mostafa Mohamed Ahmed

Reputation: 649

you are binding to the wrong properties.

The controller action expect an object of type LoginRegisterViewModel, and it's the type of the model your view is expecting , but your controls are binding to wrong property .

for example <input type="text" name="Email" id="Email" placeholder="Email"> this maps to model.Email (where model is an object of LoginRegisterViewModel) , and LoginRegisterViewModel doesn't have an Email property but it has a LoginModel property which has the Email property , so you should bind your input to model.Login.Email .

Ps : you can use the MVC core tag helpers to bind properties to model

<input asp-for="model.Login.Email" name="anyothername" class="form-control" />

or even razor syntax @Html.EditorFor(model => model.Login.Email)

Upvotes: 1

Vlad Radu
Vlad Radu

Reputation: 131

Just got it. I should have used name="Login.Email" and name="Login.Password" in the view.

Upvotes: 0

Related Questions