ASP.NET MVC控制器有选择地抛出MissingMethodException [无法创建接口实例]

时间:2015-08-25 21:39:41

标签: c# asp.net asp.net-mvc-4 ninject

我在MVC 4应用程序中变得很奇怪(至少对我而言)。

我整个晚上都在谷歌上搜索;我也阅读了很多SO帖子 - 没有快乐;我知道我不能直接实例化接口。

在这个特定的应用程序中,我使用Ninject进行DI。 在控制器构造函数中,我实现了一个接口,并且此时一切都很好 - 实际上我相信Ninject或它的用法根本没有问题。

此外,我确信这段代码工作一次,之后没有引入任何更改,除非将Ninject库更新到3.2.2.0 - 无法记住之前的那个;显然年纪大了...

我在同一个控制器中有简单的CRUD操作,它占用了我的另一个WEB服务。 4种方法中有2种正常工作(LOL) - Index()Create()Update()Delete()会抛出上述异常;这里是堆栈跟踪:

[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) +119
    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) +11
    System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +183
    System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +563
    System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +416
    .
    .
    .

这是控制器,非常简单,真的......

public class NonFederalWorkingDayController : BaseController
{
    private readonly INonFederalWorkingDayManagementService _nonFederalWorkingDayService = null;

    public NonFederalWorkingDayController(INonFederalWorkingDayManagementService nonFederalWorkingDayService)
    {
        _nonFederalWorkingDayService = nonFederalWorkingDayService;
    }

    private JsonResultModel<IEnumerable<NonFederalWorkingDayDto>> InvokeService(Func<IEnumerable<NonFederalWorkingDayDto>, I9UserDto, IEnumerable<NonFederalWorkingDayDto>> operation, IEnumerable<NonFederalWorkingDayDto> models)
    {
        var result = new JsonResultModel<IEnumerable<NonFederalWorkingDayDto>>();

        if (ModelState.IsValid)
        {
            var modifier = new I9UserDto
            {
                Id = SiteContext.User.UserId
            };

            try
            {
                result.Model = operation(models, modifier);
                result.Message = "Operation completed successfully.";
            }
            catch (Exception ex)
            {
                result.HasError = true;
#if DEBUG
                result.Message = string.Concat("Operation failed: ", ex.Message);
#else
                result.Message = "Operation failed: Internal server error.";
#endif
            }

            if (result.Model != null)
            {
                foreach (var dto in result.Model)
                {
                    dto.CreatedOn = null;
                    dto.Creator = null;
                    dto.ModifiedOn = null;
                    dto.Modifier = null;
                }
            }
        }
        else
        {
            result.HasError = true;
            result.Message = "Invalid data.";
        }

        return result;
    }

    public ActionResult Index()
    {
        var model = _nonFederalWorkingDayService.Load();

        return View(model);
    }

    [HttpPost]
    public ActionResult Create(IEnumerable<NonFederalWorkingDayDto> models)
    {
        var result = InvokeService(_nonFederalWorkingDayService.Create, models);

        return Json(result);
    }

    [HttpPost]
    public ActionResult Update(IEnumerable<NonFederalWorkingDayDto> models)
    {
        var result = InvokeService(_nonFederalWorkingDayService.Update, models);

        return Json(result);
    }

    [HttpPost]
    public ActionResult Delete(IEnumerable<NonFederalWorkingDayDto> models)
    {
        var result = InvokeService(_nonFederalWorkingDayService.Delete, models);

        if (!result.HasError)
        {
            var plurality = models.Count() == 1 ? "Entity" : "Entities";
            result.Message = string.Concat(plurality, " deleted successfully.");
        }

        return Json(result);
    }
}

正如我所提到的,问题在于最后两种方法:Update()Delete()。事实上,执行永远不会进入其中任何一个 - 在模型绑定期间错误会增加。但请注意除了IEnumerable<>之外没有接口,它们在同一个应用程序中的其他方法中绑定得很好,包括此控制器中的Create()方法。我不确定究竟有多确切,但DefaultBinder似乎很聪明,可以确定IEnumerable实际上是List。所以这不应该是它,是吗?

另外,我需要提一下,我通过AJAX调用这些操作,而不是正常的请求。这有关系吗?

我似乎无法弄清楚出了什么问题......请帮忙!

更新

我已继承DefaultModelBinder以挂钩到模型绑定管道。所以我迷上了BindModel()controllerContext.Controller实际上是NonFederalWorkingDayController

的完全功能实例

更新2

以下是NonFederalWorkingDayDto的代码清单:

public class NonFederalWorkingDayDto : DtoBase, INonFederalWorkingDay
{
    public static NonFederalWorkingDayDto Consume(INonFederalWorkingDay Donor)
    {
        NonFederalWorkingDayDto result = null;

        if (Donor != null)
        {
            result = DtoBase.Consume<NonFederalWorkingDayDto>(Donor);

            result.Description = Donor.Description;
            result.FallsOn = Donor.FallsOn;
            result.Id = Donor.Id;
            result.Name = Donor.Name;
        }

        return result;
    }

    public string Description { get; set; }

    public DateTime? FallsOn { get; set; }

    public string Name { get; set; }

    #region INonFederalWorkingDay support

    DateTime INonFederalWorkingDay.FallsOn
    {
        get { return FallsOn ?? default(DateTime); }
    }

    int IIdentifier<int>.Id
    {
        get { return Id ?? default(int); }
    }

    #endregion
}

1 个答案:

答案 0 :(得分:0)

我认为您的行动声明是问题,请尝试:

[HttpPost]
public ActionResult Create(List<NonFederalWorkingDayDto> models)
{
    ...
}

[HttpPost]
public ActionResult Update(List<NonFederalWorkingDayDto> models)
{
    ...
}

[HttpPost]
public ActionResult Delete(List<NonFederalWorkingDayDto> models)
{
    ...
}

真的解释是在消息中,即它不能创建接口的实例,因为你说构造函数很酷,所以问题在于IEnumerable,它需要是一个具体的可枚举类(如List for例子)。