0

在 Visual Studio 2012 中开发 Webforms 站点时,将方法注册到 ListView 的 UpdateMethod 参数时遇到以下错误:

Constructor on type 'System.Web.UI.WebControls.ListViewUpdateEventArgs' not found.

堆栈跟踪:

[MissingMethodException: Constructor on type 'System.Web.UI.WebControls.ListViewUpdateEventArgs' not found.]
   System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +1136
   System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +128
   System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +18
   System.Web.SecurityUtils.SecureCreateInstance(Type type, Object[] args, Boolean allowNonPublic) +104
   System.Web.ModelBinding.MutableObjectModelBinder.CreateModel(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext) +26
   System.Web.ModelBinding.MutableObjectModelBinder.EnsureModel(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext) +42
   System.Web.ModelBinding.MutableObjectModelBinder.BindModel(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext) +37
   System.Web.ModelBinding.DefaultModelBinder.BindModel(ModelBindingExecutionContext modelBindingExecutionContext, ModelBindingContext bindingContext) +196
   System.Web.UI.WebControls.ModelDataSourceView.EvaluateMethodParameters(DataSourceOperation dataSourceOperation, ModelDataSourceMethod modelDataSourceMethod, IDictionary controlValues, Boolean isPageLoadComplete) +996
   System.Web.UI.WebControls.ModelDataSourceView.EvaluateMethodParameters(DataSourceOperation dataSourceOperation, ModelDataSourceMethod modelDataSourceMethod, IDictionary controlValues) +18
   System.Web.UI.WebControls.ModelDataSourceView.EvaluateUpdateMethodParameters(IDictionary keys, IDictionary values, IDictionary oldValues) +144
   System.Web.UI.WebControls.ModelDataSourceView.GetUpdateMethodResult(IDictionary keys, IDictionary values, IDictionary oldValues) +21
   System.Web.UI.WebControls.ModelDataSourceView.ExecuteUpdate(IDictionary keys, IDictionary values, IDictionary oldValues) +23
   System.Web.UI.DataSourceView.Update(IDictionary keys, IDictionary values, IDictionary oldValues, DataSourceViewOperationCallback callback) +87
   System.Web.UI.WebControls.ListView.HandleUpdate(ListViewItem item, Int32 itemIndex, Boolean causesValidation) +1643
   System.Web.UI.WebControls.ListView.HandleEvent(EventArgs e, Boolean causesValidation, String validationGroup) +1070
   System.Web.UI.WebControls.ListView.OnBubbleEvent(Object source, EventArgs e) +315
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
   System.Web.UI.WebControls.ListViewDataItem.OnBubbleEvent(Object source, EventArgs e) +141
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
   System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) +114
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +159
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1724

该项目配置为针对 .NET 4.5 进行编译,据我所知,所需的构造函数应该存在得很好。这是从 MetaData 中检索到的 ListViewUpdateEventArgs 的定义:

#region Assembly System.Web.Extensions.dll, v4.0.0.0
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Web.Extensions.dll
#endregion

using System;
using System.Collections.Specialized;
using System.ComponentModel;

namespace System.Web.UI.WebControls
{
    // Summary:
    //     Provides data for the System.Web.UI.WebControls.ListView.ItemUpdating event.
    public class ListViewUpdateEventArgs : CancelEventArgs
    {
        // Summary:
        //     Initializes a new instance of the System.Web.UI.WebControls.ListViewUpdateEventArgs
        //     class.
        //
        // Parameters:
        //   itemIndex:
        //     The index of the item being updated.
        public ListViewUpdateEventArgs(int itemIndex);

        // Summary:
        //     Gets the index of the data item that is being updated.
        //
        // Returns:
        //     The index of the data item that is being updated.
        public int ItemIndex { get; }
        //
        // Summary:
        //     Gets a dictionary of field name/value pairs that represent the key or keys
        //     of the item to update.
        //
        // Returns:
        //     The field name/value pairs that represent the key or keys of the item to
        //     update.
        public IOrderedDictionary Keys { get; }
        //
        // Summary:
        //     Gets a dictionary that contains the revised values of the item to update.
        //
        // Returns:
        //     The revised values of the item to update.
        public IOrderedDictionary NewValues { get; }
        //
        // Summary:
        //     Gets a dictionary that contains the original values of the item to update.
        //
        // Returns:
        //     The original values of the item to update.
        public IOrderedDictionary OldValues { get; }
    }
}

这是我的看法:

<%@ Page 
    Title="View Blog Post" 
    Language="C#" 
    MasterPageFile="~/Site.Master" 
    AutoEventWireup="true" 
    CodeBehind="Record.aspx.cs" 
    Inherits="Pritchard.Jumpstart.Webforms.BlogPost.Record" 
