私noobnessに耐えてください、私は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を使用します。基本的に、ビューでは2つのモデルを使用する必要があります。1つは情報の出力用、もう1つはデータの投稿用です。部分的なビューを使用してこれを達成できると思いましたが、このエラーが発生します:
ディクショナリに渡されるモデルアイテムのタイプは「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; }
}
何か不足していますか?これを行う適切な方法は何ですか?
編集:ニコラ・ミテフの答えを反映してコードを作り直しましたが、今は別の問題があります。ここに私が得るエラーがあります:
オブジェクト参照がオブジェクトインスタンスに設定されていません。 (@ 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:プロファイルアクションの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>
}
コントローラで定義されているViewData
を送信できる@Html.Partial
のオーバーロードがあります。これは、私が通常部分ビューに使用する方法です。コントローラーでViewData["mypartialdata"]
をViewDataDictionary
として定義します。その後、あなたの意見で
@Html.Partial("_ModifyProfileInfo",ViewData["mypartialdata"])
[HttpPost]
profil関数で、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);
}
}
私はこの質問がずっと前に聞かれたことを知っていますが、一部の人々はまだ同様の問題に直面しているかもしれません。 1つのページに複数のビューモデルを渡すまたは使用する簡単な解決策の1つは、ViewBagを使用して2番目のオブジェクトを保持し、ビュー内でそれを参照することです。以下の例を参照してください。
コントローラーでこれを行います:
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;
その後、ビューでこれらのプロパティがすぐに利用可能になります