iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
SideProject30

我想自己刻部落格系列 第 28

個人資料變更 UpdateUser

  • 分享至 

  • xImage
  •  

原本今天要把 UpdateUser 動作與頁面與側邊欄一起做完,不過時間來不及,所以先做 UpdateUser。

側邊欄我考慮很久,需不需要直接用文章來呈現,這樣照片、自介的位置可以自己編輯,甚至可以用編輯器插入 Html。不過想來想去有點麻煩,還是用 User 資料來實作。

所以資料庫的 User 資料表,我新增了 ImageAbout 兩個欄位。

public partial class User
{
    ......

    public string Image { get; set; }

    public string About { get; set; }
}

所以在 UserService 中的 Create 與 Update 都要做相應的調整。都要加上 ImageAbout 兩個欄位。

user.Image = viewModel.Image;
user.About = viewModel.About;

此外,因為我們的密碼有做雜湊,我在實做的過程中發現,UserViewModel 不能重複用在 Update 的時候。所以拆成 UserUpdateViewModel 和 UserCreateViewModel 。 UpdateUser 的時候不做變更密碼。
其中 ImageAbout 屬性設定為 string? , 因為發現有 Nullable 設定的關係, string 需要明確宣告 string? 才可以空白不填,後面轉換成 User 時再設為 string.Empty 就可以了。

public class UserCreateViewModel : UserBaseViewModel
{
    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; } = string.Empty;

    [Compare(nameof(Password))]
    [DataType(DataType.Password)]
    public string PasswordCheck { get; set; } = string.Empty;
}

public class UserUpdateViewModel : UserBaseViewModel
{
}

public class UserBaseViewModel : IValidatableObject
{
    public int Id { get; set; }

    [Required]
    [EmailAddress]
    public string Email { get; set; } = string.Empty;

    [Required]
    public string Name { get; set; } = string.Empty;

    [Required]
    public string DisplayId { get; set; } = string.Empty;

    public string? Image { get; set; }
    public string? About { get; set; }
    public int Role { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (string.IsNullOrWhiteSpace(Email))
        {
            yield break;
        }

        var userRepository = validationContext.GetService<IUserRepository>();
        var emailUser = userRepository.Query(x => x.Email == Email).FirstOrDefault();
        if (emailUser is not null && emailUser.Id != Id)
        {
            yield return new ValidationResult("此 Email 已存在", new[] { nameof(Email) });
        }

        var displayIdUser = userRepository.Query(x => x.DisplayId == DisplayId).FirstOrDefault();
        if (displayIdUser is not null && displayIdUser.Id != Id)
        {
            yield return new ValidationResult("此 DisplayId 已存在", new[] { nameof(DisplayId) });
        }
    }
}

在 User 與 ViewModel 轉換的方面,我改用擴充方法來實作轉換

public static User ToUser(this UserCreateViewModel model)
{
    var user = new User();
    user.Id = model.Id;
    user.Name = model.Name;
    user.Email = model.Email;
    user.Password = model.Password;
    user.DisplayId = model.DisplayId;
    user.Image = model.Image ?? string.Empty;
    user.About = model.About ?? string.Empty;
    user.Role = model.Role;
    user.CreateDate = new DateTime();
    user.UpdateDate = user.CreateDate;

    return user;
}

public static UserUpdateViewModel ToUserUpdateViewModel(this User user)
{
    var model = new UserUpdateViewModel();
    model.Id = user.Id;
    model.Name = user.Name;
    model.Email = user.Email;
    model.DisplayId = user.DisplayId;
    model.About = user.About;
    model.Image = user.Image;
    model.Role = user.Role;

    return model;
}

實作 UpdateUser 的 Controlller Action

在 AdminController 下面實作 UpdateUser Action 如下,目前做了登入功能,所以 UserId 可以從 Cookie 拿取。

public async Task<IActionResult> UpdateUser()
{
    var user = await _userService.GetAsync(User.GetUserId());
    return View(user.ToUserUpdateViewModel());
}

[HttpPost]
public async Task<IActionResult> UpdateUser(UserUpdateViewModel user)
{
    user.Id = User.GetUserId();
    await _userService.UpdateAsync(user);
    return RedirectToAction("Index", "Home");
}

我在 ClaimsPrincipal 型別上面,定義了擴充方法,來幫助我取得 Cookie 中的 UserId

public static class ClaimsPrincipalExtenstions
{
    public static int GetUserId(this ClaimsPrincipal claims)
    {
        if (claims.Identity.IsAuthenticated)
        {
            var idStr = claims.FindFirstValue(nameof(User.Id));
            if (int.TryParse(idStr, out int id))
            {
                return id;
            }
        }

        return 0;
    }
}

最後檢視的部分一樣使用樣板產生器產生。

https://ithelp.ithome.com.tw/upload/images/20231013/201204207YBhAE261F.png

最後實際程式碼以 GitHub 上為主。


上一篇
建立註冊、登入、登出
下一篇
側邊欄實作,文章排序、路由調整
系列文
我想自己刻部落格31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言