%>
<%@ Import Namespace="Microsoft.AspNet.FriendlyUrls" %>
<%@ Import Namespace="Pritchard.Jumpstart.Common.Data" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

    <asp:ListView runat="server"
        ID="BlogPostContainer"
        ItemType="Pritchard.Jumpstart.Common.Data.BlogPost"
        ItemPlaceholderID="BlogPost"
        SelectMethod="GetBlogPost"
        UpdateMethod="UpdateBlogPost"
        InsertMethod="InsertBlogPost">

        <LayoutTemplate>
            <asp:PlaceHolder runat="server" ID="BlogPost" />
        </LayoutTemplate>

        <EmptyDataTemplate>
            Sorry.  There are no blog posts to show.
        </EmptyDataTemplate>

        <ItemTemplate>
            <h2>
                <%# Item.Title %>
            </h2>
            <p>
                <strong>Author:</strong>  <%# Item.Author %>
                <br />
                <strong>Created On:</strong>  <%# Item.CreatedOn %>
            </p>
            <p>
                <strong>Post Summary</strong>
                <br />

                <%# Item.Summary %>
            </p>
            <p>
                <strong>Full Text</strong>
                <br />

                <%# Item.FullText %>
            </p>
            <p>
                <strong>Tags</strong>
                <br />

                <%# Item.Tags %>
            </p>
        </ItemTemplate>

        <EditItemTemplate>

            <h2>
                Edit Blog Post
            </h2>

            Title:
            <asp:TextBox runat="server" ID="BlogTitle" ClientIDMode="Static" Text='<%# Bind("Title") %>' />
            <br />

            Author:
            <asp:TextBox runat="server" ID="Author" ClientIDMode="Static" Text='<%# Bind("Author") %>' />
            <br />

            Text:
            <asp:TextBox runat="server" ID="FullText" ClientIDMode="Static" Text='<%# Bind("FullText") %>' TextMode="MultiLine" />
            <br />

            Tags:
            <asp:TextBox runat="server" ID="Tags" ClientIDMode="Static" Text='<%# Bind("Tags") %>' />
            <br />

            <asp:Button runat="server" CommandName="Update" Text="Update" />
            <asp:Button ID="Button1" runat="server" CommandName="Cancel" Text="Cancel" />

        </EditItemTemplate>

    </asp:ListView>

</asp:Content>

这是我的代码隐藏:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.AspNet.FriendlyUrls;
using Pritchard.Jumpstart.Common.Data.Services;
using Pritchard.Jumpstart.Webforms.Common;

namespace Pritchard.Jumpstart.Webforms.BlogPost
{
    public partial class Record : BasePage
    {

        private int id = 0;

        protected void Page_Load(object sender, EventArgs e)
        {

            var mode = "read";

            Int32.TryParse(Request.GetFriendlyUrlSegments().FirstOrDefault(), out id);
            mode = Request.QueryString["mode"];

            switch (mode)
            {
                case "read":
                    break;
                case "update":
                    BlogPostContainer.EditIndex = 0;
                    break;
                case "insert":
                    break;
            }

            if (id != 0)
                Model = BlogPostService.Get(id);

        }

        public IEnumerable<Jumpstart.Common.Data.BlogPost> GetBlogPost()
        {
            var list = new List<Jumpstart.Common.Data.BlogPost>();
            var item = BlogPostService.Get(id);

            if (item != null)
                list.Add(item);

            return list;
        }

        public void UpdateBlogPost(Object sender, ListViewUpdateEventArgs args)
        {
            var blogPost = (Jumpstart.Common.Data.BlogPost) args.NewValues[0];

            BlogPostService.Update(blogPost);
        }

        public void InsertBlogPost()
        {
            throw new NotImplementedException();
        }
    }
}

额外细节:

  • 我的环境中的所有内容似乎都设置为 .NET 4.5。我已经尽可能彻底地检查了这一点。

  • 使用 FormView 而不是 ListView 会导致同样的问题。

  • 使用替代的 UpdateMethod 签名 (int id) 会导致将 null id 传递给已注册的 UpdateMethod。

4

1 回答 1

0

这个修改后的代码有效,但它绝对不是我想要的解决方案。我不得不放弃使用 ListView/FormView 模型绑定并改用 ObjectDataSource。:

看法:

<%@ Page
    Title="View Blog Post"
    Language="C#"
    MasterPageFile="~/Site.Master"
    AutoEventWireup="true"
    CodeBehind="Record.aspx.cs"
    Inherits="Pritchard.Jumpstart.Webforms.BlogPost.Record"
