无法创建接口的实例(PagedList) [英] Cannot create an instance of an interface (PagedList)

查看:90
本文介绍了无法创建接口的实例(PagedList)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个视图模型对象,其中包含另一个模型对象类型的List.当用户在页面上进行查询时,如果返回的List包含300条以上的记录,我们希望使用分页来减少加载时间(某些搜索结果可以返回14000条以上的记录).我们正在使用的此页面插件.

I have a view model object that contains a List of another model object type. When the user does a query on the page, if the List returned contains more than 300 records we want to use paging to keep the loading time down (some search results can return more than 14k records). The paging plugin we're using can be found here.

一旦结果显示在页面上,用户便可以单击特定结果旁边的复选框,在输入文本框中键入一些信息,单击提交",并使用该信息编辑所选记录从文本框中输入.

Once the results have been displayed on the page, the user has the ability to click a check box next to specific results, type in some information in an input text box, hit submit, and have the selected records edited with the information from the text box.

由于我们需要使用IPagedList<>来启用分页,但是,当您单击提交"时(甚至在该页面还没有命中控制器之前),我们都会收到以下错误消息:

Since we needed to use an IPagedList<> in order to enable paging, however, when you hit submit (and before the page even hits the controller) we get the following error:

                 Cannot create an instance of an interface.

查看模型

这是我们用于分页的两个列表对象. zipCodeTerritory对象保存查询的结果. pagedTerritoryList用于仅在用户所在的特定页面上显示结果.

These are the two list objects that we use for paging. The zipCodeTerritory object holds the results of the query. The pagedTerritoryList is used to display only the results on the specific page the user is on.

    //Paging List objects
    public IPagedList<ZipCodeTerritory> pagedTerritoryList { get; set; }
    public List<ZipCodeTerritory> zipCodeTerritory { get; set; }
    public IPagedList PagingMetaData { get; set; }

控制器

这是我们的基本搜索. .ToPagedList方法用于指定我们要显示的结果范围,并将它们放置在对象中.

This is our basic search. The .ToPagedList method is used to specify what range of results we want to display and place them in the pagedTerritoryList object.

                //set Paged List counter variables
                int pageNumber = page ?? 1;
                int pageSize = 300;

                //Determine if Territory present?
                if (string.IsNullOrWhiteSpace(search.searchTerritory))
                {
                    //State Code ONLY search
                    search.zipCodeTerritory = (from z in db.ZipCodeTerritory
                                               where z.StateCode.Equals(search.searchState)
                                               select z).ToList();
                }
                else if(string.IsNullOrWhiteSpace(search.searchState))
                {
                    //Territory ONLY search
                    search.zipCodeTerritory = (from z in db.ZipCodeTerritory
                                               where z.IndDistrnId.Equals(search.searchTerritory)
                                               select z).ToList();
                }
                else
                {
                    //Territory AND state search
                    search.zipCodeTerritory = (from z in db.ZipCodeTerritory
                                               where z.IndDistrnId.Equals(search.searchTerritory) &&
                                                     z.StateCode.Equals(search.searchState)
                                               select z).ToList();
                }

                //Convert list to IPagedList for pagining on Index
                search.pagedTerritoryList = search.zipCodeTerritory.ToPagedList(pageNumber, pageSize);

                //Set Paged List objects
                search.PagingMetaData = new StaticPagedList<ZipCodeTerritory>(search.zipCodeTerritory, pageNumber, pageSize,
                                                                      search.zipCodeTerritory.Count).GetMetaData();

                return View(search);

查看

这是显示搜索结果的表格.如果用户选中该复选框,然后单击clonedelete按钮,则应该将结果发布回控制器的Update方法,并执行适当的编辑或删除操作.用户想要在编辑中覆盖的信息以格式(在table上方)输入到newTerritory/Description/etc字段中.

This is the form that displays the search results. If a user checks the check box, then hits either clone or delete buttons, the results are supposed to be posted back to the controller's Update method and appropriate edits or deletes performed. The information the user wants to overlay in an edit are input into the newTerritory/Description/etc fields in the form (above the table).

关于@Html.PagedListPager,我发现我必须将相同的搜索标准从页面传递回索引方法,因此RouteValueDictionary中的参数过多.

Regarding the @Html.PagedListPager I found I had to pass back to the index method the same search criteria from the page, thus the excessive amount of parameters in the RouteValueDictionary.

