2016-03-27 36 views
-1

我在创建操作时遇到了Post Controller的一些问题。以下是我的模型,圆形,材质,MaterialShape,RawMaterial。我的主要目标是将Round对象添加到数据库。ViewModel DropDownList和HTTP Post Controller

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

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

抽象类材料形状

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


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

回合从MaterialShape

[Table("Rounds")] 
public class Round : MaterialShape 
{ 
    [Required] 
    [Display(Name="Outside Diameter")] 
    public double OuterDiameter { 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; } 
} 

控制器创建操作

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

创建视图

@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

正如你可以看到我完成了获取列表数据库。我在将Viewmodel转换回Create [Post]操作中的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参数设置正确吗?我是否将我的selecteditem正确地转换为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仍然是错误的。我认为我们在这里仍然缺少一些东西。

+0

在公众的ActionResult创建((VMRoundMaterial视图模型),是你的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) 

旁注:你在POST方法使用roundmaterial.Material.ID = viewmodel.MaterialId;可能会抛出一个NullReferenceException因为你还没有初始化属性Material

0

如果我理解正确的问题:尝试在POST方法来改变VMRoundMaterial到ModelDTO,其中modeldto这样定义:

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

检查,如果现在你会得到适当补充水分模型。

+0

本例中的ModelDTO是圆形的圆形是从MaterialShape继承的,MaterialShape具有材质类型的属性见上。使用MaterialID作为数据模型中的键而不是材质类型/对象。也许我的对象是pro blem。 – dev8989

+0

您将无法获得材料的集合。 ViewModel!= DTO模型。请注意,在HTML中,您只能找到一个带有MaterialD的,并且正在获取它,如屏幕截图所示。为了获得你需要重新生成它的材料清单。代码是正确的。 – jstadnicki

+0

因此,从数据库中重新生成列表,然后将其保存为材质类型?为什么ModelState.IsValid =“false”? – dev8989