Bodhi
Bodhi

Reputation: 354

Update few changed fields MVC 3 project

I making a MVC 3 website that allows users to register and buy stuff online. I'm using EF for all DB operations. My implementation for the user class is as follows

public class User
{
    [HiddenInput(DisplayValue = false)]
    public long UserID { get; set; }

    [Required(ErrorMessage = "Please enter a first name")]
    [Display(Name="First Name")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Please enter a last name")]
    [Display(Name="Last Name")]
    public string LastName { get; set; }

    [Required(ErrorMessage = "Please enter an Email")]
    [RegularExpression(".+\\@.+\\..+", ErrorMessage="Please enter a valid email")]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required(ErrorMessage = "Please enter a phone number")]
    [Display(Name = "Phone Number")]
    public string PhoneNumber { get; set; }

    [Required(ErrorMessage = "Please enter a value for address line 1")]
    [Display(Name = "Address Line 1")]
    public string AddressLine1 { get; set; }

    [Required(ErrorMessage = "Please enter a value for address line 2")]
    [Display(Name = "Address Line 2")]
    public string AddressLine2 { get; set; }

    [Required(ErrorMessage = "Please enter a city")]
    [Display(Name = "City")]
    public string City { get; set; }

    [Required(ErrorMessage = "Please enter a country")]
    [Display(Name = "Country")]
    public string Country { get; set; }

    [Required(ErrorMessage = "Please enter a login name")]
    [Display(Name = "Your Login Name")]
    public string UserName { get; set; }

    [Required(ErrorMessage = "Please enter a password")]
    [DataType(DataType.Password)]
    [Compare("Password")]
    [Display(Name = "Your Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Compare("Password", ErrorMessage="Passwords do not match")]
    [System.ComponentModel.DataAnnotations.Schema.NotMapped]
    [Display(Name = "Confirm Password")]
    public string ConfirmPassword { get; set; }
}

Now the problem I'm facing is while updating the user details. I want that I will present two different pages for updating details. One for changing password and the other for changing other details. But, the problem is when I'm creating a view to enable edit for other details, the validations for password fire and don't allow me to save the data. I want that the data for the fields, which have not been displayed, are the same as the ones stored in the DB.

Please help me in this, also, since this is my first question here, please tell me about anything else that you will need to solve my problem. Below is the code for the user controller edit action:

 public ViewResult Edit(int userId)
    {
        User user = repository.Users.Where(x => x.UserID == userId).Select(x => x).FirstOrDefault();
        user.UserName = repository.Users.Where(x => x.UserID == userId).Select(x => x.UserName).FirstOrDefault();
        return View(user);
    }

    [HttpPost]
    public ActionResult Edit(User user)
    {
        //user.Password = repository.Users.Where(u => u.UserName.Equals(user.UserName)).Select(p => p.Password).FirstOrDefault().ToString();
        user.ConfirmPassword = user.Password;

        if (ModelState.IsValid)
        {
            repository.AddUser(user, "Edit");
            TempData["message"] = string.Format("{0} has been saved", (user.FirstName+ " " +user.LastName));
            return RedirectToAction("ListUsers", "User");
        }
        else
        {
            return View(user);
        }
    }

Here is the code for the View for editing the user

@model SportsStore.Domain.Entities.User

@{
    ViewBag.Title = "Edit User";
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}

<h2>Edit @Model.FirstName @Model.LastName</h2>

@Html.ValidationSummary()

@using (Html.BeginForm("Edit", "User", FormMethod.Post))
{

<table class="Grid">
    <tr>
        <td>First Name</td>
        <td>@Html.EditorFor(x => x.FirstName)</td>
    </tr>
    <tr>
        <td>Last Name</td>
        <td>@Html.EditorFor(x => x.LastName)</td>
    </tr>
    <tr>
        <td>Email</td>
        <td>@Html.EditorFor(x => x.Email)</td>
    </tr>
    <tr>
        <td>Phone Number</td>
        <td>@Html.EditorFor(x => x.PhoneNumber)</td>
    </tr>
    <tr>
        <td>Address Line 1</td>
        <td>@Html.EditorFor(x => x.AddressLine1)</td>
    </tr>
    <tr>
        <td>Address Line 2</td>
        <td>@Html.EditorFor(x => x.AddressLine2)</td>
    </tr>
    <tr>
        <td>City</td>
        <td>@Html.EditorFor(x => x.City)</td>
    </tr>
    <tr>
        <td>Country</td>
        <td>@Html.EditorFor(x => x.Country)</td>
    </tr>
</table>
@*Html.EditorFor(x => x.UserName)
@Html.PasswordFor(x => x.Password)
@Html.HiddenFor(x => x.ConfirmPassword)

@*{Model.ConfirmPassword = Model.Password;}*@

<input type="submit" value="Save" />
if (User.Identity.Name.Equals("admin", StringComparison.OrdinalIgnoreCase))
{
    @Html.ActionLink("Cancel and return to User List", "ListUsers");
}
else
{
    @Html.ActionLink("Cancel and return to User List", "List", "Product");
}
}

Upvotes: 0

Views: 204

Answers (1)

Fals
Fals

Reputation: 6839

You should split this into ViewModels, one containing User login information, UserLoginViewModel and UserInfoViewModel, containing only other User information. Just add to each model only required properties for update, for exemple the UserLoginModelo below:

public class UserLoginViewModel
{
  [HiddenInput(DisplayValue = false)]
  public long UserID { get; set; }

  [Required(ErrorMessage = "Please enter a password")]
  [DataType(DataType.Password)]
  [Compare("Password")]
  [Display(Name = "Your Password")]
  public string Password { get; set; }

  [DataType(DataType.Password)]
  [Compare("Password", ErrorMessage="Passwords do not match")]
  [System.ComponentModel.DataAnnotations.Schema.NotMapped]
  [Display(Name = "Confirm Password")]
  public string ConfirmPassword { get; set; }
}

Then, create strongly typed views based on this models. The controllers should expect each view model, then you can map every single atributte to the real User object and then save all changes:

View:

@model SportsStore.Domain.Entities.UserLoginViewModel 

Controller:

[HttpPost]
public ActionResult Edit(UserLoginViewModel user)
{
   //Retrieve the user and map every updated property to the original User
}

[HttpPost]
public ActionResult Edit(UserInfoViewModel user)
{
   //Retrieve the user and map every updated property to the original user
}

Upvotes: 2

Related Questions