你调用的对象是空的。 POST时自定义对象返回null

时间:2013-03-15 06:01:12

标签: asp.net-mvc c#-4.0 razor asp.net-mvc-4

我正在尝试在视图中创建对象列表,但在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

2 个答案:

答案 0 :(得分:0)

试试这个

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

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方法中获得值,并在视图中添加帮助程序类引用

答案 1 :(得分:0)

要快速解决此问题,您可以使用&#34; for&#34;对列表项使用索引。循环,因为这将呈现控件的名称以适应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后看到列表中的七个项目。希望这能帮助你。