%>
<%@ Import Namespace="Microsoft.AspNet.FriendlyUrls" %>
<%@ Import Namespace="Pritchard.Jumpstart.Common.Data" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

    <asp:ObjectDataSource ID="BlogPostDataSource" runat="server"
                          SelectMethod="GetBlogPost"
                          InsertMethod="InsertBlogPost"
                          UpdateMethod="UpdateBlogPost"
                          TypeName="Pritchard.Jumpstart.Webforms.BlogPost.Record"
                          DataObjectTypeName="Pritchard.Jumpstart.Common.Data.BlogPost" />

    <asp:FormView runat="server"
        ID="BlogPostContainer"
        ItemType="Pritchard.Jumpstart.Common.Data.BlogPost"
        ItemPlaceholderID="BlogPost"
        DataSourceID="BlogPostDataSource"
        DataKeyNames="PostID" >

        <EmptyDataTemplate>
            Sorry.  There are no blog posts to show.
        </EmptyDataTemplate>

        <ItemTemplate>
            <h2>
                <%# Item.Title %>
            </h2>
            <p>
                <strong>Author:</strong>  <%# Item.Author %>
                <br />
                <strong>Created On:</strong>  <%# Item.CreatedOn %>
            </p>
            <p>
                <strong>Post Summary</strong>
                <br />

                <%# Item.Summary %>
            </p>
            <p>
                <strong>Full Text</strong>
                <br />

                <%# Item.FullText %>
            </p>
            <p>
                <strong>Tags</strong>
                <br />

                <%# Item.Tags %>
            </p>
        </ItemTemplate>

        <EditItemTemplate>

            <asp:HiddenField runat="server" ID="PostID" Value='<%# Bind("PostID") %>'/>
            <asp:HiddenField runat="server" ID="CreatedOn" Value='<%# Bind("CreatedOn") %>'/>
            <asp:HiddenField runat="server" ID="CustomCSS" Value='<%# Bind("CustomCSS") %>'/>
            <asp:HiddenField runat="server" ID="CustomJavaScript" Value='<%# Bind("CustomJavaScript") %>'/>
            <asp:HiddenField runat="server" ID="Inactive" Value='<%# Bind("Inactive") %>'/>
            <asp:HiddenField runat="server" ID="PermanentURL" Value='<%# Bind("PermanentURL") %>'/>

            <h2>
                Edit Blog Post
            </h2>

            Title:
            <asp:TextBox runat="server" ID="BlogTitle" ClientIDMode="Static" Text='<%# Bind("Title") %>' />
            <br />

            Author:
            <asp:TextBox runat="server" ID="Author" ClientIDMode="Static" Text='<%# Bind("Author") %>' />
            <br />

            Text:
            <asp:TextBox runat="server" ID="FullText" ClientIDMode="Static" Text='<%# Bind("FullText") %>' TextMode="MultiLine" />
            <br />

            Tags:
            <asp:TextBox runat="server" ID="Tags" ClientIDMode="Static" Text='<%# Bind("Tags") %>' />
            <br />

            <asp:Button runat="server" CommandName="Update" Text="Update" />
            <asp:Button ID="Button1" runat="server" CommandName="Cancel" Text="Cancel" />

        </EditItemTemplate>

    </asp:FormView>

</asp:Content>

代码隐藏:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.AspNet.FriendlyUrls;
using Pritchard.Jumpstart.Common.Data.Services;
using Pritchard.Jumpstart.Webforms.Common;

namespace Pritchard.Jumpstart.Webforms.BlogPost
{
    public partial class Record : BasePage
    {

        protected void Page_Load(object sender, EventArgs e)
        {

            if (IsPostBack)
                return;

            var id = 0;
            var mode = "read";

            Int32.TryParse(Request.GetFriendlyUrlSegments().FirstOrDefault(), out id);
            mode = Request.QueryString["mode"];

            switch (mode)
            {
                case "read":
                    break;
                case "update":
                    BlogPostContainer.DefaultMode = FormViewMode.Edit;
                    break;
                case "insert":
                    break;
            }

            if (id != 0)
                Model = BlogPostService.Get(id);

        }

        public IEnumerable<Jumpstart.Common.Data.BlogPost> GetBlogPost()
        {
            var list = new List<Jumpstart.Common.Data.BlogPost>();
            var item = BlogPostService.Get( ((Jumpstart.Common.Data.BlogPost)Model).PostID);

            if (item != null)
                list.Add(item);

            return list;
        }

        public void UpdateBlogPost(Jumpstart.Common.Data.BlogPost blogPost)
        {
            BlogPostService.Update(blogPost);
        }

        public void InsertBlogPost(Jumpstart.Common.Data.BlogPost blogPost)
        {
            throw new NotImplementedException();
        }
    }
}

请注意,我必须将“模型”属性移动到 Session 中,因为 ViewState 没有保留它:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.AspNet.FriendlyUrls;

namespace Pritchard.Jumpstart.Webforms.Common
{

    public class BasePage : System.Web.UI.Page
    {

        public object Model
        {
            get { return Session["Model"]; }
            set { Session["Model"] = value; }
        }

    }

}

这里发生了什么?我真的希望只在 ListView 中使用新的 ASP.NET 4.5 模型绑定。现在我必须使用单独的数据源?为什么?

于 2013-07-01T17:23:40.170 回答