【问题标题】:The type String cannot be constructed. You must configure the container to supply this value无法构造 String 类型。您必须配置容器以提供此值
【发布时间】:2015-12-23 13:51:39
【问题描述】:

我查看了几个关于如何为 MVC 5 项目实现统一的教程和 stackoverflow 问题,但我似乎无法克服这个错误:

无法构造字符串类型。您必须配置容器以提供此值。

我安装了 NuGet 包 Unity.Mvc5,并在统一配置中注册了我的类型。我还在 unityconfig 文件中调用了 register components 方法。

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>();
        container.RegisterType<IStateService, StateService>();

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }
}

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    UnityConfig.RegisterComponents();
}

public class StateController : Controller
{
    private readonly IStateService stateService;

    public StateController(IStateService stateService)
    {
        this.stateService = stateService;
    }

    // GET: /State/
    public ActionResult Index()
    {
        return View(stateService.GetStates());
    }
}

public interface IStateService : IDisposable
{
    IEnumerable<State> GetStates();
}

public class StateService : IStateService
{
    private MyAppDbContext context;
    public StateService() : this(new MyAppDbContext()){}

    public StateService(MyAppDbContext context)
    {
        this.context = context;
    }

    private IQueryable<State> All()
    {
        return context.States;
    }

    public IEnumerable<State> GetStates()
    {
        return this.All().ToList();           
    }

    public void Dispose()
    {
        context.Dispose();
    }
}

这是堆栈跟踪:


[InvalidOperationException: The type String cannot be constructed. You must configure the container to supply this value.]
   Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.GuardTypeIsNonPrimitive(IBuilderContext context) +311
   Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context) +229
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +274
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, NamedTypeBuildKey buildKey) +162
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +245
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +274
   Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +250
   Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +101
   lambda_method(Closure , IBuilderContext ) +215
   Microsoft.Practices.ObjectBuilder2.c__DisplayClass1.b__0(IBuilderContext context) +71
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +333
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +274
   Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +250
   Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +101
   lambda_method(Closure , IBuilderContext ) +205
   Microsoft.Practices.ObjectBuilder2.c__DisplayClass1.b__0(IBuilderContext context) +71
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +333
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +274
   Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +250
   Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +101
   lambda_method(Closure , IBuilderContext ) +209
   Microsoft.Practices.ObjectBuilder2.c__DisplayClass1.b__0(IBuilderContext context) +71
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +333
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +274
   Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +383

[ResolutionFailedException: Resolution of the dependency failed, type = "MyApp.MVC.Controllers.StateController", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type String cannot be constructed. You must configure the container to supply this value.
-----------------------------------------------
At the time of the exception, the container was:

  Resolving MyApp.MVC.Controllers.StateController,(none)
  Resolving parameter "stateService" of constructor MyApp.MVC.Controllers.StateController(MyApp.Service.Services.IStateService stateService)
    Resolving MyApp.Service.Services.StateService,(none) (mapped from MyApp.Service.Services.IStateService, (none))
    Resolving parameter "context" of constructor MyApp.Service.Services.StateService(MyApp.Data.DAL.MyAppDbContext context)
      Resolving MyApp.Data.DAL.MyAppDbContext,(none)
      Resolving parameter "connectionString" of constructor MyApp.Data.DAL.MyAppDbContext(System.String connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model)
        Resolving System.String,(none)
]
   Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +446
   Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides) +50
   Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) +48
   Microsoft.Practices.Unity.UnityContainerExtensions.Resolve(IUnityContainer container, Type t, ResolverOverride[] overrides) +61
   Unity.Mvc5.UnityDependencyResolver.GetService(Type serviceType) +140
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +87

[InvalidOperationException: An error occurred when trying to create a controller of type 'MyApp.MVC.Controllers.StateController'. Make sure that the controller has a parameterless public constructor.]
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +247
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +438
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +257
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +326
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +157
   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

我可能做错了什么?

更新

我在 UnityConfig 类的 RegisterComponents 方法中添加了以下代码,它似乎可以正常工作:

container.RegisterInstance<StateService>(new StateService());

没有一个教程显示需要这个,我觉得我的示例案例我使用它非常标准。 我为什么需要这条线?我对 Unity 还不是很了解,所以我仍然很好奇。

【问题讨论】:

  • 这个错误什么时候/在哪里发生?
  • 我刚刚添加了堆栈跟踪,但它发生在 StateController 中。
  • StateService 的代码是什么样的?
  • 它正在工作,因为您强制 Unity 使用没有 ctor 参数的 StateService。默认情况下,DI 容器是贪婪的,并且会采用具有最多参数的 ctor。在您的情况下,具有 EF 上下文的那个将失败。
  • @vidalsasoon 它确实有效,因为我真正想要使用的上下文 ctor 是空的。空 ctor 将我的连接字符串(来自静态类)传递给接受一个参数(字符串 connectionString)的基本 ctor。我想我只是要回到我最初的方式,并删除接受参数的 ctor,因为我无论如何都不会使用它们。它们是从 EF POCO 生成器生成的。感谢您的帮助!

标签: c# asp.net-mvc entity-framework asp.net-mvc-5 unity-container


【解决方案1】:

我在任何地方都没有看到这个答案,所以我也想添加这个。在我看来,您的 StateService 对象上有多个构造函数。因此,Unity 正在选择具有最多参数的构造函数(如 cmets 中所述)。

你调用告诉 Unity 使用 InjectionConstructor 使用哪个构造函数。

下面告诉它使用无参数构造函数。

container.RegisterType&lt;IStateService, StateService&gt;(new InjectionConstructor());

或者你也可以告诉它使用一个类型。

container.RegisterType<IStateService, StateService>(new InjectionConstructor(<some type>))

这将强制 Unity 使用所需的构造函数。

【讨论】:

    【解决方案2】:

    您的 StateService 正在尝试解析“上下文”。我建议您将上下文排除在 DI 映射之外,以便将其排除在您要解析的构造函数之外。

    Resolving parameter "context" of constructor MyApp.Service.Services.StateService(MyApp.Data.DAL.MyAppDbContext context)
    

    【讨论】:

    • 我的上下文不在我的映射中。我拥有的唯一映射是从 IStateService 到 StateService。我是不是误会你的意思了?
    • @user2023116 默认情况下,Unity 注册所有类型,因此它会在调用 StateService(MyAppDbContext context) 时尝试创建 MyAppDbContext 的实例(因为它是隐式注册的)。我假设MyAppDbContext 有一些构造函数的字符串参数(因此无法解析)。
    • @AlexeiLevenkov 如果隐式注册,我如何将上下文从 DI 映射中排除?我是否将我的上下文接口注入到服务中?
    • 一般规则:除非是接口,否则不要在构造函数中注入任何内容。从您的 StateService ctor 中删除“MyAppDbContext context”,它应该很好。如果您需要上下文,请在此处使用它:msdn.microsoft.com/en-ca/data/jj729737.aspx。基本上,不要注入你的 EF 上下文,因为它是一罐蠕虫。将其隐藏在您的服务中。
    • @user2023116 您应该就此提出单独的问题。同样在这样做之前,请确保您了解所涉及的每个依赖项的生命周期(例如“我希望上下文为单个 Web 请求而存在”)。
    猜你喜欢
    • 1970-01-01
    • 2012-02-09
    • 2012-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多