2015-03-25 48 views
0

我有一個實體6框架的MVC5項目,我無法獲得正確的信息傳遞給帖子上的編輯操作,以便將其綁定到模型。我的viewModel的ModelState返回無效。我不知道我錯過了什麼。我猜測它與編輯器模板的設置方式以及模型的結構有關,但我需要一些幫助來解決它。我花了好幾個小時改變了一些東西,試圖讓它起作用,我仍然無法解決問題。MVC5 ModelView在編輯操作後無效

我的視圖模型:

namespace CommunityHealth.Models.ViewModels 
{ 
    public class ActivityViewModel 
    { 
     public virtual IList<JunctionTypeAction> junctionTypeActions{ get; set; } 
     public virtual IList<JunctionDepartmentAction> junctionDepartmentActions{ get; set; } 
     public virtual IList<JunctionPopulationAction> junctionPopulationActions { get; set; } 
     public virtual CommunityAction Action { get; set; } 
    } 
} 

社區行動型號:

public partial class CommunityAction 
{ 
    public CommunityAction() 
    { 
     this.JunctionPopulationActions = new HashSet<JunctionPopulationAction>(); 
     this.JunctionDepartmentActions = new HashSet<JunctionDepartmentAction>(); 
     this.JunctionTypeActions = new HashSet<JunctionTypeAction>(); 
    } 

    public int ActionID { get; set; } 
    public System.DateTime StartDate { get; set; } 
    public Nullable<System.DateTime> EndDate { get; set; } 
    public string BreifDescription { get; set; } 
    public Nullable<int> Duration { get; set; } 
    public int LocationID { get; set; } 
    public string SubLocation { get; set; } 
    public int ProgramID { get; set; } 
    public string Notes { get; set; } 
    public string AddedBy { get; set; } 
    public byte[] RecordVersion { get; set; } 

    public virtual Location Location { get; set; } 
    public virtual Program Program { get; set; } 
    public virtual ICollection<JunctionPopulationAction> JunctionPopulationActions { get; set; } 
    public virtual ICollection<JunctionDepartmentAction> JunctionDepartmentActions { get; set; } 
    public virtual ICollection<JunctionTypeAction> JunctionTypeActions { get; set; } 
} 

的結表型號: JunctionDepartmentAction:

public partial class JunctionDepartmentAction 
{ 
    public int IndexID { get; set; } 
    public int DepartmentID { get; set; } 
    public int ActionID { get; set; } 
    public string SubDepartment { get; set; } 
    public int Individuals { get; set; } 

    public virtual CommunityAction CommunityAction { get; set; } 
    public virtual Department Department { get; set; } 
} 

JunctionPopulationAction:

public partial class JunctionPopulationAction 
{ 
    public int IndexID { get; set; } 
    public int PopulationID { get; set; } 
    public int ActionID { get; set; } 
    public bool isActive { get; set; } 
    public virtual CommunityAction CommunityAction { get; set; } 
    public virtual TargetPopulation TargetPopulation { get; set; } 
} 

JunctionTypeAction:

public partial class JunctionTypeAction 
{ 
    public int IndexID { get; set; } 
    public int TypeID { get; set; } 
    public int ActionID { get; set; } 
    public virtual ActivityType ActivityType { get; set; } 
    public virtual CommunityAction CommunityAction { get; set; } 
} 

事件控制器編輯操作方法:

// GET: /Event/Edit/5 
    public async Task<ActionResult> Edit(int? id) 
    { 
     if (id == null) 
     { 
      return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 
     } 
     CommunityAction communityaction = await db.CommunityActions.FindAsync(id); 
     ActivityViewModel activityviewmodel = new ActivityViewModel(); 
     activityviewmodel.Action = communityaction; 
     IList<JunctionTypeAction> junctiontypeactions = await db.JunctionTypeActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync(); 
     IList<JunctionDepartmentAction> junctiondepartmentactions = await db.JunctionDepartmentActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync(); 
     IList<JunctionPopulationAction> junctionpopulationactions = await db.JunctionPopulationActions.Where(d => d.ActionID == communityaction.ActionID).ToListAsync(); 
     activityviewmodel.junctionTypeActions = junctiontypeactions.ToList(); 
     activityviewmodel.junctionDepartmentActions = junctiondepartmentactions.ToList(); 
     activityviewmodel.junctionPopulationActions = junctionpopulationactions.ToList();    
     if (communityaction == null) 
     { 
      return HttpNotFound(); 
     } 
     ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", activityviewmodel.Action.LocationID); 
     ViewBag.ProgramID = new SelectList(db.Programs, "ProgramID", "ProgramID", activityviewmodel.Action.ProgramID); 
     return View(activityviewmodel); 
    } 

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public async Task<ActionResult> Edit(ActivityViewModel activity) 
    { 
     //request added for debugging purposes 
     Request.ToString(); 
     if (ModelState.IsValid) 
     { 
      db.Entry(activity).State = EntityState.Modified; 
      await db.SaveChangesAsync(); 
      return RedirectToAction("Index"); 
     } 
     ViewBag.LocationID = new SelectList(db.Locations, "LocationID", "LocationName", activity.Action.LocationID); 
     ViewBag.ProgramID = new SelectList(db.Programs, "ProgramID", "ProgramID", activity.Action.ProgramID); 
     return View(activity); 
    } 

