2013-03-15 34 views
0

我试图在我的视图中创建对象列表,但是在post方法中,进来的参数为null。创建页面可以正常加载我想要的所有信息,但是当我单击“创建”时,我会在我的标题中看到列出的错误。我能做什么错了?未将对象引用设置为对象的实例。自定义对象在POST时返回null

员工每天有可用的链接。这就是我想实现

型号

public class Availability 
{ 

    [Required] 
    public long Id { get; set; } 

    [Required] 
    [DataType(DataType.Text)] 
    [Display(Name = "Weekday")] 
    public string weekday { get; set; } 

    [DataType(DataType.Time)] 
    [Display(Name = "Start Time")] 
    public DateTime StartTime { get; set; } 

    [DataType(DataType.Time)] 
    [Display(Name = "End Time")] 
    public DateTime EndTime { get; set; } 

    public virtual Employee employee { get; set; } 

} 
} 

自定义类

public class SetAvailability 
{ 
    public long EmpID { get; set; } 
    public String firstName {get; set;} 
    public String lastName { get; set; } 
    public Availability availability {get; set;} 


} 

控制器方法

// GET: /Availability/Create 

    public ActionResult Create(long id) 
    { 
     string[] weekdays ={"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 
     //find the employee 
     Employee emp = db.Employees.Find(id); 

     //create a list of setAvailability objects for each day 
     List<SetAvailability> editor = new List<SetAvailability>(); 


     //instantiate each SetAvailability object and populate accordingly for 7 days 
     for (int i = 0; i < 7; i++) 
     { 
      //create a blank SetAvilability 
      var _editor = new SetAvailability(); 

      //create a blank availability 
      _editor.availability = new Availability(); 

      //set the weekday 
      _editor.availability.weekday = weekdays[i].ToString(); 

      //set the employee id, first name and last name 
      _editor.EmpID = emp.Id; 
      _editor.firstName = emp.FirstName; 
      _editor.lastName = emp.LastName; 
      //add the _editor to the editorlist 
      editor.Add(_editor); 
     } 

     return View(editor); 


    } 

    // 
    // POST: /Availability/Create 

    [HttpPost] 
    public ActionResult Create(List<SetAvailability> dto) 
    { 
     //dto object is coming in null! (checked by debugging) 
     List<SetAvailability> temp = new List<SetAvailability>(); 
     temp = dto; 

     if (ModelState.IsValid) 
     { 
      // set the values for each availability object 
      // breaks here! 
      foreach (var item in dto) 
      {      
       // get the employee 
       item.availability.employee = db.Employees.Find(item.EmpID); 

       // weekday should already be set 
       // start and end times should come in from the create view 

       db.Availability.Add(item.availability); 
      } 
      db.SaveChanges(); 
      return RedirectToAction("Index","employee"); 
     } 

     return View(temp); 
    } 

查看

@model List<VolumeV2.Models.DTOs.SetAvailability> 

@{ 
ViewBag.Title = "Create"; 

} 

<h2>Create</h2> 

@using (Html.BeginForm()) { 
@Html.ValidationSummary(true) 

<fieldset> 
    <legend>Availability</legend> 

    <table> 
     <tr> 
     @foreach (var item in Model)     
      {    
        @Html.HiddenFor(model => item.EmpID) 
        @Html.HiddenFor(model => item.firstName) 
        @Html.HiddenFor(model => item.lastName) 
      <td> 
       @Html.LabelFor(model => item.availability.weekday) 
      </td>     
      <td> 
       @Html.LabelFor(model => item.availability.StartTime)     
      </td> 
      <td> 
       @Html.LabelFor(model => item.availability.EndTime)     
      </td>     
      break; 
     } 
     </tr> 
     @foreach (var item in Model){ 
        @Html.HiddenFor(model => item.EmpID) 
        @Html.HiddenFor(model => item.firstName) 
        @Html.HiddenFor(model => item.lastName) 
      <tr> 
       <td> 
       @Html.EditorFor(modelitem => item.availability.weekday) 
       @Html.ValidationMessageFor(modelitem => item.availability.weekday) 
       </td> 

       <td>       
       @Html.EditorFor(modelitem => item.availability.StartTime) 
       @Html.ValidationMessageFor(modelitem => item.availability.StartTime) 
       </td> 

       <td>       
       @Html.EditorFor(modelitem => item.availability.EndTime) 
       @Html.ValidationMessageFor(modelitem => item.availability.EndTime) 
       </td> 
      </tr> 
     } 
    </table> 
    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 
} 

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

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

enter image description here

+0

尝试编辑模板。 – ssilas777 2013-03-15 06:36:03

+0

你会碰巧知道一个很好的基本MVC4教程吗?我很难找到一个好的源码 – Fpanico 2013-03-15 06:53:25

回答

0

试试这个

要在POST获取对象的集合方法就需要修改Html.BeginForm, 添加以下Helper类在你的将返回你的应用程序列表的对象。 (例如辅助类DemoApplication /模型的位置/)

public static class HtmlPrefixScopeExtensions 
    { 
     private const string idsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_"; 

     public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName) 
     { 
      var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName); 
      string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString(); 

      // autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync. 
      html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex))); 

      return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex)); 
     } 

     public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix) 
     { 
      return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix); 
     } 

     private static Queue<string> GetIdsToReuse(HttpContextBase httpContext, string collectionName) 
     { 
      // We need to use the same sequence of IDs following a server-side validation failure, 
      // otherwise the framework won't render the validation error messages next to each item. 
      string key = idsToReuseKey + collectionName; 
      var queue = (Queue<string>)httpContext.Items[key]; 
      if (queue == null) { 
       httpContext.Items[key] = queue = new Queue<string>(); 
       var previouslyUsedIds = httpContext.Request[collectionName + ".index"]; 
       if (!string.IsNullOrEmpty(previouslyUsedIds)) 
        foreach (string previouslyUsedId in previouslyUsedIds.Split(',')) 
         queue.Enqueue(previouslyUsedId); 
      } 
      return queue; 
     } 

     private class HtmlFieldPrefixScope : IDisposable 
     { 
      private readonly TemplateInfo templateInfo; 
      private readonly string previousHtmlFieldPrefix; 

      public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix) 
      { 
       this.templateInfo = templateInfo; 

       previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix; 
       templateInfo.HtmlFieldPrefix = htmlFieldPrefix; 
      } 

      public void Dispose() 
      { 
       templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix; 
      } 
     } 
    } 

