EntryPointNotFoundException when calling DependencyResolver.SetResolver(new UnityDependencyResolver(Container)); - c#

I've got an MVC project and I've been doing DI in my WebAPI controllers for quite some time using a IHttpControllerActivator.
configuration.Services.Replace(
typeof(IHttpControllerActivator),
new UnityCompositionRoot(Container));
Now I need to use DI in an MVC controller so tried adding this line from the Unity.MVC project.
DependencyResolver.SetResolver(new UnityDependencyResolver(Container));
But I'm getting an EntryPointNotFound exception when trying to set the resolver with the following stack trace.
at System.Web.Mvc.DependencyResolver.CacheDependencyResolver..ctor(IDependencyResolver resolver)
at System.Web.Mvc.DependencyResolver.InnerSetResolver(IDependencyResolver resolver)
at System.Web.Mvc.DependencyResolver.SetResolver(IDependencyResolver resolver)
at GRP2App.Web.App_Start.DependencyConfig.RegisterDependencys(HttpConfiguration configuration) in c:\Dev\SVN-Git\GRP2.5\GRP2App\GRP2App.Web\App_Start\DependencyConfig.cs:line 96
I've updated all my Unity nu-get packages so all the different projects should be on the same version. I'm not really sure what else to try.

I seem to remember this was an issue with upgrading from MVC 4 to MVC 5.
I upgraded using NuGet but there are several version numbers in the assembly redirects and razor engine sections of the web.config file which need updating.
This article contains full instructions with all the different places where the version numbers need upgrading.
http://www.asp.net/mvc/tutorials/mvc-5/how-to-upgrade-an-aspnet-mvc-4-and-web-api-project-to-aspnet-mvc-5-and-web-api-2
This was the important part for me.
Update all elements that contain “System.Web.WebPages.Razor” from
version “2.0.0.0” to version“3.0.0.0”. If this section contains
“System.Web.WebPages”, update those elements from version “2.0.0.0”
to version“3.0.0.0”

Related

MediatR setup for shared Class Library in Console vs WebAPI

I have a .Net Core 2.2 class library that uses the CQRS pattern with MediatR. I add all my dependencies into a serviceProvider in Main and attach MediatR via:
serviceCollection.AddMediatR();
var serviceProvider = serviceCollection.BuildServiceProvider();
Everything works like a charm and I am able to send any of my commands or queries to MediatR without fail.
I want to use the same exact library in a WebApi (also .Net Core 2.2) and set up my serviceProvider the exact same way inside of the Startup.ConfigureServices() method and I get the following exception when calling any controller that uses MediatR:
InvalidOperationException: Handler was not found for request of type MediatR.IRequestHandler`2[Core.Application.Accounts.Queries.GetAccountListQuery,System.Collections.Generic.List`1[Core.Application.Accounts.Models.AccountViewModel]]. Register your handlers with the container. See the samples in GitHub for examples.
MediatR.Internal.RequestHandlerBase.GetHandler(ServiceFactory factory)
I was able to resolve the issue by explicitly adding each command or query prior to adding MediatR to the DI container:
services.AddMediatR(typeof(GetAccountListQuery).GetTypeInfo().Assembly);
services.AddMediatR();
But does this mean I have to register every single IRequest object in my library? How is MediatR able to register them for me in the Console app but not in the WebAPI? Is there a better method?
I have seen this post that recommends assembly scanning, however it perplexes me that my Console app seemed to do this automatically. Also I am not sure I want to move to Autofac just yet. I have seen some packages to help you do the same with the default ServiceProvider - however I really want to avoid adding extra dependencies unless absolutely necessary.
It should be enough to just have this:
services.AddMediatR(typeof(GetAccountListQuery));
or just
services.AddMediatR(typeof(Startup));
It works for me in ASP.NET Core 2.2. The project has these two NuGet dependencies:
MediatR version 6.0.0
MediatR.Extensions.Microsoft.DependencyInjection version 6.0.1
P.S. For those, who minuses - any class from assembly would work. I used GetAccountListQuery as an example because it is for sure inside the right assembly. See my comments below.

