0

我试图在我的视图中创建一个对象列表,但是在 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")
}

在此处输入图像描述

4

2 回答 2

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 之后的列表中看到七个项目。希望这对您有所帮助。

于 2013-03-15T07:20:36.737 回答
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")
        }

创建局部视图 _parttailView.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 方法中获得值,并且还会在视图中添加Helper 类引用

于 2013-03-15T06:25:01.440 回答