我在Ubuntu 14.04 LTS(在IDE中运行时使用Mono 3.10.0 mod-mono-server4 / xsp)在Xamarin Studio / monodevelop-opt中设置了一个新的ASP.NET MVC 4应用程序。安装的软件包是:
Install-Package Microsoft.AspNet.Mvc -Version 4.0.40804
我还必须安装Optimization Framework:
Install-Package Microsoft.AspNet.Web.Optimization
我选择从NuGet实现IoC容器Ninject并安装了以下软件包:
Install-Package Ninject.Mvc4
因为我安装了Ninject.Mvc4,它在App_Start中为我创建了一个名为NinjectWebCommon.cs的好文件
这是Create Kernal方法:
private static IKernel CreateKernel ()
{
var kernel = new StandardKernel ();
try {
kernel.Bind<Func<IKernel>> ().ToMethod (ctx => () => new Bootstrapper ().Kernel);
kernel.Bind<IHttpModule> ().To<HttpApplicationInitializationHttpModule> ();
RegisterServices (kernel);
return kernel;
} catch {
kernel.Dispose ();
throw;
}
}
以下是注册服务方法:
private static void RegisterServices (IKernel kernel)
{
kernel.Bind<IResourceEntryService> ().To<ResourceEntryService> ();
var modules = new List<INinjectModule> {
new ConfigModule (),
new RepositoryModule (),
new LoggingModule ()
};
kernel.Load (modules);
}
资源输入服务和界面:
public interface IResourceEntryService
{
IEnumerable<ResourceEntry> GetResourceEntries ();
IEnumerable<ResourceEntry> GetResourceEntriesByNameAndCulture (string name, string culture);
}
public class ResourceEntryService : IResourceEntryService
{
IResourceEntryRepository _resourceEntryRepository;
public ResourceEntryService (IResourceEntryRepository resourceEntryRepository)
{
_resourceEntryRepository = resourceEntryRepository;
}
#region IResourceEntryService implementation
public System.Collections.Generic.IEnumerable<ResourceEntry> GetResourceEntries ()
{
IEnumerable<ResourceEntry> resourceEntries = _resourceEntryRepository.GetResourceEntries ();
return resourceEntries;
}
public System.Collections.Generic.IEnumerable<ResourceEntry> GetResourceEntriesByNameAndCulture (string name, string culture)
{
IEnumerable<ResourceEntry> resourceEntries = _resourceEntryRepository.GetResourceEntriesByNameAndCulture (name, culture);
return resourceEntries;
}
#endregion
}
资源输入控制器将新模型对象传递到视图中:
public class ResourceEntryController : Controller
{
IResourceEntryService _resourceEntryService;
public ResourceEntryController (IResourceEntryService resourceEntryService)
{
_resourceEntryService = resourceEntryService;
}
public ActionResult Index ()
{
ResourceEntryViewModel viewModel = new ResourceEntryViewModel ();
return View (viewModel);
}
}
这是我的〜/ Views / ResourceEntry / Index.cshtml文件:
@model App.Web.UI.ViewModels.ResourceEntryViewModel
<h1>Resource Page</h1>
所以现在一切看起来都好吗?错了!当我尝试查看该页面时收到以下错误消息。
System.MissingMethodException
Default constructor not found for type App.Web.UI.Controllers.ResourceEntryController
at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00094] in /usr/src/packages/BUILD/mcs/class/corlib/System/Activator.cs:326
at System.Activator.CreateInstance (System.Type type) [0x00000] in /usr/src/packages/BUILD/mcs/class/corlib/System/Activator.cs:222
at System.Web.Mvc.DefaultControllerFactory+DefaultControllerActivator.Create (System.Web.Routing.RequestContext requestContext, System.Type controllerType) [0x00000] in <filename unknown>:0
Version Information: 3.10.0 (tarball Sat Oct 4 16:28:24 UTC 2014); ASP.NET Version: 4.0.30319.17020
Powered by Mono
任何人都有任何想法如何设置在单声道堆栈上运行的MVC 4应用程序的Ninject。
我有一个很好的谷歌和堆栈,并且无法真正找到明确的答案。一切都链接到Web API,我对Web API并不感兴趣,因为我将使用ServiceStack。
我只是希望这个Web应用程序能够运行。有人有什么建议吗?
更新:2014年12月20日
在Windows下运行但不是Ubuntu
我创建了一个简单的应用程序,可以在这里找到:
任何想法?
2014年12月21日更新
我尝试过另一种IoC容器实现。
同样的事情发生了,我想这可能是Mono MVC 4 Thing。仍然不知道为什么。
2014年12月22日更新
看起来App_Start在启动时不会被调用。
我在Console.WriteLine
和CreateKernel
中做了RegisterServices
,没有打印出来。
我可以通过在Global.ascx.cs文件中配置Container来使SimpleInjector工作。如果它在App_Start中初始化并且顶部有以下行,它将无法工作。
[assembly: WebActivator.PostApplicationStartMethod (typeof(App.Web.UI.App_Start.SimpleInjectorInitializer), "Initialize")]
想知道使用Mono的WebActivator是否存在问题。
答案 0 :(得分:1)
查看堆栈跟踪,我可以在底部看到DefaultControllerFactory,它将在内部实例化控制器实例,如:
return Activator.CreateInstance(YourControllerType);
这个调用会变得脾气暴躁,因为你的控制器没有无参数构造函数,你没有为它找到一个参数值列表来找到一个合适的构造函数来使用...因此异常。 此外,您不希望提供参数列表,这些参数列表不灵活且无法实现IoC的目的,您希望IoC内核改为创建实例。
现在,我没有使用Ninject的经验,所以可能有更多的“Ninjecty”方式(如果你知道那是什么请加到这个:)但你需要创建自己的DefaultControllerFactory,它可以确定类型并使用Ninject创建它。 像这样:
// NOTE: Something like this, not exactly, I've not used Ninject!
public class YourControllerFactory : DefaultControllerFactory
{
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var type = GetControllerType(requestContext, controllerName);
return kernel.Get(type);
}
}
在Global.asax中注册:
ControllerBuilder.Current.SetControllerFactory(new YourControllerFactory());
现在您可以控制实例化过程了!