后改性查看

@model List<VolumeV2.Models.DTOs.SetAvailability> 



    @{ 
    ViewBag.Title = "Create"; 

    } 

    <h2>Create</h2> 


@Html.ValidationSummary(true) 

    @using(Html.BeginForm()) 
    { 

     <fieldset> 
      <legend>Availability</legend> 

      <table> 

       @foreach (var item in Model)     
        {  

        @Html.Partial("_partialView",item) 
       } 


      </table> 
      <p> 
       <input type="submit" value="Create" /> 
      </p> 
     </fieldset> 
     } 

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

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

创建的局部视图 _partailView.cshtml

@model VolumeV2.Models.DTOs.SetAvailability 
    @using DemoApplication.Models // Added Helper class reference 
    <tr> 
    @using (Html.BeginCollectionItem("dto")) { 

           @Html.HiddenFor(model => model.EmpID) 
           @Html.HiddenFor(model => model.firstName) 
           @Html.HiddenFor(model => model.lastName) 
         <td> 
          @Html.LabelFor(model => model.availability.weekday) 
         </td>     
         <td> 
          @Html.LabelFor(model => model.availability.StartTime)     
         </td> 
         <td> 
          @Html.LabelFor(model => model.availability.EndTime)     
         </td>     
         break; 

         } 
      </tr> 

注意:必须在POST方法中保留Html.BeginCollectionItem(“dto”)和参数名称的相同名称,否则您将不会在POST方法中获得值,并且还会添加助手类参考在您的看法。

+0

我已经在我的项目中添加了html helper类,并将它包含在视图中,并且现在更改了beginCollectionItem广告我的创建按钮不会执行任何操作 – Fpanico 2013-03-15 06:48:00

+0

@Fpanico我已经完成了一些操作视图变化请检查它。 – Shivkumar 2013-03-15 07:26:41

0

要快速解决这个问题,您可以使用“for”循环在列表项上使用索引,因为这将呈现控件的名称以适应MVC模型绑定的命名约定。例如,[0] .availability.weekday,[1] .availability.weekday等等,表示具有相应索引的项目数组,以便能够在模型绑定时构建项目列表。

@model List<MvcApplication5.Models.SetAvailability> 

@using (Html.BeginForm("Create","Employee")) { 
@Html.ValidationSummary(true) 

<fieldset> 
    <legend>Availability</legend> 

    <table> 
     <tr> 
     @for (int i = 0; i < Model.Count; i++) 
     { 
      @Html.HiddenFor(model => Model[i].EmpID) 
        @Html.HiddenFor(model => Model[i].firstName) 
        @Html.HiddenFor(model => Model[i].lastName) 
      <td> 
       @Html.LabelFor(model => Model[i].availability.weekday) 
      </td>     
      <td> 
       @Html.LabelFor(model => Model[i].availability.StartTime)     
      </td> 
      <td> 
       @Html.LabelFor(model => Model[i].availability.EndTime)     
      </td>     
      break; 
     } 
     </tr> 
     @for (int i = 0; i < Model.Count; i++) 
     { 
      @Html.HiddenFor(model => Model[i].EmpID) 
        @Html.HiddenFor(model => Model[i].firstName) 
        @Html.HiddenFor(model => Model[i].lastName) 
      <tr> 
       <td> 
       @Html.EditorFor(modelitem => Model[i].availability.weekday) 
       @Html.ValidationMessageFor(modelitem => Model[i].availability.weekday) 
       </td> 

       <td>       
       @Html.EditorFor(modelitem => Model[i].availability.StartTime) 
       @Html.ValidationMessageFor(modelitem => Model[i].availability.StartTime) 
       </td> 

       <td>       
       @Html.EditorFor(modelitem => Model[i].availability.EndTime) 
       @Html.ValidationMessageFor(modelitem => Model[i].availability.EndTime) 
       </td> 
      </tr> 
     } 
    </table> 
    <p> 
     <input type="submit" value="Create" /> 
    </p> 
</fieldset> 
} 

现在,您应该在POST之后的列表中看到七个项目。希望这对你有所帮助。

相关问题