2017-01-11 16 views
0

名前(一意かつ必須)パスワード(必須)およびプロフィール(必須)。プロファイルクラスには固有の名前が必要な名前があります。どちらのクラスも、最初にコードを使用してデータベースを生成する際に主キーとして機能するIDを持っています。エンティティAはエンティティBに依存し、エンティティBのすべての情報をエンティティAのPOST作成メソッドにMVCコードを使用して送信する方法

私は私のページで、新規ユーザーを作成できるようにしたい、ここでこれを行うにはいくつかのコードは次のとおりです。

コントローラ

 // GET: Users/Create 
    public ActionResult Create() 
    { 
     populateViewBagWithProfilesAsSelectListItem(); 
     return View(); 
    } 

    private void populateViewBagWithProfilesAsSelectListItem() 
    { 
     IEnumerable<SelectListItem> profiles = db.Profiles.ToList(). 
      Select(x => new SelectListItem 
      { 
       Value = x.Id.ToString(), 
       Text = x.Name 
      }); 
     ViewBag.Profiles = profiles; 
    } 

    // POST: Users/Create 
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 
    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Create([Bind(Include = "Name,Password,Profile")] User user) 
    { 
     user.Profile = db.Profiles.Find(user.Profile.Id); 
     ModelState.Clear(); 
     TryValidateModel(user); 
     lock (UsersLocker) 
     { 
      if (ModelState.IsValid) 
      { 
       db.Users.Add(user); 
       db.SaveChanges(); 
       return RedirectToAction("Index"); 
      } 
     } 

     populateViewBagWithProfilesAsSelectListItem(); 
     return View(user); 
    } 

ビュー

@model ProceduresRecord.Web.MVC.Models.User 

@{ 
    ViewBag.Title = "Crear"; 
} 

<h2>@ViewBag.Title</h2> 


@using (Html.BeginForm()) 

{ 
@Html.AntiForgeryToken() 

<div class="form-horizontal"> 
    <h4>Usuario</h4> 
    <hr /> 
    @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } }) 
      @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } }) 
      @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Profile, htmlAttributes: new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.DropDownListFor(model => model.Profile.Id, (IEnumerable<SelectListItem>)ViewBag.Profiles, htmlAttributes: new { @class = "form-control" }) 
      @Html.ValidationMessageFor(model => model.Profile.Name, "", new { @class = "text-danger" }) 
     </div> 
    </div> 

    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input type="submit" value="Crear" class="btn btn-default" /> 
     </div> 
    </div> 
</div> 
} 

<div> 
    @Html.ActionLink("Volver a la Lista", "Index") 
</div> 

を作成します。このページの結果:

あなたは、私がデータベースからプロファイルを読み込む見ることができるように、彼は1をピックアップし、そのプロファイルのIDはPOSTメソッドに送信され、作成上のクリックした後

Create user View

は、私は、ユーザーにプロファイル名が表示さで作成しますコントローラ。それから、私は提供されたIDを使用してデータベースから完全なプロファイルを取得するために苦労し、ユーザーに完全なプロファイルを割り当て、ModelStateを検証します(実際に変更されるように...プロファイルに名前がない今まで)。 それはすべて動作するようですが、私は不思議に思っていた...

これを行うには良い方法はありませんか?私は一発でPOSTにプロフィールを送信し、このコードを避けるためにできることは素晴らしいではないでしょう、選択したHTMLを取り込むとき、私はすでにデータ・ベースからプロファイルを得た、意味:

 user.Profile = db.Profiles.Find(user.Profile.Id); 
     ModelState.Clear(); 
     TryValidateModel(user); 

場合何らかの方法があります、教えてください!

P.D:私はMVCとコードファーストを自分で学習しようとしていますが、アドバイスをいただければ幸いです。

+0

特に編集時に、ビューでデータモデルを使用しないでください。 'Name'、Password'、' SelectedProfile'のプロパティを表示するモデルを作成します - CodingYoshiの回答を参照してください(質問の最後の3行は必要ありません) –

答えて

1

ModelStateのエラーが不明です。しかし、おそらくあなたのUser enitityにはProfileIdと呼ばれる財産があるはずです。そうでない場合は、おそらく追加する必要があります。そして、次に、あなたのBind(Include)ProfileIdにアクションを作成し、作成アクションはちょうどそれが私だったら、私は思います

// POST: Users/Create 
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see http://go.microsoft.com/fwlink/?LinkId=317598. 
[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Create([Bind(Include = "Name,Password,ProfileId")] User user) 
{ 
    lock (UsersLocker) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Users.Add(user); 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
    } 

    populateViewBagWithProfilesAsSelectListItem(); 
    return View(user); 
} 

ことができるのでProfileを変更

@Html.DropDownListFor(model => model.ProfileId, (IEnumerable<SelectListItem>)ViewBag.Profiles, htmlAttributes: new { @class = "form-control" }) 

にあなたのビュープロファイルドロップダウンを変更することができますID、名前、パスワード、およびProfileIdプロパティを持つ新しいビューモデルクラスUserViewModelを作成し、ビューに前後に渡します。

+0

ありがとう、それはまさに私の間違いでした。私のUserのProfileタイプのプロパティであるが、int型のProfileIdが見つからなかったので、私は両方とも持っていなければならないということを知らなかった...私はEFがそれらの2つのプロパティ。とても有難い! – Loaderon

2

ユーザーを作成するときは、ProfileのIDはProfileにする必要はありません。したがって、ユーザー情報とProfile IDを投稿するだけで済みます。新しいユーザーを作成してProfile Idプロパティを設定すると、EFがそれを把握します。そのキーにプロファイルが存在する場合はそれを使用します。それ以外の場合は、提供された外部キーを持つアイテムを見つけることができないという不満があります。

また、私は次のようになりますビュー用のモデル作成します。各SelectListItemは次のように作成することができ

public class UserModel 
{ 
    public string UserName { get; set; } 
    public string Password { get; set; } 

    // This will be the selected profile id 
    public string SelectedProfileId { get; set; } 

    // fill this with all the profiles 
    public IEnumerable<SelectListItem> AvailableProfiles { get; set; } 
} 

を:あなたのコントローラで

new SelectListItem 
    { 
     Value = ProfileId, // Whatever the property is 
     Text = ProfileName, // this will be displayed in dropdown 
    }); 

は、そのインスタンスを作成し、それをあなたの意見に送ってください。あなたのビューで

は次のようにドロップダウンを作成します。

@Html.DropDownListFor(m => m.SelectedProfileId, 
       new SelectList(m.AvailableProfiles)), 
       "Select Profile") 

が続いてポストに SelectedProfileIdプロパティから選択したプロファイルIDを取得します。

+0

'Selected = true'を設定すると、モデルプロパティにバインドするとき(何が選択されたかを決定する' SelectedProfileId'の値なので 'DropDownListFor()'メソッドで無視されます)、それ以外の場合は正しいアプローチです –

+0

@StephenMueckeはチップをありがとう。編集された答え。 – CodingYoshi

+0

ありがとうございました!たとえJamieD77の答えが私の知識不足に適していたとしても、あなたは非常に役に立つと答えました。ビューモデルの使い方はわかりませんでしたが、非常に簡単で強力でした。ありがとう! – Loaderon

関連する問題