首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MVC - IoC统一-确保控制器有一个无参数的公共构造函数

MVC - IoC统一-确保控制器有一个无参数的公共构造函数
EN

Stack Overflow用户
提问于 2015-10-14 10:04:57
回答 4查看 16.6K关注 0票数 5

问题

我使用Unity作为IoC,这很好,但是随着我不断添加功能,发现任何错误变得越来越困难,因为团结提供了一个错误,它是错误的症状,而不是实际错误:

代码语言:javascript
运行
复制
"Message":"An error has occurred.","ExceptionMessage":"An error occurred
when trying to create a controller of type 'MyController'. Make sure that the
controller has a parameterless public
constructor.","ExceptionType":"System.InvalidOperationException"

背景

我有一个MVC Web Api控制器,它依赖Manager实例(来自域):

代码语言:javascript
运行
复制
public class MyController : ApiController
{
    private IMyManager MyManager { get; set; }

    public MyController(IMyManager myManager)
    {
        this.MyManager = myManager;
    }

    ...
}

发生上述错误是因为IoC映射IMyManager失败。当它失败时,我没有参数,这意味着MyController是使用无参数构造函数调用的,但是由于它不存在(而且不应该),所以我得到了上面的错误。

我已经尝试过的

所以,我得到的错误不是“真正的”错误。显而易见的是要确保每个新的实现都在IoC下注册,我检查了它们。我手动做这件事是为了保持事情的可管理性(噢,讽刺!)

我就是这样做的:

代码语言:javascript
运行
复制
container.RegisterType<IMyManager, MyManager>();

但是,这不是问题所在。

我做的一个解决办法是循环依赖。我将所有涉及的构造函数和方法更改为使用属性值,而不是实例。我检查了所有涉及的类,不再存在任何循环依赖关系。

然而,问题仍然存在。

问题

我怎样才能找出实际的问题呢?手动检查依赖关系的开销太大,因为该结构是一个复杂的更深层次依赖关系的网络。随着应用程序的成熟,情况会变得更糟。

或者,如果联合总是掩盖这些消息(而无法修复),那么是否有其他方法确实提供了有价值的错误信息?

更新

对于每个请求,完整的错误消息(虽然我不认为堆栈跟踪非常有用):

代码语言:javascript
运行
复制
{"Message":"An error has occurred.","ExceptionMessage":"An error occurred when trying to create a controller of type 'MyController'. Make sure that the controller has a parameterless public constructor.","ExceptionType":"System.InvalidOperationException","StackTrace":"   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()","InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Type 'MyProject.Web.Api.Controllers.MyController' does not have a default constructor","ExceptionType":"System.ArgumentException","StackTrace":"   at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"}}

更新2

我进行了更深入的研究,检查了所有的依赖项(它们非常庞大),但是所有的东西都被正确地注册和加载。也没有任何循环依赖,所以据我所能告诉‘应该’工作。因为这不是我的结论,有一些错误发生了,但没有被抛出。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-10-15 15:09:50

我发现了它,问题是我正在以相同的解决方案重新编译现有的代码,这意味着会有相同名称的重复文件。

在这个特定的例子中,我有一个与以前存在的接口完全相同的接口。在代码的某个地方,我使用了错误的命名空间,这意味着IoC映射是不正确的。

所以,就像这样:

我有:

代码语言:javascript
运行
复制
old.managers.IMyManager

代码语言:javascript
运行
复制
new.managers.IMyManager

我在地图上所做的是:

代码语言:javascript
运行
复制
container.RegisterType<IMyManager, MyManager>();

在本例中,IMyManager是new.managers.IMyManager,这是应该的。

这种依赖关系的使用者之一期望命名空间的IMyManager (名称空间old.managers )。

更新使用者以使用新的命名空间修复它。

票数 2
EN

Stack Overflow用户

发布于 2015-10-14 10:34:02

如果错误说您需要一个无参数的构造函数,那么这就意味着WebAPI没有注册,即使它是为您的ASP.NET MVC应用程序注册的。如果您的IoC工作正常,它不应该需要一个无参数的构造函数,因为它应该能够解决控制器构造函数中存在的依赖关系。

WebAPI有自己的通往ASP.NET MVC的管道--例如,WebAPI可以托管在own上,因此即使它们存在于同一个项目中,也需要单独连接。

您应该将WebAPI连接到UnityConfig中的依赖项解析器,我相信这里有一个示例:http://www.devtrends.co.uk/blog/using-unity.mvc5-and-unity.webapi-together-in-a-project

代码语言:javascript
运行
复制
using Microsoft.Practices.Unity;
using System.Web.Http;
using System.Web.Mvc;

namespace WebApplication1
{
    public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers

            // e.g. container.RegisterType<ITestService, TestService>();

            // Configures container for ASP.NET MVC
            DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));

            // Configures container for WebAPI
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
    }
}

在上面的示例中,有两行用于配置,但它们共享相同的容器,因此也共享相同的绑定--您不必对它们进行两次定义。如果您曾经将WebAPI项目与ASP.NET MVC项目分开,那么您就必须有一个单独的容器和绑定。

根据我的经验,在发现问题,或者对您隐藏错误的统一方面,情况并非如此。您所遇到的错误直接来自ASP.NET MVC。在没有IoC的正常使用中,您需要一个无参数的构造函数.使用IoC,它控制控制器的创建,从而解决依赖关系。

票数 9
EN

Stack Overflow用户

发布于 2020-11-27 15:05:24

别忘了这一点在你的web.config

代码语言:javascript
运行
复制
<system.web>
    <compilation targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
    <customErrors mode="Off" />
</system.web>

缺少httpRuntime targetFramework="4.8“部分将导致无参数公共构造函数错误

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33122410

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档