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

これを試して

POSTメソッドでオブジェクトのコレクションを取得するには、Html.BeginForm を変更する必要があります。アプリケーションに次のヘルパー クラスを追加すると、オブジェクトのリストが返されます。(例: ヘルパー クラス 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 メソッドで値を取得できず、ビューにヘルパー クラス参照も追加されません。

于 2013-03-15T06:25:01.440 に答える
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 後にリストに 7 つの項目が表示されるはずです。これがお役に立てば幸いです。

于 2013-03-15T07:20:36.737 に答える