20

Tôi đang sử dụng Web.api và Unity và tôi nhận được lỗi sau khi cố gắng mở mặc định "giúp đỡ" tích:Các kiểu String không thể được xây dựng

[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 

Tôi mới để thống nhất và tôi chắc chắn tôi đang thiếu (các) bước. Trong 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 (giá trị mặc định)

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

    } 
    } 

nỗ lực của tôi tại một 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> 

Tôi có đi đúng hướng không ??

Cảm ơn

Cập nhật: 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 Tôi cố gắng để truy cập: http: // hostname: port/Help

+0

Bạn có gì trên bộ điều khiển của mình? (phương thức khởi tạo và phương thức hành động mà bạn đang cố truy cập). –

+0

Một nơi nào đó trong cấu hình của bạn, bạn có một hàm tạo trong chuỗi. – Steven

+0

@FelipeOriani Đây là bộ điều khiển trợ giúp mặc định từ dự án web.api. Tôi sẽ cập nhật câu hỏi để đưa vào. Hành động sẽ là "Chỉ mục" –

Trả lời

23

Như mẫu mã của bạn, tôi m giả sử bạn đang ở trên một Controller và không phải là một bộ điều khiển API (từ api web).

Bộ điều khiển api của bạn có sự phụ thuộc vào hàm tạo từ HttpConfiguration. Thùng chứa có thể không có định nghĩa này cho loại này và do đó không biết cách giải quyết nó và string trên thông báo lỗi phải đến từ loại này dưới dạng phụ thuộc. Tôi khuyên bạn nên sử dụng lớp tĩnh GlobalConfiguration và truy cập thuộc tính Configuration để có được phiên bản HttpConfiguration. Bạn có thể trừu tượng nó trong một bất động sản, cho mẫu:

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

Bây giờ, nếu bạn đang ở trên một điều khiển Api, bạn chỉ có thể truy cập trực tiếp this.Configuration tài sản đó là đã có trên ApiController (lớp cơ sở cho các bộ điều khiển Api) và lấy một bản sao của HttpConfiguration.

37

Tôi nghĩ cách tốt hơn là thêm thuộc tính InjectionConstructor vào hàm tạo mặc định. Thuộc tính này buộc sự thống nhất sử dụng hàm tạo trang trí.

Ví dụ:

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

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

Tuyệt vời! Giải pháp sạch và ngắn. –

+0

Thật tuyệt vời, đã làm việc cho tôi. Cảm ơn! – Vishal

1

Tôi vừa mới có lỗi này xảy ra trên một codebase làm việc trước đó. Câu trả lời dưới đây cho thấy những gì tôi đã làm để sửa chữa nó:

Adding Web API and API documentation to an existing MVC project

Về cơ bản làm cho các nhà xây dựng với các thông số protected hơn public

6

Lý do điều này xảy ra là bởi vì Unity sẽ theo mặc định chọn sử dụng các nhà xây dựng với các thông số nhất do đó bỏ qua constructor mặc định.

Nhận xét hai hàm tạo tồn tại trong mẫu HelpController và thêm một hàm mặc định đặt cấu hình.

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

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

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

Câu trả lời đơn giản và rõ ràng hoạt động tốt hầu hết thời gian khi bạn giới thiệu unitu cho dự án webapi. –

2

Đăng ký các đối tượng HttpConfiguration như một ví dụ trong UnityContainer cũng sẽ giúp giải quyết vấn đề này.
Chỉ cần thêm để thêm dòng dưới đây khi đăng ký trong UnityContainer.

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

Điều này sẽ giúp giải quyết Unity tham số config, khi nó gọi các nhà xây dựng với tham số.

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