@if (Model.zipCodeTerritory.Count > 0)
{
    using (Html.BeginForm("Update", "ZipCodeTerritory", FormMethod.Post))
    {
        @Html.HiddenFor(model => model.searchZip)
        @Html.HiddenFor(model => model.searchDate)
        @Html.HiddenFor(model => model.searchState)

        <div id="cloneBox">
            <div id="rw1">
                @Html.LabelFor(model => model.newTerritory)
                @Html.TextBoxFor(model => model.newTerritory, new { style = "width: 30px;padding-left:10px;", maxLength = 3 })
                @Html.LabelFor(model => model.newDescription)
                @Html.TextBoxFor(model => model.newDescription, new { style = "width: 250px;padding-left:10px;", maxLength = 30 })  
                @Html.LabelFor(model => model.newEffectiveDate)     
                @Html.TextBoxFor(model => model.newEffectiveDate, new { style = "width: 80px;padding-left:10px;" }) 
                <div id="rw2" style="padding-top: 10px;">
                    @Html.LabelFor(model => model.newChannelCode)
                    @Html.DropDownListFor(model => model.newChannelCode, Model.ChannelCodes, " ")
                    @Html.LabelFor(model => model.newStateCode)
                    @Html.DropDownListFor(model => model.newStateCode, Model.StateCodes, "  ")
                </div>                                 
            </div>
        </div>
        <br/>
        <div id="buttonDiv">
            <button type="submit" id="CloneButton" name="button" value="clone">Apply New Data</button>
            <button type="submit" id="deleteButton" name="button" value="delete">Delete Selected Items</button>            
        </div>


        @*Display paging only if necessary*@
        if (Model.pagedTerritoryList.Count >= 300)
        {
           <div id="pagingDiv">
               @Html.PagedListPager(new StaticPagedList<Monet.Models.ZipCodeTerritory>(Model.zipCodeTerritory, Model.PagingMetaData) , 
            Page => Url.Action("Index", new RouteValueDictionary()
               {
                   { "Page", Page},
                   { "searchZip", Model.searchZip },
                   { "searchActiveOnly", Model.searchActiveOnly },
                   { "searchDate", Model.searchDate },
                   { "searchState", Model.searchState },
                   { "searchTerritory", Model.searchTerritory },
                   { "searchChannel" , Model.searchChannelCode }
               }), PagedListRenderOptions.DefaultPlusFirstAndLast)
           </div>            
        }

        <table id="thetable" class="tablesorter" >
            <thead>
                <th>@Html.CheckBox("SelectAll")</th>
                <th>State</th>
                <th>Territory</th>
                <th>Zip</th>
                <th>Description</th>
                <th>Effective</th>
                <th>End Date</th>
                <th>Last Update Date</th>
                <th>Channel</th>
                <th></th>
            </thead>
            <tbody id="tableBody">
                @for (int i = 0; i < Model.pagedTerritoryList.Count; i++)
                {
                    <tr id="@(Model.lastEditedId == Model.pagedTerritoryList[i].Id ? "lastEdit" : "")">
                        <td>
                            @Html.CheckBoxFor(model => model.pagedTerritoryList[i].Update)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].Update)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].StateCode)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].StateCode)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].IndDistrnId)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].IndDistrnId)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].ZipCode)
                            @Html.HiddenFor(model => model.zipCodeTerritory[i].ZipCode)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].DrmTerrDesc)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].DrmTerrDesc)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].EffectiveDate)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].EffectiveDate)
                        </td>
                        <td>
                            @if (Model.pagedTerritoryList[i].EndDate.Date != DateTime.MaxValue.Date)
                            {
                                @Html.DisplayFor(model => model.pagedTerritoryList[i].EndDate)
                                @Html.HiddenFor(model => model.pagedTerritoryList[i].EndDate)                                
                            }
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].LastUpdateDate)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].LastUpdateDate)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].ChannelCode)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].ChannelCode)
                        </td>

                        @if (ViewBag.SecurityLevel >= 4)
                        {
                            <td>
                                @Html.ActionLink("Edit", "Edit", new
                                    {
                                        id = Model.zipCodeTerritory[i].Id,
                                        searchZip = Model.searchZip,
                                        searchActiveOnly = Model.searchActiveOnly,
                                        searchDate = Model.searchDate,
                                        searchState = Model.searchState,
                                        searchTerritory = Model.searchTerritory,
                                        searchChannelCode = Model.searchChannelCode
                                    })
                                @Html.HiddenFor(model => model.zipCodeTerritory[i].Id)
                            </td>                            
                        }

                    </tr>
                }
            </tbody>
        </table>
    }
}

编辑

根据下面的评论,这是表单发布到的方法的签名.它包含ZipCodeIndex的一个实例,该实例最初会加载到页面上,再加上button的文本来确定我们要执行的是clone还是delete

Per the comment below, here is the signature for the method the form is posting to. It contains an instance of the ZipCodeIndex that gets loaded on the page originally, plus the text from the button to determine whether we're doing a clone or delete

    [HttpPost]
    public ActionResult Update(ZipCodeIndex updateZip, string button)
    {

第二次修改

尝试了此问题中的方法,但仍收到原始错误消息(无法创建以下内容的实例接口").

Tried the method from this question but still receiving the original error message ("cannot create instance of an interface").

推荐答案

我能够完全摆脱困境,但是我认为这不是最好的解决方案.如果有人可以提供更好的答案,将不胜感激,但是与此同时,我将在此处发布.

I was able to completely hack my way out of this, however I don't think it's the best solution. Would love it if someone could provide a better answer however I'll post this up here in the meantime.

由于构建了IPagedList对象以容纳特定范围的List<>,所以我刚刚在视图模型上创建了display属性,并在视图上使用了该属性.此列表(而不是IPagedList)被发布回控制器以进行更新,因此不会发生界面怪异.

Since the IPagedList object was built to hold a specific range of the List<> I just made a display property on my view model and used this on my view. This list, not the IPagedList gets posted back to the controller for the updates, so no interface weirdness occurs.

查看模型

    //Paging List objects
    public IPagedList<ZipCodeTerritory> pagedTerritoryList { get; set; }
    public List<ZipCodeTerritory> zipCodeTerritory { get; set; }
    public List<ZipCodeTerritory> displayForPaging { get; set; } 

控制器

    //Convert list to IPagedList for pagining on Index
    search.pagedTerritoryList = search.zipCodeTerritory.ToPagedList(pageNumber, pageSize);
    search.displayForPaging = search.pagedTerritoryList.ToList();

查看

    <td>
         @Html.CheckBoxFor(model => model.displayForPaging[i].Update)
         @Html.HiddenFor(model => model.displayForPaging[i].Update)
    </td>
    <td>
     .
     .

这篇关于无法创建接口的实例(PagedList)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