1

I am trying to add a specific role at the time of new Employee Creation. But getting this error on create.cshtml select tag. I am using .NET 6 MVC with a local SqlServer.

The roles in the application are Admin, Employee, and HumanResource.

Here is the image

System.NullReferenceException: 'Object reference not set to an instance of an object.'

Microsoft.AspNetCore.Mvc.Razor.RazorPage<TModel>.Model.get returned null.

Here is my code [EmployeeViewModel.cs]

public class EmployeeViewModel
{
    public string Id { get; set; }
    [Display(Name = "Username")]
    public string UserName { get; set; }

    [Display(Name = "Email Address")]
    public string Email { get; set; }

    [Display(Name = "First Name")]
    public string Firstname { get; set; }

    [Display(Name = "Last Name")]
    public string Lastname { get; set; }

    public IEnumerable<SelectListItem>? UserRoles { get; set; }

    [Display(Name = "Roles")]
    [Required]
    public string? RoleName { get; set; }
}

[EmployeeController.cshtml]

public class EmployeeController : Controller
    {
        private readonly UserManager<Employee> _userManager;
        private readonly RoleManager<IdentityRole> _roleManager;
        private readonly IMapper _mapper;

        public EmployeeController(UserManager<Employee> userManager, 
            RoleManager<IdentityRole> roleManager, IMapper mapper)
        {
            _userManager = userManager;
            _roleManager = roleManager;
            _mapper = mapper;
        }

// GET: EmployeeController/Create
        public ActionResult Create()
        {
            // Displaying user role except Admin Role on select Tag
            IEnumerable<SelectListItem> roles = _roleManager.Roles.AsNoTracking()
                .Where(n=>n.Name != Roles.Admin.ToString())
                .Select(n=>new SelectListItem()
                    {
                        Value = n.Id, Text = n.Name
                    }).ToList();

            var employeeViewModel = new EmployeeViewModel()
            {
                UserRoles = roles
            };
            return View(employeeViewModel);
        }

        // POST: EmployeeController/Create
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create(EmployeeViewModel model)
        {
            try
            {
                var employee = _mapper.Map<Employee>(model); // used AutoMapper to map data from employee view model to Employee entity
                string defaultPassword = "123Pa$$word."; // default password at the time first User creation
                var result = await _userManager.CreateAsync(employee, defaultPassword);
                if (! result.Succeeded)
                {
                    ModelState.AddModelError("", "Employee is not Created");
                    return View(model);
                }

                var role =  _roleManager.FindByIdAsync(model.RoleName).Result;
                var roleResult = await _userManager.AddToRoleAsync(employee, role.Name);
                if(! roleResult.Succeeded)
                {
                    ModelState.AddModelError("", "Employee Role is not Created");
                    return View(model);
                }

                return RedirectToAction(nameof(Index));
            }
            catch
            {
                ModelState.AddModelError("", "Employee is not Created for exception");
                return View();
            }
        }
}

[Creat.cshtml]

@model LeaveManagement.ViewModels.EmployeeViewModel

@{
    ViewData["Title"] = "Create Employee ";
}

<h2>Create Employee</h2>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create" method="post">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="UserName" class="control-label"></label>
                <input asp-for="UserName" class="form-control" />
                <span asp-validation-for="UserName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Email" class="control-label"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Firstname" class="control-label"></label>
                <input asp-for="Firstname" class="form-control" />
                <span asp-validation-for="Firstname" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="RoleName" class="control-label"></label>
                <select asp-for="RoleName" asp-items="@Model.UserRoles" class="form-select" ></select>
                <span asp-validation-for="RoleName" class="text-danger"></span>
            </div>
            <div class="form-group mt-2">
                <input type="submit" value="Create" class="btn btn-primary" /> 
                <a asp-action="Index" class="btn btn-primary">Back to index</a>
            </div>
        </form>
    </div>
</div>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
SP Sarkar
  • 11
  • 5
  • 2
    You [posted too much code](https://idownvotedbecau.se/toomuchcode/). That's typically because you don't know where the problem is. And that's typically because [you haven't debugged the problem](https://idownvotedbecau.se/nodebugging/). You need to do that before posting on Stack Overflow. Read [What is a NullReferenceException, and how do I fix it](https://stackoverflow.com/questions/4660142/), then update your question with your findings. – Dour High Arch Jun 03 '22 at 19:32
  • 2
    `return View();` in the `catch`... you're not passing a view model. – madreflection Jun 03 '22 at 19:33

0 Answers0