20

Używam Web.api i jedność, a ja otrzymuję następujący błąd, gdy próbuje otworzyć domyślny „help” Powierzchnia:typu String nie może być skonstruowana

[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 

jestem nowy i mam do jedności pewnie brakuje mi kroku (ów). W 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 (domyślne)

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) 
    { 

    } 
    } 

Moja próba web.config web.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> 

Czy zmierzam we właściwym kierunku?

Dzięki

Aktualizacja: 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 Próbuję dostępu: http: // hostname: port/Pomoc

+0

Co masz na swoim kontrolerze? (metoda konstruktora i akcji, do której próbujesz uzyskać dostęp). –

+0

Gdzieś w konfiguracji masz konstruktora, który przyjmuje ciąg znaków. – Steven

+0

@FelipeOriani Jest to domyślny helpcontroller z projektu web.api. Zaktualizuję pytanie, które należy uwzględnić. Akcja będzie "Indeks" –

Odpowiedz

23

Jako próbkę kodu, I” m przy założeniu, że jesteś na kontrolerze, a nie na kontrolerze API (z interfejsu sieciowego).

Twój kontroler api ma zależność od konstruktora od HttpConfiguration. Pojemnik prawdopodobnie nie ma tej definicji dla tego typu iw konsekwencji nie wie, jak go rozwiązać, a komunikat o błędzie powinien pochodzić z tego typu jako zależność. Polecam użyć klasy statycznej GlobalConfiguration i uzyskać dostęp do właściwości Configuration, aby uzyskać instancję HttpConfiguration. Można abstrakcyjne go w nieruchomości, dla próbki:

// 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"); 
    } 
} 

Teraz, jeśli jesteś na Api kontrolera, po prostu można uzyskać dostęp bezpośrednio właściwość this.Configuration że jest już na ApiController (klasa bazowa dla kontrolerów API) i uzyskać instancję HttpConfiguration.

37

Myślę, że lepszym sposobem jest dodanie atrybutu InjectionConstructor do domyślnego konstruktora. Ten atrybut zmusza jedność do używania dekorowanego konstruktora.

Przykład:

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

    [InjectionConstructor] 
    public HelpController() 
     : this(GlobalConfiguration.Configuration) 
    { 
    } 
+0

Awesome! Czyste i krótkie rozwiązanie. –

+0

Awesome rzeczywiście, pracował dla mnie. Dzięki! – Vishal

6

Powodem takiej sytuacji jest, ponieważ Unity będzie domyślnie wybrać, aby użyć konstruktora z większość parametrów w ten sposób pomija domyślny konstruktor.

Skomentuj dwa konstruktory istniejące w szablonie HelpController i dodaj domyślny konfigurator.

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

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

    public HelpController() 
    { 
     Configuration = GlobalConfiguration.Configuration; 
    } 
+2

Prosta i oczywista odpowiedź, która działa najlepiej, gdy wprowadzasz Unitu do projektu webapi. –

2

Rejestrowanie obiektu HttpConfiguration jako przykład w UnityContainer pomoże rozwiązać ten problem.
Wystarczy dodać, aby dodać poniższy wiersz podczas rejestracji w UnityContainer.

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

Pomoże Unity rozwiązać parametr config, gdy wywołuje konstruktor z parametrem.

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