2013-06-18 3 views
29

noobness noobness으로 보내주십시오, MVC 패턴에 초보자입니다. 나는 내 사이트에 등록 된 사용자에 대한 프로필 정보 페이지를 구축하고MVC 4 - 부분보기에서 다른 모델 사용

할 노력하고있어 무엇

. 이 페이지는 생년월일, 전화 번호, 가입 상태 등과 같은 사용자에 관한 데이터를 나열합니다. 아이디어를 얻습니다. 또한 사용자가 암호, 전자 메일 주소, 개인 정보를 같은 페이지에 바꿀 수있는 양식을 갖고 싶습니다.

내 문제는 사용자의 데이터가 전달 된 모델 변수를 통해 내 컨트롤러에서 오는

:

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을 사용합니다. 그래서 basiccaly 나는 정보를 출력하기위한 것과 데이터를 게시하기위한 두 가지 모델을 사용해야합니다.

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

     @Html.Partial("_ModifyProfileInfo") 
    } 

다음 부분보기입니다 :

여기

The model item passed into the dictionary is of type 'Applicense.Models.User', but this dictionary requires a model item of type 'Applicense.Models.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; } 
    } 
: 마침내 여기
@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입니다

나는 뭔가를 놓친 것입니까? 이 작업을 수행하는 적절한 방법은 무엇입니까?

편집 : Nikola Mitev의 대답을 반영하는 코드를 다시 작성했지만 지금은 또 다른 문제가 있습니다. 다음은 내가 얻은 오류입니다.

Object reference not set to an instance of an object. (@Model.UserObject.LastName)

변경된 전자 메일 주소 값을 게시 할 때만 발생합니다. 여기 내 뷰 모델 (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... 

I 모델이 있기 때문에 무슨 일이 일어나고 생각하고 있어요 각 required 열의 데이터를 데이터베이스에 저장하려고합니다.

Edit2가 : 내하기 Profil 조치의 httppost 방법 :

컨트롤러에 정의 된대로 ViewData를 보낼 수 있습니다 @Html.Partial의 과부하가있다
[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); 
      } 
     } 

답변

35

이러한 상황이 사용하고 프로필 컨트롤러에 뷰 모델을 전달하는 것입니다 처리하는 최선의 방법으로, 뷰 모델은보기에 전달하려는 여러 개체에 대한 래퍼 클래스입니다.

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); 
} 

그리고보기 : 당신의 [HttpPost] PROFIL 기능에서

@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> 
} 
+2

감사합니다 당신을 위해 쉽게 사용할 수있게, 마치 마법처럼 작동합니다! :) +1 또한 아주 잘 쓰여진 답. – PeterInvincible

+0

다른 오류가 발생했습니다 : (나는 그것을 반영하기 위해 질문을 편집했습니다. – PeterInvincible

+0

@Tharline은 성함 필드에 값을 가져 오는 특정 레코드가 있습니까? –

13

이 - 이것이 내가 일반적으로 사용하는 방법입니다 부분보기. 컨트롤러에서 ViewData["mypartialdata"]ViewDataDictionary으로 정의하십시오. 그런 다음보기

@Html.Partial("_ModifyProfileInfo",ViewData["mypartialdata"]) 
1

, modelstate.isvalid이 false 인 경우, 당신은 당신의 편집보기를 반환하지만, pmViewModel을 다시 정의해야합니다. 다른 부분보기에는 표시 할 개체가 없습니다. 다음을 사용하여 어떤 일이 일어 났는지 알려주십시오.

[HttpPost] 
[Authorize] 
[ValidateAntiForgeryToken] 
public ActionResult Profil(ProfileModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     //insert into database 
     return Content("everything's good"); 
    } 
    else 
    { 
     //outputs form errors 
     var pmViewModel = new ProfileUserViewModel 
     { 
      ProfileModelObject = profileModel, 
      UserModelObject = userModel 
     }; 

     return View(model); 
    } 
} 
+0

감사합니다! 실제로보기가 반환되기 전에 pmViewModel을 넣어야했습니다. – PeterInvincible

+0

당신은'pmViewModel'을 선언하고 있으며 결코 사용되지 않습니다. 맞습니까? – SharpC

0

나는이 질문이 오랜 전에 제기되었지만 어떤 사람들은 여전히 ​​비슷한 문제에 직면 할 수 있음을 알고 있습니다. 하나의 페이지에 하나 이상의 뷰 모델을 전달하거나 사용하는 쉬운 솔루션은 ViewBag를 사용하여 두 번째 객체를 잡고 뷰에서 참조하는 것입니다. 아래 예제를 참조하십시오. 컨트롤러에서

이 작업을 수행 :

Obj2 personalDets = new Obj2(); 
DbContext ctx = new DbContext(); 
var details = ctx.GetPersonalInformation; 

foreach(var item in details) { 
    personalDets.Password = item.Password; 
    personalDets .EmailAddress = item.EmailAddress; 
} 

ViewBag.PersonalInformation = personalDets; 

그런 다음보기에 이러한 속성이