2016-03-27 21 views
-1

投稿アクションのポストコントローラに問題があります。以下は、私のモデル、ラウンド、マテリアル、マテリアルシェイプ、ローマテリアルです。私の主な目的は、Roundオブジェクトをデータベースに追加することです。ViewModel DropDownListとHTTPポストコントローラ

public class Material 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ID { get; set; } 

    [Required] 
    [Display(Name="Material")] 
    public string MaterialName { get; set; } 
} 

材質のための抽象クラスは、私はビューにすべての材料を持って作成されたビューモデルをラウンド以下

[Table("Rounds")] 
public class Round : MaterialShape 
{ 
    [Required] 
    [Display(Name="Outside Diameter")] 
    public double OuterDiameter { get; set; } 
} 

MaterialShape

からクラスを継承

public abstract class MaterialShape 
{ 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 


    [Required] 
    public virtual Material Material { get; set; } 
} 

をされる形状。私は、IEnumerableを使用して、すべての異なる材料をデータベースから取り出しました。選択したアイテムを保持するためのMaterialIdも含まれています。

public class VMRoundMaterial 
{ 
    public Round Round { get; set; } 

    [Display(Name="Material")] 
    public IEnumerable<SelectListItem> Materials { get; set; } 

    public int MaterialId { get; set; } 
} 

コントローラあなたは私がデータベースにリストを取得達成見ることができるように表示

@model SetupSheet.Models.ViewModel.VMRoundMaterial 

@{ 
ViewBag.Title = "Create"; 
} 

<h2>Create</h2> 


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

<div class="form-horizontal"> 
    <h4>Round</h4> 
    <hr /> 
    @Html.ValidationSummary(true) 

    <div class="form-group"> 
     @Html.LabelFor(model => model.Round.OuterDiameter, new { @class = "control-label col-md-2" }) 

     <div class="col-md-10"> 
      @Html.EditorFor(model => model.Round.OuterDiameter) 
      @Html.ValidationMessageFor(model => model.Round.OuterDiameter) 


     </div> 
    </div> 
    <div class="form-group"> 
     @Html.LabelFor(model => model.Materials, new { @class = "control-label col-md-2" }) 
     <div class="col-md-10"> 
      @Html.DropDownListFor(m => m.MaterialId, Model.Materials) 
     </div> 
    </div> 

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

    <div> 
    @Html.ActionLink("Back to List", "Index") 
    </div> 

@section Scripts { 
@Scripts.Render("~/bundles/jqueryval") 
} 

Round Create View with Combobox from Database

を作成アクション

public ActionResult Create() 
     { 
     var model = new VMRoundMaterial(); 
     using (var db = new DbContext()) 
     { 
      model.Materials = db.Materials.ToList().Select(x => new SelectListItem 
      { 
       Value = x.ID.ToString(), 
       Text = x.MaterialName 
      }); 
     } 
     return View(model); 
    } 

を作成します。 ViewModelをCreate [Post] ActionのDatamodelに変換する際に問題があります。

[HttpPost] 
    public ActionResult Create(VMRoundMaterial viewmodel) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 
       Round roundmaterial = new Round(); 

       roundmaterial.OuterDiameter = viewmodel.Round.OuterDiameter; 
       roundmaterial.Material.ID = viewmodel.MaterialId; 
       db.Rounds.Add(roundmaterial); 
       db.SaveChanges(); 
      } 

      return RedirectToAction("Index"); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 

Viewmodel null マイ[HttpPost]が正しく機能していません。私はそれを正しく設定しましたか? DropDownListForパラメータは正しく設定されていますか?選択したアイテムをRoundオブジェクトに正しく変換しましたか?何らかの理由でModelState.IsValidがfalseに返されています。これを引き起こした原因は何ですか? コードは

roundmaterial.Material.ID = viewmodel.MaterialId; 

データベース接続が動作しているに失敗しているが、私は結果には届きません。私は他の戦略を見つけることができます。

jstadnicki提案された解決策

[HttpPost] 
    public ActionResult Create(ModelDTO viewmodel) 
    { 
     try 
     { 
      if (ModelState.IsValid) 
      { 

       Round roundmaterial = new Round(); 

       roundmaterial.OuterDiameter = viewmodel.Round.OuterDiameter; 
       roundmaterial.Material.ID = viewmodel.MaterialId; 

       db.Rounds.Add(roundmaterial); 
       db.SaveChanges(); 
      } 

      return RedirectToAction("Index"); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 

ModelDTO Values

ModelState.IsValid = "false"

あなたにはModelDTOを使用したいが、私はまだ問題を抱えている理由を私は理解しています。

ModelStateはまだfalseです。私はまだここに何かが欠けていると思う。

+0

((VMRoundMaterialののviewmodel)を作成し、ある初期化されていないため、POSTメソッドでroundmaterial.Material.ID = viewmodel.MaterialId;のご使用は可能性の高いNullReferenceExceptionがスローされますあなたのviewModel null? –

+0

viewmodelはnullではありません。上記で編集した写真を参照してください。 – dev8989

答えて

1

ModelStateは、ビューモデル(Round)でデータモデルを使用し、必要なMaterialプロパティの値をポストバックしないため無効です。

一般的には、編集データのビューモデルは、データモデルのプロパティ、およびビューを含めるべきではありません

public class VMRoundMaterial 
{ 
    [Required] 
    [Display(Name="Outside Diameter")] 
    public double OuterDiameter { get; set; } 
    [Display(Name="Material")] 
    public int MaterialId { get; set; } 
    public IEnumerable<SelectListItem> Materials { get; set; } 
} 

注意する必要がありますまた、あなたの表示属性は、作成するためにint MaterialId、ないIEnumerable<SelectListItem> Materialsにする必要がありますMaterialIdに関連付けられたラベル(現在、「ラベル」をクリックすると、<select>要素にフォーカスが設定されません)。その後、ビューには、サイドノートが

@Html.LabelFor(m => m.OuterDiameter) 
@Html.EditorFor(m => m.OuterDiameter) 
@Html.ValidationMessageFor(m => m.OuterDiameter) 

@Html.LabelFor(m => m.MaterialId) 
@Html.DropDownListFor(m => m.MaterialId, Model.Materials) 
@Html.ValidationMessageFor(m => m.MaterialId) 

次のようになります。あなたが公共のActionResultで財産Material

0

私が正しくあなたの問題を理解していれば:modeldtoは、次のように定義されてModelDTOにPOSTメソッドでVMRoundMaterialを変更しよう:

public class ModelDTO 
{ 
    public Round Round {get;set;} 
    public int MaterialId { get; set; } 
} 

チェック今あなたが適切に水和モデルを取得するかどうか。

+0

ModelDTOはRoundです。RoundはMaterialShapeから継承されています。MaterialShapeはMaterialタイプのMaterialのプロパティを持っています。マテリアルタイプ/オブジェクトの代わりにデータモデルのキーとしてMaterialIDを使用します。おそらく私のオブジェクトはプロです傷み。 – dev8989

+0

あなたは資料のコレクションを取得しません。 ViewModel!= DTOモデル。 HTML上ではとMaterialDが1つしか見つかりません。スクリーンショットに示されているように、あなたはそれを入手しています。マテリアルのリストを取得するには、自分でそれを再生成する必要があります。コードは正しいです。 – jstadnicki

+0

データベースからリストを再生成し、マテリアルタイプとして保存しますか?なぜModelState.IsValid = "false"ですか? – dev8989