web-dev-qa-db-ja.com

文字列型を作成できません

Web.apiとUnityを使用していますが、デフォルトの「ヘルプ」領域を開こうとすると、次のエラーが発生します。

[InvalidOperationException: The type String cannot be constructed. You must configure the      container to supply this value.]
Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.GuardTypeIsNonPrimitive(IBuilderContext context, SelectedConstructor selectedConstructor) +280
Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context) +356
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +260
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, NamedTypeBuildKey buildKey) +205
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +231
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +260
   Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +250
   Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +101
   BuildUp_System.Web.Http.HttpRouteCollection(IBuilderContext ) +202
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +319
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +260
   Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +250
   Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +101
   BuildUp_System.Web.Http.HttpConfiguration(IBuilderContext ) +202
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +319
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +260
   Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +250
   Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +101
   BuildUp_API.Areas.HelpPage.Controllers.HelpController(IBuilderContext ) +204
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +42
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +319
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +260
   Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +373


[ResolutionFailedException: Resolution of the dependency failed, type = "API.Areas.HelpPage.Controllers.HelpController", 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 API.Areas.HelpPage.Controllers.HelpController,(none)
  Resolving parameter "config" of constructor API.Areas.HelpPage.Controllers.HelpController(System.Web.Http.HttpConfiguration config)
Resolving System.Web.Http.HttpConfiguration,(none)
Resolving parameter "routes" of constructor System.Web.Http.HttpConfiguration(System.Web.Http.HttpRouteCollection routes)
  Resolving System.Web.Http.HttpRouteCollection,(none)
  Resolving parameter "virtualPathRoot" of constructor System.Web.Http.HttpRouteCollection(System.String virtualPathRoot)
    Resolving System.String,(none)
]
   Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +436
   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.Mvc4.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     'API.Areas.HelpPage.Controllers.HelpController'. 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) +226
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +326
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +177
   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

私は団結に不慣れであり、私はステップを逃していると確信しています。 webapiconfig.csの場合:

public static void Register(HttpConfiguration config)
{
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );

    //Custom formatter
    config.Formatters.Clear();
    config.Formatters.Add(new JSONPFormater());

    config.EnableSystemDiagnosticsTracing();

    //Setup DI
    Bootstrapper.Initialise();
}

Bootstraper.cs(デフォルト値)

public static class Bootstrapper
  {
    public static IUnityContainer Initialise()
    {
      var container = BuildUnityContainer();

      DependencyResolver.SetResolver(new UnityDependencyResolver(container));

      return container;
    }

    private static IUnityContainer BuildUnityContainer()
    {
      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>();    
      RegisterTypes(container);

      return container;
    }

    public static void RegisterTypes(IUnityContainer container)
    {

    }
  }

Web.configweb.configでの私の試み

 <configSections>
    <!-- For more information on Entity Framework configuration, visit        http://go.Microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework"     type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="unity"  type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <connectionStrings>
    <add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-API-20130708152001;Integrated     Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-API-20130708152001.mdf" />
    <add name="<REMOVED>DBEntities" connectionString="metadata=res://*/Models.DAL.<REMOVED>.csdl|res://*/Models.DAL.<REMOVED>.ssdl|res://*/Models.DAL.<REMOVED>.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=<REMOVED>;initial catalog=<REMOVED>;persist security info=True;user id=<REMOVED>;password=<REMOVED>;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
<!--unity setting-->
<unity>
    <containers>
        <types>
            <register type="API.Areas.HelpPage.Controllers.HelpController, API">
                <constructor>
                    <param valu=""></param>
            </constructor>
            </register>
        </types>
    </containers>
</unity>

私は正しい方向に向かっていますか?

ありがとう

更新:helpcontroller.cs:

public class HelpController : Controller
    {
        public HelpController()
            : this(GlobalConfiguration.Configuration)
        {
        }

        public HelpController(HttpConfiguration config)
        {
            Configuration = config;
        }

        public HttpConfiguration Configuration { get; private set; }

        public ActionResult Index()
        {
            return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
        }

        public ActionResult Api(string apiId)
        {
            if (!String.IsNullOrEmpty(apiId))
            {
                HelpPageApiModel apiModel = Configuration.GetHelpPageApiModel(apiId);
                if (apiModel != null)
                {
                    return View(apiModel);
                }
            }

            return View("Error");
        }
    }

アクセスしようとしているURL:http:// hostname:port/Help

21
Daniel M

コードサンプルとして、(Web APIからの)APIコントローラーではなくコントローラーを使用していることを前提としています。

APIコントローラーは、HttpConfigurationのコンストラクターに依存しています。コンテナにはおそらくこのタイプのこの定義がないため、解決方法がわからないため、エラーメッセージのstringは依存関係としてこのタイプから取得されるはずです。 GlobalConfiguration静的クラスを使用し、ConfigurationプロパティにアクセスしてHttpConfigurationインスタンスを取得することをお勧めします。サンプルとして、プロパティで抽象化できます。

// include this namespace
using System.Web.Http;

public class HelpController : Controller
{
    // remove the constructors...

    // property
    protected static HttpConfiguration Configuration
    {
        get { return GlobalConfiguration.Configuration; }
    }

    public ActionResult Index()
    {
        return View(this.Configuration.Services.GetApiExplorer().ApiDescriptions);
    }

    public ActionResult Api(string apiId)
    {
        if (!String.IsNullOrEmpty(apiId))
        {
            HelpPageApiModel apiModel = this.Configuration.GetHelpPageApiModel(apiId);
            if (apiModel != null)
            {
                return View(apiModel);
            }
        }

        return View("Error");
    }
}

これで、Apiコントローラーを使用している場合は、すでにApiController(Apiコントローラーの基本クラス)にあるthis.Configurationプロパティに直接アクセスして、HttpConfigurationのインスタンスを取得できます。

23
Felipe Oriani

より良い方法は、InjectionConstructor属性をデフォルトのコンストラクターに追加することだと思います。この属性により、Unityは装飾されたコンストラクターを使用するように強制されます。

例:

public class HelpController : Controller
{
    private const string ErrorViewName = "Error";

    [InjectionConstructor]
    public HelpController()
        : this(GlobalConfiguration.Configuration)
    {
    }
39
user3221409

これが発生する理由は、Unityがデフォルトで最も多くのパラメーターを持つコンストラクターを使用することを選択するため、デフォルトのコンストラクターをバイパスするためです。

HelpControllerテンプレートに存在する2つのコンストラクターをコメントアウトし、構成を設定するデフォルトのコンストラクターを追加します。

    //public HelpController()
    //    : this(GlobalConfiguration.Configuration)
    //{
    //}

    //public HelpController(HttpConfiguration config)
    //{
    //    Configuration = config;
    //}

    public HelpController()
    {
        Configuration = GlobalConfiguration.Configuration;
    }
6
Always Learning

HttpConfigurationオブジェクトをインスタンスとしてUnityContainerに登録すると、問題の解決にも役立ちます。
UnityContainerに登録するときに、以下の行を追加するために追加する必要があります。

public static void RegisterTypes(IUnityContainer container) {
    container.RegisterInstance<HttpConfiguration>(GlobalConfiguration.Configuration);
}

これは、Unityがパラメーターを使用してコンストラクターを呼び出すときに、configパラメーターを解決するのに役立ちます。

public HelpController(HttpConfiguration config) {
    Configuration = config;
}
3
Boney

最近、以前に機能していたコードベースでこのエラーが発生しました。次の答えは、私がそれを修正するために何をしたかを示しています。

既存のMVCプロジェクトへのWeb APIおよびAPIドキュメントの追加

基本的に、コンストラクターはprotectedではなくパラメーターpublicで作成します。

1
Carl