Method Not Found when using LightInject with MVC5 and .Net 4.5

When setting up LightInject for an MVC controller I am getting an error when calling container.EnableMvc(); in the injector setup.
Error:
Method not found:
'Void LightInject.WebContainerExtensions.EnablePerWebRequestScope(LightInject.IServiceContainer)'
Source:
public static void Register() {
var container = new ServiceContainer();
container.ScopeManagerProvider = new PerLogicalCallContextScopeManagerProvider();
WebContainerExtensions.EnablePerWebRequestScope(container);
container.RegisterControllers();
container.Register<ISomeClass, SomeClass>();
container.EnableMvc();
}
Additional Information:
I am running the code locally through Visual Studio
The project is 4.5
My OS is Windows 10 (framework 4.5)
In the past when I have setup LightInject I have set the scope lifetime manually but the documentation, for general setup and MVC specific examples, has since changed. I came across one thread that mentioned this could be an issue with not including LightInject.Web as a dep, but I can see it listed as a dep for LightInject.MVC and in the list of references in the project.
Are there any other steps I can take to manually configure the lifetime or otherwise verify that this method is available before Enabling MVC?
The issue here was that I installed LightInject.MVC with NuGet. It lists it's dependencies as:
LightInject.Web (>= 1.0.0.4)
LightInject (>= 3.0.1.7)
The after I exhausted this being an issue with versions of .Net 4.5 and possible issues with async. I decided to manually update both LightInject.Web and LightInject to their newest versions. After the update it resolved the issue.
I will add this as a bug in the listed dependencies on the projects site.

Ninject in .NET Core

I am trying to install Ninject 3.3.2 in .NET Core, Released in May 2016. I got an error: The dependency Ninject 3.2.2 does not support framework .NETCoreApp, Version=v1.0.
Does anybody had similar problem, and is there any solution for this?
Ninject 3.3.0 was released September 26th 2017 and now targets .NET Standard 2.0 and thus also runs on .NET Core 2.0.
From the course of things (see issues/discussions on GitHub) it seems likely that some of the changes in the 4.0-beta will be reverted. I would not expected a 4.0 final shortly. Hence I would advise to go with the current version 3 release.
Just wanted to add; while both of the previous answers are correct in that ASP.Net core does provide built in dependency injection, it is NOT sufficient for more advanced scenarios. As it does not support a whole host of features that Ninject, AutoFac, Unity, or StructureMap supports.
At present, the only DI libraries that I am aware of that fully supports .net core are AutoFac and now Unity as well. It is very simple to add this in. The only thing you need to do to replace the built in DI is as follows. This example is for AutoFac but its almost identical for Unity it looks like.
First, replace the void on ConfigureServices in startup.cs with an IServiceProvider (dependency from AutoFac) like so:
public IServiceProvider ConfigureServices(IServiceCollection services)
Then create a container builder, build and resolve an IServiceProvider from ConfigureServices:
var builder = new ContainerBuilder();
builder.Populate(services);
var container = builder.Build();
return container.Resolve<IServiceProvider>();
I have a wrapper around the this second part that allows you to dynamically load and build different configurations using AutoFac modules, that I might be convinced to upload to GitHub or something if there is any interest.
Ninject does not support .NET Core. You can check it's website to be sure if there is no version that supports it.
ASP.NET Core has its own Dependency Injection container build in. See here.
Ninject does not support .Net Core, instead of this we can use dependency injection of .net core. following are the steps to implement.
Go to startup.cs at public void
ConfigureServices(IServiceCollection services)
Add services.AddTransient<Interface, Class>();
Go to the controller where you want to apply dependency injection.
Create a global private Interface _propertyName;
Pass the interface type variable to the constructor like
public Constructor(Interface name)
{
_propertyName= name;
}
Now you can access the members of the class through _propertyName.

Getting Autofac to work with MVC6/ASP.NET5

