KendoUI网格不会触发saveChanges事件(System.MissingMethodException:无法创建接口的实例。)

时间:2014-09-16 01:31:20

标签: asp.net-mvc kendo-grid model-binding kendo-asp.net-mvc custom-model-binder

KendoUI网格不会触发SaveChanges事件。 当我运行项目并单击SaveChanges按钮但没有触发SaveChanges事件时,我在Visual Studio 2013环境和浏览器(FF,IE,Chrome)中没有看到任何问题。 为了进一步调查,我使用了Chrome的调试器,我发现了一个问题。请查看问题,错误日志和代码的图片。 (我使用过JQuery v1.10) 请帮我解决一下。

编辑:

我了解该错误与[Bind(Prefix = "models")]有关。当我删除它时, Editing_Update会被触发,但articles对象为空。我该如何解决?

Server Error in '/' Application.

Cannot create an instance of an interface.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.MissingMethodException: Cannot create an instance of an interface.

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 

[MissingMethodException: Cannot create an instance of an interface.]   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232   System.Activator.CreateInstance(Type type, Boolean nonPublic) +83   System.Activator.CreateInstance(Type type) +66   System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +460   System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1137   System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +633   System.Web.Mvc.DefaultModelBinder.UpdateCollection(ControllerContext controllerContext, ModelBindingContext bindingContext, Type elementType) +555   System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +2486   System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +633   System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +495   System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +199   System.Web.Mvc.Async.<>c__DisplayClass1e.<BeginInvokeAction>b__16(AsyncCallback asyncCallback, Object asyncState) +1680   System.Web.Mvc.Async.WrappedAsyncResult`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +59   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +94   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +525   System.Web.Mvc.Controller.<BeginExecuteCore>b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +82   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +73   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +105   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +595   System.Web.Mvc.Controller.<BeginExecute>b__14(AsyncCallback asyncCallback, Object callbackState, Controller controller) +47   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +65   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +139   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +484   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +50   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__3(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +98   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +73   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +106   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +446   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +88   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +50   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

First Picture of Problem

Second Picture of Problem

我的控制器的一部分:

[Authorize(Roles = "Administrator")]
    public class ArticleAdminController : MVCController
    {
    private JahanBlogDbContext db = DataContextFactory.GetDataContext();
    private readonly IArticleRepository _articleAdminRepository;
    public ArticleAdminController(IArticleRepository articleRepository)
    {
        _articleAdminRepository = articleRepository;
    }

    public ArticleAdminController()
        : this(new ArticleRepository())
    {
    }

    // GET: ArticleAdmin
    public ActionResult Index([DataSourceRequest] DataSourceRequest request)
    {
        IEnumerable<ArticleViewModel> instance = new ArticleViewModel().FindByCriteria();
        return View(instance);
    }

    public ActionResult Editing_Read([DataSourceRequest] DataSourceRequest request)
    {
        List<ArticleViewModel> instance = new ArticleViewModel().FindByCriteria().ToList();
        DataSourceResult dsRequest = instance.ToDataSourceResult(request);
        return Json(dsRequest, JsonRequestBehavior.AllowGet);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Editing_Update([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<ArticleViewModel> articles)
    {
        if (articles != null && ModelState.IsValid)
        {
            using (new EFUnitOfWorkFactory().Create())
            {
                foreach (ArticleViewModel articleViewModel in articles)
                {
                    var art = new Article
                    {
                        Id = articleViewModel.Id,
                        IsActive = articleViewModel.IsActive,
                        IsActiveNewComment = articleViewModel.IsActiveNewComment,
                        Title = articleViewModel.Title,
                    };
                    _articleAdminRepository.Update(art);
                }
            }
        }
        DataSourceResult result = articles.ToDataSourceResult(request, ModelState);
        return Json(result);

    }
   // ....
  }

根据上面的代码,当我点击SaveChanges按钮时,Editing_Update必须是火,但没有发生!!

我的网格:

@using Jahan.Blog.ViewModel
@using Kendo.Mvc.UI
@using Jahan.Blog.Web.Mvc.HtmlHelpers
@using Kendo.Mvc.UI.Fluent
@model IEnumerable<ArticleViewModel>
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<div style="width: 100%;">
    @(Html.Kendo().Grid<Jahan.Blog.ViewModel.ArticleViewModel>()
          .Name("ArticleAdmin").Navigatable()
          .Resizable(c => c.Columns(true))
          .HtmlAttributes(new { @class = "cursorLink", @style = "width: 1600px;height:auto;overflow: scroll;" })
          .Columns(columns =>
          {
              columns.Template(x => { }).ClientTemplate("<a href='" + Url.Action("Details", "ArticleAdmin") + "/#=Id#'>Details</a>").Width(60);
              columns.Bound(p => p.Id).Title("Article Id").Width(75);
              columns.Bound(p => p.Owner).Title("Writer").Width(70);
              columns.Bound(p => p.Title).Width(200);
              columns.Bound(p => p.IsActive).Encoded(false).ClientTemplate("<img src='/Content/#= IsActive ? 'tick.png' : 'cross.png' #''>").Width(80);
              columns.Bound(p => p.IsActiveNewComment).Encoded(false).ClientTemplate("#= showActivationStatusIcon(IsActiveNewComment) #").Width(170);
              columns.Bound(p => p.Tags).ClientTemplate("#= ShowTagsInGridView(Tags) #").Width(200);
              columns.Bound(p => p.NumberOfComments).Title("No. Comments").Width(115);
              columns.Bound(p => p.LikeCounter).Title("No. Like").Width(70);
              columns.Bound(p => p.RateCounter).Title("Rate").Width(60);
              columns.Bound(p => p.CreatedDate).Format("{0:G}").Width(160);
              columns.Bound(p => p.ModifiedDate).Format("{0:G}").Width(160);
              columns.Command(command => command.Destroy()).Width(170);
          })
          .ToolBar(toolbar =>
          {
              toolbar.Create();
              toolbar.Save();
          })
          .Editable(editable => editable.Mode(GridEditMode.InCell))
          .Pageable()
          .Navigatable()
          .Sortable()
          .Scrollable()
          .DataSource(dataSource => dataSource
              .Ajax()
              .Batch(true)
              .PageSize(10)
              .ServerOperation(false)
              .Events(events => events.Error("error_handler"))
              .Model(model =>
              {
                  model.Id(p => p.Id);
                  model.Field(p => p.Id).Editable(false);
                  model.Field(p => p.Tags).Editable(false);
                  model.Field(p => p.Owner).Editable(false);
                  model.Field(p => p.LikeCounter).Editable(false);
                  model.Field(p => p.RateCounter).Editable(false);
                  model.Field(p => p.CreatedDate).Editable(false);
                  model.Field(p => p.ModifiedDate).Editable(false);
              })
              .Create("Editing_Create", "ArticleAdmin")
              .Read(read => read.Action("Editing_Read", "ArticleAdmin"))
              .Update(update => update.Action("Editing_Update", "ArticleAdmin"))
              .Destroy(delete => delete.Action("Editing_Destroy", "ArticleAdmin"))
          ))
</div>

<script type="text/javascript">

    function error_handler(e) {
        if (e.errors) {
            var message = "Errors:\n";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            alert(message);
        }
    }

</script>

我的ViewModel:

namespace Jahan.Blog.ViewModel
{
    public class ArticleViewModel : IArticleViewModel
    {
    public ArticleViewModel()
    {

    }
    public virtual int Id { get; set; }
    public virtual int? UserId { get; set; }

    public virtual string Title { get; set; }

    public virtual string Summary { get; set; }

    public virtual string Description { get; set; }

    public virtual decimal? RateCounter { get; set; }

    public virtual int? LikeCounter { get; set; }

    public virtual bool IsActive { get; set; }

    public virtual bool IsActiveNewComment { get; set; }

    public virtual IList<Comment> Comments { get; set; }

    public virtual ISet<Rating> Ratings { get; set; }

    public virtual IList<AttachmentFile> AttachmentFiles { get; set; }

    public virtual IList<ArticleTag> ArticleTags { get; set; }

    public virtual ISet<ArticleLike> ArticleLikes { get; set; }

    public virtual DateTime? CreatedDate { get; set; }

    public virtual DateTime? ModifiedDate { get; set; }

    //[UIHint("_TagsOfArticle")]
    public List<TagGridViewModel> Tags { get; set; }
    public virtual int NumberOfComments { get; set; }

    public virtual string Owner { get; set; }

    private IQueryable<ArticleViewModel> QueryBuilder()
    {
        ArticleRepository repository = new ArticleRepository();
        IQueryable<ArticleViewModel> query = repository.FindAll().Select(article => new ArticleViewModel
        {
            Id = article.Id,
            //AttachmentFiles = article.AttachmentFiles.Where(a => a.ArticleId == article.Id).Distinct().ToList(),
            //Comments = article.Comments.Where(c => c.ArticleId == article.Id).ToList(),
            CreatedDate = article.CreatedDate,
            Description = article.Description,
            IsActive = article.IsActive,
            IsActiveNewComment = article.IsActiveNewComment,
            LikeCounter = article.LikeCounter,
            ModifiedDate = article.ModifiedDate,
            NumberOfComments = article.Comments.Count(c => c.ArticleId == article.Id),
            RateCounter = article.RateCounter,
            Summary = article.Summary,
            Title = article.Title,
            UserId = article.UserId,
        });
        return query;
    }

    public virtual IQueryable<ArticleViewModel> QueryBuilderByCriteria(Expression<Func<ArticleViewModel, bool>> predicate = null, params Expression<Func<ArticleViewModel, object>>[] includeProperties)
    {
        IQueryable<ArticleViewModel> items = QueryBuilder();
        if (includeProperties != null)
        {
            foreach (Expression<Func<ArticleViewModel, object>> includeProperty in includeProperties)
            {
                items = items.Include(includeProperty);
            }
        }
        if (predicate != null)
            return items.Where(predicate);
        return items;
    }

    public virtual IEnumerable<ArticleViewModel> FindByCriteria(Expression<Func<ArticleViewModel, bool>> predicate = null, params Expression<Func<ArticleViewModel, object>>[] includeProperties)
    {
        List<ArticleViewModel> result = new List<ArticleViewModel>();
        var query = QueryBuilderByCriteria(predicate, includeProperties);
        foreach (var articleViewModel in query)
        {
            articleViewModel.Tags = TagGridViewModel.GetByArticleId(articleViewModel.Id); 
            articleViewModel.Owner = AppUserStore.Instance.FindByIdAsync(int.Parse(articleViewModel.UserId.ToString())).Result.UserName;
            result.Add(articleViewModel);
        }
        return result;
    }

    public virtual ArticleViewModel FindByArticleId(int articleId)
    {
        ArticleViewModel result = QueryBuilder().FirstOrDefault(a => a.Id == articleId);
        return result;
    }
}
}

2 个答案:

答案 0 :(得分:0)

首先,从您提供的图片中可以清楚地看到,Save Changes会触发Editing_Update方法。只有您获得代码500,这意味着您的服务器在处理数据时会抛出异常。 我的建议是在Editing_Update方法的第一行代码和F10中设置断点,直到找到触发它的内容为止。 祝你好运

答案 1 :(得分:0)

我为它创建了一个自定义模型绑定器。

public class ArticleViewModelBinder : BaseModelBinder<ArticleViewModel>
{
}

BaseModelBinder类:

public class BaseModelBinder<TModel> : IModelBinder where TModel : class, new()
    {
        public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            TModel model = (TModel)bindingContext.Model ?? new TModel();
            ICollection<string> propertyNames = bindingContext.PropertyMetadata.Keys;
            foreach (var propertyName in propertyNames)
            {
                var value = GetValue(bindingContext, propertyName);
                model.SetPropertyValue(propertyName, value);
            }
            return model;
        }

        private string GetValue(ModelBindingContext context, string name)
        {
            name = (context.ModelName == "" ? "" : context.ModelName + ".") + name;

            ValueProviderResult result = context.ValueProvider.GetValue(name);
            if (result == null || result.AttemptedValue == "")
            {
                return "<Not Specified>";
            }
            else
            {
                return (string)result.AttemptedValue;
            }
        }
    }

助手类: 在助手课程中,我使用了FastMember

public static class Miscellaneous
    {
        public static void SetPropertyValue(this object obj, string property, object value, bool usingByFastMember = true)
        {
            switch (usingByFastMember)
            {
                case true:
                    var wrapped = ObjectAccessor.Create(obj);
                    var properyType = obj.GetType().GetProperty(property).PropertyType;
                    var val = ChangeType(value, properyType);//Convert.ChangeType(value, properyType);
                    wrapped[property] = val;
                    break;
                case false:
                    PropertyInfo prop = obj.GetType().GetProperty(property, BindingFlags.Public | BindingFlags.Instance);
                    if (prop != null && prop.CanWrite)
                    {
                        prop.SetValue(obj, value, null);
                    }
                    break;
            }
        }

        public static object ChangeType(object value, Type conversion)
        {
            object result = null;
            var t = conversion;

            if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                if (value == null)
                {
                    return null;
                }
                t = Nullable.GetUnderlyingType(t); ;
            }
            try
            {
                result = Convert.ChangeType(value, t);
            }
            catch (Exception)
            {
                return null;
            }
            return result;
        }
    }