最後我的看法。我在DataBase的聯結表中使用了三個編輯器模板,還有一個用於CommunityAction對象。然後我有一個使用三個編輯器模板顯示ViewModel的部件的事件視圖。

CommunityAction.cshtml:

@model CommunityHealth.Models.CommunityAction 
<div class="form-horizontal"> 
<h4>CommunityAction</h4> 
<hr /> 
@Html.ValidationSummary(true) 
@Html.HiddenFor(model => model.ActionID) 
@Html.HiddenFor(model => model.RecordVersion) 
<div class="form-group"> 
    @Html.LabelFor(model => model.StartDate, new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.StartDate) 
     @Html.ValidationMessageFor(model => model.StartDate) 
    </div> 
</div> 
<div class="form-group"> 
    @Html.LabelFor(model => model.EndDate, new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.EndDate) 
     @Html.ValidationMessageFor(model => model.EndDate) 
    </div> 
</div> 
<div class="form-group"> 
    @Html.LabelFor(model => model.BreifDescription, new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.BreifDescription) 
     @Html.ValidationMessageFor(model => model.BreifDescription) 
    </div> 
</div> 

<div class="form-group"> 
    @Html.LabelFor(model => model.Duration, new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.EditorFor(model => model.Duration) 
     @Html.ValidationMessageFor(model => model.Duration) 
    </div> 
</div> 
<div class="form-group"> 
    @Html.LabelFor(model => model.LocationID, "Location", new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.DropDownListFor(model => model.Location, ViewBag.LocationID as SelectList, new { htmlAttributes = new { @class = "control-form" } }) 
     @Html.ValidationMessageFor(model => model.Location) 
    </div> 
</div> 

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

<div class="form-group"> 
    @Html.LabelFor(model => model.ProgramID, "Program", new { @class = "control-label col-md-2" }) 
    <div class="col-md-10"> 
     @Html.DropDownListFor(model => model.ProgramID, ViewBag.ProgramID as SelectList, new { htmlAttributes = new { @class = "control-form" } }) 
     @Html.ValidationMessageFor(model => model.Program) 
    </div> 
</div> 

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

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

JunctionTypeAction.cshtml:

@model CommunityHealth.Models.JunctionTypeAction 
<div class="type"> 
<fieldset> 
    @Html.HiddenFor(model => model.ActionID) 
    @Html.HiddenFor(model => model.IndexID) 
    @Html.EditorFor(model => model.TypeID, "TypeName", new { @class = "control-label col-md-2" }) 
</fieldset> 
</div> 

JunctionDepartmentAction.cshtml:

@model CommunityHealth.Models.JunctionDepartmentAction 
@using CommunityHealth.Models 
<div> 
<table> 
    <tbody> 
     <tr> 
      <td> 
       @Html.HiddenFor(model => model.ActionID) 
       @Html.HiddenFor(model => model.IndexID) 
       @Html.EditorFor(model => model.DepartmentID, "DepartmentName", new { @class = "control-label col-md-2" }) 
      </td> 
      <td> 
       @Html.EditorFor(model => model.SubDepartment, "SubDepartment", new { @class = "control-label col-md-2 " }) 
      </td> 
      <td> 
       @Html.EditorFor(model => model.Individuals) 
      </td> 
     </tr> 
    </tbody> 
</table> 
</div> 

JunctionPopulationAction.cshtml:

@model CommunityHealth.Models.JunctionPopulationAction 

<div class="population"> 
<fieldset> 
    @Html.HiddenFor(model => model.ActionID) 
    @Html.HiddenFor(model => model.IndexID) 
    @Html.EditorFor(model => model.PopulationID, "PopulationName", new { @class = "control-label col-md-2" }) 
</fieldset> 
</div> 

查看\事件\ Edit.cshtml:

@model CommunityHealth.Models.ViewModels.ActivityViewModel 
@using CommunityHealth.Models.ViewModels; 
@{ 
    ViewBag.Title = "Edit"; 
} 
<h2>Edit</h2> 
@using (Html.BeginForm("Edit","Event",FormMethod.Post)) 
{ 
    @Html.AntiForgeryToken() 
    <div> 
     <div class="form-group"> 
      @Html.EditorFor(model => model.Action) 
     </div> 
     <div class="form-group"> 
      @Html.Label("Types") 
      <div class="col-md-10"> 
       <fieldset> 
        @for (int x = 0; x < Model.junctionTypeActions.Count(); x++) 
        { 
         @Html.EditorFor(model => model.junctionTypeActions[x]) 
        } 
       </fieldset> 
      </div> 
     </div> 
     <div class="form-group"> 
      @Html.Label("Departments") 
      <div class="col-md-10"> 
       @for (int x = 0; x < Model.junctionDepartmentActions.Count(); x++) 
       { 
        @Html.EditorFor(model => model.junctionDepartmentActions[x]) 
       } 
      </div> 
     </div> 
     <div class="form-group"> 
      @Html.Label("Target Populations") 
      <div class="col-md-10"> 
       @for (int x = 0; x < Model.junctionDepartmentActions.Count(); x++) 
       { 
        @Html.EditorFor(model => model.junctionPopulationActions[x]) 
       } 
      </div> 
     </div> 
     <div class="form-group"> 
      <div class="col-md-offset-2 col-md-10"> 
       <input type="submit" value="Save" class="btn btn-default" /> 
      </div> 
     </div> 
    </div> 
    <div> 
     @Html.ActionLink("Back to List", "Index") 
    </div> 
} 
@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
} 

當我檢查請求我收到此錯誤:

「的參數轉換,從類型 'System.String' 輸入' CommunityHealth.Models.CommunityAction'失敗,因爲沒有類型轉換器可以在這些類型之間進行轉換。「

+0

什麼是回發問題 - 模型爲null?是模型null的屬性?是不是綁定的集合? (你真的希望任何人都可以瀏覽所有的代碼)注意:渲染所有隱藏的輸入是不好的做法並會降低性能 - 使用視圖模型來表示你想要編輯的內容。只需使用'@ Html.EditorFor(m => m.junctionTypeActions)' - 不在'for'循環內 – 2015-03-25 05:00:08

+0

我很感激任何反饋。我當然不會「期待」任何人提供幫助,我只是希望有人能夠看一眼,看看我缺少的是什麼。如果有人確實選擇瞭解我的問題,我希望他們擁有所需的一切,以弄清楚我做錯了什麼。我沒有計劃保留隱藏的類型。我確實喜歡你擁有路口的方式,併爲了簡單起見而改變了這一點。 – ghg565 2015-03-25 05:40:49

+0

你的模特不應該是這個複雜的......哎呀,爲什麼這些藏品是虛擬的?這不是實體框架。通常沒有理由讓所有這些集合在視圖模型中互相引用。 – 2015-03-25 14:10:17

回答

0

原因這個錯誤是因爲你模型(typeof運算CommunityAction)命名activity一個屬性,您的帖子方法的參數也被命名activity。參數名稱更改爲比屬性的名稱以外的任何模型(一個或多個)

public async Task<ActionResult> Edit(ActivityViewModel model) 
{ 
    .... 
} 

旁註

  1. 只需使用@Html.EditorFor(m => m.junctionTypeActions)產生 的集合(不是在for循環的HTML )。 @Html.EditorFor() 足夠智能識別集合並生成正確的 html。
  2. 生成所有這些隱藏的輸入是不好的做法,並會降低性能(並且任何惡意用戶都可能會改變這些值)。 爲每個或您的類型使用視圖模型,只包含您需要顯示/編輯的 屬性。
+0

這似乎讓我超越了目前的障礙!我必須更改CommunityAction編輯器模板,以便將其綁定到LocationID而不是Location,但是一旦我更改了名稱並且能夠在我的斷點處正確查看所有結果,就很容易找到它。感謝您的幫助! – ghg565 2015-03-25 07:17:44