I cannot get autofac to work, I have looked at this potentially duplicate question, but it doesn't help.
I am using the full .NET stack, DNX 4.5.1
I have included the following dependencies.
"dependencies": {
// matched latest autofac version with latest dependencyinjection version.
"Autofac": "4.0.0-beta8-157",
"Autofac.Framework.DependencyInjection": "4.0.0-beta8-157",
"Microsoft.AspNet.Mvc": "6.0.0-rc1-final" ...
And the following initialisation code.
// void?
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var container = new ContainerBuilder();
...
// compilation error here!
container.Populate(services);
}
I am receiving this error:
Error CS1503 Argument 2: cannot convert
from'Microsoft.Extensions.DependencyInjection.IServiceCollection' to
'System.Collections.Generic.IEnumerable<Microsoft.Framework.DependencyInjection.ServiceDescriptor>'
MuWapp.DNX 4.5.1 C:\MuWapp\Startup.cs 54 Active
For RC1 you will need to use the Autofac.Extensions.DependencyInjection package.
https://www.nuget.org/packages/Autofac.Extensions.DependencyInjection/
We renamed our package to align with Microsoft's rename to Microsoft.Extensions.DependencyInjection. It's been a moving target supporting the early DNX releases.
As I've mentioned in the comment, you should use compatible versions of all packages in your project.json. I see on their page: https://github.com/autofac/Autofac/releases that they have released version for RC1, however there is no Autofac.Framework.DependencyInjection for RC1, so if you require this package, you will be unable to run it.
I think you should use built-in dependency injection during your development untill there is RTM version and all of the third-party packages will become stable.
Build-in DI has functionality for injecting classes into controllers, properties as well as attributes, so unless you use some advanced scenarios in which autofac is necessary, you should stick to asp.net 5 DI.

Do I need a Global.asax.cs file at all if I'm using an OWIN Startup.cs class and move all configuration there?

