1

I have an email property in my model that looks like this

    [Required(ErrorMessage ="Email Address is required.")]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    [Remote("checkEmailValidate", "Employee", HttpMethod = "POST", ErrorMessage ="User with this Email already exists")]
    public virtual string EmailAddress { get; set; }

And I have two different views that use this model, the first is when creating a user;

<div class="form-group">
    @Html.LabelFor(model => model.EmailAddress, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { @class = "form-control", placeholder = "Email Address" } })
        @Html.ValidationMessageFor(model => model.EmailAddress, "", new { @class = "text-danger" })            
    </div>
</div>

And the second is when you are editing the users account

<div class="form-group">
    @Html.LabelFor(model => model.EmailAddress, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.EmailAddress, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.EmailAddress, "", new { @class = "text-danger" })
    </div>
</div>

Now my controller looks something like this

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "EmployeeId,FirstName,LastName,UniversityID,EmailAddress,Department,MinimumHours,ApproverEmailAddress,IsActive,Type,NotificationRecipients,ReviewerFor,IsDepartmentHR,IsAdministrator")] Employee employee)
    {
        if (checkEmail(employee.EmailAddress))
        {
            if (IsAuthorized(AuthorizationType.Either))
            {
                if (ModelState.IsValid)
                {
                    if (IsAuthorized(AuthorizationType.Administrator))
                    {
                        db.Employees.Add(employee);
                        db.SaveChanges();
                        Utilities.AuditEvent(loggedOnEmployee, employee, Utilities.AuditEventType.AddEmployee);
                        return RedirectToAction(actionName: "Index");
                    }
                    if (IsAuthorized(AuthorizationType.DepartmentHR))
                    {
                        employee.Department = loggedOnEmployee.Department;
                        db.Employees.Add(employee);
                        db.SaveChanges();
                        Utilities.AuditEvent(loggedOnEmployee, employee, Utilities.AuditEventType.AddEmployee);
                        return RedirectToAction(actionName: "Index");
                    }
                }
                return View(employee);
            }
            else
            {
                return RedirectToAction(actionName: "Restricted");
            }
        }
        else
        {
            return RedirectToAction(actionName: "Create");
        }

    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "EmployeeId,FirstName,LastName,UniversityID,EmailAddress,Department,MinimumHours,ApproverEmailAddress,IsActive,Type,NotificationRecipients,ReviewerFor,IsAdministrator,IsDepartmentHR")] Employee employee)
    {
        if (IsAuthorized(AuthorizationType.Either))
        {
            if (ModelState.IsValid)
            {
                if (IsAuthorized(AuthorizationType.Administrator))
                {
                    Employee employeeInDb = db.Employees.Find(employee.EmployeeId);
                    db.Entry(employeeInDb).CurrentValues.SetValues(employee);
                    db.Entry(employeeInDb).State = EntityState.Modified;
                    db.SaveChanges();
                    Utilities.AuditEvent(loggedOnEmployee, employeeInDb, Utilities.AuditEventType.EditEmployee);
                    return RedirectToAction(actionName: "Index");
                }

                if (employee.Department != loggedOnEmployee.Department)
                {
                    return RedirectToAction(actionName: "Restricted");
                }
                else
                {
                    Employee employeeInDb = db.Employees.Find(employee.EmployeeId);
                    db.Entry(employeeInDb).CurrentValues.SetValues(employee);
                    db.Entry(employeeInDb).State = EntityState.Modified;
                    db.SaveChanges();
                    Utilities.AuditEvent(loggedOnEmployee, employeeInDb, Utilities.AuditEventType.EditEmployee);
                    return RedirectToAction(actionName: "Index");
                }
            }
            return View(employee);
        }
        else
        {
            return RedirectToAction(actionName: "Restricted");
        }
    }

This is my problem:

I want to make sure that a user isn't created using an existing email address, but I want to be able to edit existing users. What happens now is when creating a user, it works perfectly, but when editing a user, I still get the user already exists message. How do I fix this so that the warning doesn't pop-up on the edit view?

Andrew McKeighan
  • 121
  • 1
  • 11
  • create 2 viewmodels for each view and put attribute on one where needed and not on other one – Ehsan Sajjad Feb 03 '17 at 17:17
  • possible duplicate of http://stackoverflow.com/questions/28218337/remote-validation-in-mvc-affected-edit – Balaji Marimuthu Feb 03 '17 at 17:21
  • 1
    What happens if an employee is edited and the edit includes an email which already exists (from another employee)? You would still need the `RemoteAttribute`, but you handle that by passing the `ID` of the employee (which will be `0` or `null` for a new one) in the `AdditionalFields` property of `RemoteAttribute`. Then then use that to conditionally check if it exists. –  Feb 03 '17 at 21:28

2 Answers2

1

Make a separate class Model public class CreateEmployee : Employee for use with the Create action. Override the EmailAddress Property on the new class and add the Remote validator to the CreateEmployee but not the Employee.

Like this:

public class Employee
{
    [Required(ErrorMessage ="Email Address is required.")]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    public virtual string EmailAddress { get; set; }
}

public class CreateEmployee : Employee
{
    //Existing members of Employee should be preserved. if there are any so your code should continue to work.

    [Required(ErrorMessage ="Email Address is required.")]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    [Remote("checkEmailValidate", "Employee", HttpMethod = "POST", ErrorMessage ="User with this Email already exists")]
    public override string EmailAddress { get; set; }
}
Theo
  • 885
  • 6
  • 16
1

These are the scenarios where ViewModel importance comes in to play, you will have to create two different ViewModel one for Create Employee View and one for EditEmployee for instance, then bind each view with it's respective ViewModel.

your both viewmodels would be like:

public class CreateEmployeeViewModel
{
    [Required(ErrorMessage ="Email Address is required.")]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    [Remote("checkEmailValidate", "Employee", HttpMethod = "POST", ErrorMessage ="User with this Email already exists")]
    public virtual string EmailAddress { get; set; }
}

and in EditEmployeeViewModel you can remove the attributes that you don't want to be applied:

public class EditEmployeeViewModel
{
    [Required(ErrorMessage ="Email Address is required.")]
    [EmailAddress(ErrorMessage = "Invalid Email Address")]
    public virtual string EmailAddress { get; set; }
}
Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
  • I noticed you just made another class instead of using inheritance like the other user answered. Why is that? Because when I try making CreateEmployee: Employee , it gives me an error – Andrew McKeighan Feb 03 '17 at 17:57
  • what is the error and it depends how your Employee class defintion looks like, show the definition of it by updating your question. – Ehsan Sajjad Feb 03 '17 at 20:43
  • It gives me a NullReferenceException. It seems like the controllers cannot access the Employee model when I make the CreateEmployee : Employee model – Andrew McKeighan Feb 06 '17 at 16:12