Asp.net

MVC 4 - 在局部視圖中使用不同的模型

  • June 18, 2013

請忍受我的菜鳥,我對 MVC 模式非常陌生。

我正在嘗試做的事情

我正在為我的網站上的註冊使用者建構個人資料資訊頁面。此頁面將列出有關使用者的數據,例如出生日期、電話號碼、訂閱狀態等。你明白了。我還想有一個表格讓使用者在同一頁面上更改他們的密碼、電子郵件地址、個人資訊。

我的問題

使用者的數據通過傳遞的模型變數來自我的控制器:

public ActionResult Profil()
       {
           var model = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
           return View(model);
       }

在我看來,輸出如下所示:

<label>Phone number: </label>
           @if (Model.PhoneNumber != null)
                   {
                       @Model.PhoneNumber
                   }
                   else
                   {
                       <span class="red">You haven't set up your phone number yet. </span>
                   }

使用者可以更改其資訊的表單將使用另一個模型 ProfileModel。所以基本上我需要在我的視圖中使用兩個模型,一個用於輸出資訊,一個用於發布數據。我認為使用局部視圖可以實現此目的,但出現此錯誤:

傳入字典的模型項的類型為“Applicense.Models.User”,但此字典需要“Applicense.Models.ProfileModel”類型的模型項。

這是我對局部視圖的呼叫如下所示:

@using (Html.BeginForm())
   {
       @Html.AntiForgeryToken()
       @Html.ValidationSummary()

       @Html.Partial("_ModifyProfileInfo")
   }

這是部分視圖:

@model Applicense.Models.ProfileModel
<ul>
   <li>
       @Html.LabelFor(m => m.Email)
       @Html.EditorFor(m => m.Email)
   </li>
   <li>
       @Html.LabelFor(m => m.ConfirmEmail)
       @Html.EditorFor(m => m.ConfirmEmail)
   </li>
   <input type="submit" value="Update e-mail" />
</ul>

最後是我的 ProfileModel:

public class ProfileModel
   {
       [Required]
       [DataType(DataType.EmailAddress)]
       [Display(Name = "New e-mail address")]
       public string Email { get; set; }

       [DataType(DataType.EmailAddress)]
       [Display(Name = "Confirm new e-mail address")]
       [Compare("Email", ErrorMessage = "The e-mail and it's confirmation field do not match.")]
       public string ConfirmEmail { get; set; }
   }

我錯過了什麼嗎?這樣做的正確方法是什麼?

編輯: 我重新編寫了反映 Nikola Mitev 答案的程式碼,但現在我遇到了另一個問題。這是我得到的錯誤:

你呼叫的對像是空的。(@Model.UserObject.LastName)

這僅在我發布更改的電子郵件地址值時發生。這是我的 ViewModel (ProfileModel.cs):

public class ProfileModel
   {
       public User UserObject { get; set; }

       [Required]
       [DataType(DataType.EmailAddress)]
       [Display(Name = "Új e-mail cím")]
       public string Email { get; set; }

       [DataType(DataType.EmailAddress)]
       [Display(Name = "Új e-mail cím megerősítése")]
       [Compare("Email", ErrorMessage = "A két e-mail cím nem egyezik.")]
       public string ConfirmEmail { get; set; }

       [DataType(DataType.EmailAddress)]
       [Display(Name= "E-mail cím")]
       public string ReferEmail { get; set; }
   }

控制器:

public ActionResult Profil()
       {
           var User = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);

           var ProfileViewModel = new ProfileModel
           {
               UserObject = User
           };

           return View(ProfileViewModel);
       }

最後這是我的user.cs模型課:

[Table("UserProfile")]
   public class User
   {
       [Key]
       [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
       public int UserId { get; set; }
       [Column("UserName")]
       public string UserName { get; set; }
       [Column("Email")]
       [Required]
       public string Email { get; set; }
       [Column("FirstName")]
       public string FirstName { get; set; }
       [Column("LastName")]
       public string LastName { get; set; }
       [Column("PhoneNumber")]
       public string PhoneNumber { get; set; }
... You get the idea of the rest...

我認為它正在發生,因為模型試圖將每required列中的數據放入數據庫中。

Edit2: 我的 Profil 操作的 httppost 方法:

[HttpPost]
       [Authorize]
       [ValidateAntiForgeryToken]
       public ActionResult Profil(ProfileModel model)
       {
           if (ModelState.IsValid)
           {
//insert into database
               return Content("everything's good");
           }
           else
           {
//outputs form errors
               return View(model);
           }
       }

處理這種情況的最佳方法是使用 viewModel 並將其傳遞給 Profile 控制器,viewModel 是要傳遞給視圖的多個對象的包裝類。

public class ProfileUserViewModel
{
  public ProfileModel ProfileModelObject {get; set;}
  public UserModel  UserModelObject {get; set;}
}   

您的控制器應如下所示:

public ActionResult Profil()
{            
   var profileModel = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
   var userModel = //fetch from db.

   var pmViewModel = new ProfileUserViewModel  
                         {
                             ProfileModelObject = profileModel,
                             UserModelObject = userModel
                         };

  return View(pmViewModel);
}

最後你的觀點:

@model Applicense.Models.ProfileUserViewModel

<label>Phone number: </label>

@if (Model.ProfileModelObject.PhoneNumber != null)
{
  @Model.PhoneNumber
}
else
{
   <span class="red">You haven't set up your phone number yet. </span>
}

引用自:https://stackoverflow.com/questions/17173204