Let's say for example in a brand new ASP.NET MVC 5 application made from the MVC with Individual Accounts template, if I delete the Global.asax.cs class and move it's configuration code to Startup.cs Configuration() method as follow, what are the downsides?
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureAuth(app);
}
}
The upsides for me is that when upgrading ASP.NET 4 applications to ASP.NET 5 and using pieces that now must be configured in the Startup.cs class, I'm not doing dependency injection and other configuration in two different classes that seem related to starting up, and configuration.
Startup.Configuration gets called slightly later than Application_Start, but I don't think the difference will matter much in most cases.
I believe the major reasons we kept the other code in Global.asax are:
Consistency with previous versions of MVC. (That's where everybody currently expects to find this code.)
Ability to add other event handlers. In Global.asax, you can handle other methods like Session_Start and Application_Error.
Correctness in a variety of authentication scenarios. The Startup.Configuration method is only called if you have Microsoft.Owin.Host.SystemWeb.dll in your bin directory. If you remove this DLL, it will silently stop calling Startup.Configuration, which could be hard to understand.
I think the third reason is the most important one we didn't take this approach by default, since some scenarios don't include having this DLL, and it's nice to be able to change authentication approaches without invalidating the location where unrelated code (like route registration) is placed.
But if none of those reasons apply in your scenario, I think you'd be fine using this approach.
For those looking for the complete steps: If you are looking to create a OWIN based, IIS hosted web API, these steps should get you there:
File -> New -> Project
In the dialogue, Installed -> templates -> Other Project types -> Visual Studio Solutions -> Blank Solution targeting .NET 4.6
On the solution, right click, add Project -> Web -> ASP.NET Web Application (targeting .NET 4.6)
3.1 Now In the ASP.NET 4.5 templates, choose Empty as the template
3.2 This creates a blank solution with two nuget packages:
Microsoft.CodeDom.Providers.DotNetCompilerPlatform v 1.0.0
Microsoft.Net.Compilers v 1.0.0
Install the following packages:
Install-Package Microsoft.AspNet.WebApi.WebHost -Version 5.2.3
Install-Package Microsoft.AspNet.WebApi -Version 5.2.3
Install-Package WebApiContrib.Formatting.Razor 2.3.0.0
For OWIN:
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Microsoft.AspNet.WebApi.OwinSelfHost
Then add Startup.cs with Configuration method:
[assembly:OwinStartup(typeof(namespace.Startup))]
public class Startup
{
/// <summary> Configurations the specified application. </summary>
/// <param name="app">The application.</param>
public static void Configuration(IAppBuilder app)
{
var httpConfiguration = CreateHttpConfiguration();
app
.UseWebApi(httpConfiguration);
}
/// <summary> Creates the HTTP configuration. </summary>
/// <returns> An <see cref="HttpConfiguration"/> to bootstrap the hosted API </returns>
public static HttpConfiguration CreateHttpConfiguration()
{
var httpConfiguration = new HttpConfiguration();
httpConfiguration.MapHttpAttributeRoutes();
return httpConfiguration;
}
}
Now add a class that inherits from ApiController, annotate it with RoutePrefix attribute and the action method with Route + HttpGet/PutPost (representing the Http verb you're after) and you should be good to go
This is my understanding of how starting/hosting a web application evolved as it's all pretty confusing to follow. A small summary:
1. Classic ASP.NET: Write only the application code to run in the last step of the mandatory IIS pipeline
2. ASP.NET with OWIN: Configure a .NET webserver and write your application code. No longer directly coupled to IIS, so you're no longer forced to use it.
3. ASP.NET Core: Configure both the host and the webserver to use and write your application code. No longer mandatatory to use a .NET webserver if you target .NET Core instead of the full .NET Framework.
Now I'll go a bit more into detail of how it works and which classes are used to start the application:
Classic ASP.NET
Classic ASP.NET applications have the Global.asax file as entry point. These applications can only be run in IIS and your code gets executed at the end of the IIS pipeline (so IIS is responsible for CORS, authentication... before your code even runs). Since IIS 7 you can run your application in integrated mode which integrates the ASP.NET runtime into IIS. This enables your code to configure functionality which wasn't possible before (or only in IIS itself) such as url rewriting in the Application_Start event of your Global.asax file or use the new <system.webserver> section in your web.config file.
ASP.NET with OWIN
First of all OWIN is not a library but a specification of how .NET web servers (for example IIS) interact with web applications. Microsoft themselves have an implementation of OWIN called project Katana (distributed through several different NuGet packages). This implementation provides the IAppBuilder interface you encounter in a Startup class and some OWIN middleware components (OMC's) provided by Microsoft. Using IAppBuilder you basically compose middleware in a plug-and-play way to create the pipeline for the webserver (in addition to only the ASP.NET pipeline in IIS7+ as in the point above) instead of being tied to the IIS pipeline (but now you use a middleware component for CORS, a middleware component for authentication...). Because of this, your application is not specifically coupled to IIS anymore and you can run it on any .NET Webserver, for example:
The OwinHost package can be used to self-host your application with a Katana webserver.
The Microsoft.Owin.Host.SystemWeb package is used to host your OWIN application in IIS7+ in integrated mode, by subscribing your middleware to the correct lifetime events internally.
The thing that makes everything so confusing is that Global.asax is still supported together with the OWIN Startup class, while they can both do similar things. For example you could implement CORS in Global.asax and authentication using OWIN middleware which becomes really confusing.
My rule of thumb is to remove the Global.asax file alltogether in favor of using Startup whenever I need to add OWIN.
ASP.NET Core
ASP.NET Core is the next evolution and now you can target either .NET Core or the full .NET Framework. When you target .NET Core you can run your application on any host which supports the .NET Standard. This means you are no longer restricted to a .NET webserver (as in the previous point), but can host your application in Docker containers, a linux webserver, IIS...
The entry point for an ASP.NET Core web application is the Program.cs file. There you configure your host and again specify your Startup class where you configure your pipeline. Using OWIN (by using the IAppBuilder.UseOwin extension method) is optional, but fully supported.

Categories