MVC - DropDownList / PartialView问题 - “Viewdata有关键int .. ..必须是IUnumerable ......”

时间:2016-09-30 06:24:57

标签: c# asp.net-mvc

  

具有“SelectedRating”键的ViewData项是类型   'System.Int32'但必须是'IEnumerable'类型。

当我尝试通过局部视图添加DropDownList时,这是我得到的错误。我试图跟随this solution,但由于我在编码方面的经验不足,我没有这样做。

这就是我的代码目前的样子:

 [HttpGet]
    public ActionResult Rating()
    {
        RateReviewVM model = new RateReviewVM()
        {
            ReviewId = id,
            RatingList = new SelectList(Enumerable.Range(1, 10))
        };
        return View(model);
    }

     [HttpPost]
     public ActionResult Rating(RateReviewVM model) {

         if (!ModelState.IsValid)
         {                
            model.RatingList = new SelectList(Enumerable.Range(1, 10));
            return View(model);
         }

       //...

查看_RatingPartial

@model xxxx.ViewModel.RateReviewVM

<h6>Rate the review</h6>

using (Html.BeginForm()) {

<div class="form-group">


    @Html.LabelFor(m => m.SelectedRating)
    @Html.DropDownListFor(m => m.SelectedRating, Model.RatingList, "-Please select-", new { @class = "form-control" })
    @Html.ValidationMessageFor(m => m.SelectedRating)

</div>

<button type="submit" class="btn btn-default submit">Rate</button>
    }
}

这是我尝试显示_RatingPartial视图的方式

@{
    var newRating = new xxxx.ViewModel.RateReviewVM { ReviewId = Model.Id };

    Html.RenderPartial("_RatingPartial", newRating);

}

模型

    public class RateReviewVM {

            public System.Guid Id { get; set; }

            public System.Guid UserId { get; set; }

            public System.Guid ReviewId { get; set; }

            public bool HasLiked { get; set; }

            public Nullable<int> Rating { get; set; }

            public int SelectedRating { get; set; }

            public IEnumerable<SelectListItem> RatingList { get; set; }
     }

编辑:---

详细信息视图(主要)

    @model xxxx.Review

    @{
        ViewBag.Title = "Details";
    }

    @*@{
        //var newRating = new xxxx.ViewModel.RateReviewVM { ReviewId = Model.Id };

        @Html.RenderPartial("_RatingPartial", newRating)

    }*@

    <h2>Details</h2>

    <div>

        <h4>Review</h4>
        <hr/>
        <dl class="dl-horizontal">
            <dt>
                @Html.DisplayNameFor(model => model.Title)
            </dt>

            <dd>
                @Html.DisplayFor(model => model.Title)
            </dd>

            <dt>
                @Html.DisplayNameFor(model => model.Description)
            </dt>

            <dd>
                @Html.DisplayFor(model => model.Description)
            </dd>
            @* and so on..  *@

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

控制人详情

            public ActionResult Details(Guid? id) {

            Review review = db.Reviews.Find(id);

            return View(review);
        }

详情的模型审核

        public System.Guid Id { get; set; }

        public System.Guid CreatorUserId { get; set; }

        [Required]
        public string Title { get; set; }

        [Required]
        public string Description { get; set; }

        public System.DateTime CreatedDate { get; set; }

        //etc - some irrelevant property        

        public virtual ICollection<RateReview> Users { get; set; }

2 个答案:

答案 0 :(得分:1)

将ViewBag用于dropdrownlist,它也适用于partialView。然后你不需要ViewModels。你的模型类可以使用。

首先向CreateRate控制器

添加Reviews操作
 public ActionResult CreateRate(RateReview rate)
    {
        if (ModelState.IsValid)
        {
            rate.Id = Guid.NewGuid();
            db.RateReviews.Add(rate);
            db.SaveChanges();
            return RedirectToAction("Details", "Reviews", new { id = rate.ReviewId });
        }

        return View();
    }

修改Details操作以创建如下所示的视包数据

public ActionResult Details(Guid? id)
{

    Review review = db.Reviews.Find(id);
    ViewBag.RatingList = new SelectList(Enumerable.Range(1, 10));

    return View(review);
}

如下所示修改PartialView以定位CreateRate操作,为ReviewId添加HiddenFor Helper并修改dropdownlist以从ViewBag中读取。我使用RateReview模型而不是ViewModel

@model WebApp.Models.RateReview


@using (Html.BeginForm("CreateRate", "Reviews")) 
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>RateReview</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

    @Html.HiddenFor(model => model.ReviewId)

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

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
}

最后您的Details视图很好:

@model WebApp.Models.Review

@{
ViewBag.Title = "Details";
}

@{
    var newRating = new WebApp.Models.RateReview { ReviewId = Model.Id };

    Html.RenderPartial("_RatingPartial", newRating);

}


<h2>Details</h2>

<div>
<h4>Review</h4>
<hr />
...

答案 1 :(得分:1)

错误的原因是RatingList的值为null(有关详细说明,请参阅The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable')。

在您的情况下,您使用RenderPartial()方法将模型传递给视图,而您没有设置属性RatingList的值(RenderPartial不会调用您的{{ 1}}方法。

您可以使用

解决错误
public ActionResult Rating()

以便填充属性,但由于您已经有了GET方法,因此最好使用调用服务器方法的@{ var newRating = new xxxx.ViewModel.RateReviewVM { ReviewId = Model.Id, RatingList = new SelectList(Enumerable.Range(1, 10)) }; Html.RenderPartial("_RatingPartial", newRating); } 方法

RenderAction()

注意我假设您的方法实际上是@{ Html.RenderAction("Rating", yourControllerName, new { id = Model.Id }); } ,因为当前代码会抛出异常,因为public ActionResult Rating(Guid id)未声明。

但是,由于POST方法返回的审核id无效(应该如此),但这不会解决您的所有问题,但它与您当前的视图不同。它也会抛出异常,因为你没有重新填充ModelState属性。

解决此问题的正确方法是为RatingList建立一个视图模型,其中包含另一个用于评论的视图模型。

Review

并在public class ReviewVM { ... properties of review including property for collection of existing commnets public CommentVM Comment { get; set; } // for generating a new comment form } 视图中添加用于生成新评论的表单,并回发到以Review.cshtml作为参数的方法。然后,如果ReviewVM无效,请根据其ID重新填充ModelState的属性,并重新填充其ReviewVM属性的RatingList属性。或者,如果您希望允许用户为Review添加多个注释,请考虑使用对话框表单添加新注释并使用ajax发布表单。