StructureMap Exception Code: 202 - asp.net-mvc-3

everyone, I have problems when using MVC3 code is as follows
public SystemController(IRepository repository)
:this
(
repository,
new AspNetMembershipProviderWrapper(System.Web.Security.Membership.Provider),
new AspNetMembershipProviderWrapper(System.Web.Security.Membership.Provider),
new AspNetRoleProviderWrapper(Roles.Provider),
new SmtpClientProxy(new SmtpClient(Utils.Setting.EmailServer,
int.Parse(Utils.Setting.EmailPort))
{
EnableSsl = true,
UseDefaultCredentials = true,
Credentials = new NetworkCredential(Utils.Setting.EmailAccount,
Utils.Setting.EmailPassword),
DeliveryMethod = SmtpDeliveryMethod.Network
})
){}
public SystemController(IRepository repository,
IUserService userService,
IPasswordService passwordService,
IRolesService rolesService,
ISmtpClient smtpClient)
: base(repository)
{
_userService = userService;
_passwordService = passwordService;
_rolesService = rolesService;
_smtpClient = smtpClient;
}
public class SmtpClientProxy : ISmtpClient
{
private readonly SmtpClient _smtpClient;
public SmtpClientProxy(SmtpClient smtpClient)
{
_smtpClient = smtpClient;
}
#region ISmtpClient Members
public void Send(MailMessage mailMessage)
{
_smtpClient.Send(mailMessage);
}
#endregion
}
ObjectFactory.Initialize(x =>
{
x.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.WithDefaultConventions();
});
x.For<ISessionFactory>()
.Singleton()
.Use(GetSessionFactory());
x.For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(y => y.GetInstance<ISessionFactory>().OpenSession());
x.For<IUserService>()
.Use<AspNetMembershipProviderWrapper>();
x.For<IPasswordService>()
.Use<AspNetMembershipProviderWrapper>();
x.For<IPasswordService>()
.Use<AspNetMembershipProviderWrapper>();
x.For<IRolesService>()
.Use<AspNetRoleProviderWrapper>();
x.For<ISmtpClient>()
.Use<SmtpClientProxy>().Ctor<SmtpClient>();
x.For<MembershipProvider>()
.Use(System.Web.Security.Membership.Provider);
x.For<RoleProvider>()
.Use(Roles.Provider);
});
Error info:
StructureMap Exception Code: 202
No Default Instance defined for PluginFamily System.Net.Mail.SmtpClient, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
I think the problem lies in this:
x.For <ISmtpClient> ()
. Use <SmtpClientProxy> (). Ctor <SmtpClient> ();
I ask you how to write it?

Your SmtpClientProxy class requires an SmtpClient class in its constructor. You don't have anything registered for SmtpClient.
Try adding this to your registration:
x.For<SmtpClient>().Use<SmtpClient>();
This assumes that SmtpClient does not take dependencies in its constructor. If it does you will likely get an error that one of its dependencies are not registered with a default implementation.
Alternatively you could change the constructor code to this (no constructor dependency):
private readonly SmtpClient _smtpClient = new SmtpClient();
public SmtpClientProxy()
{
}
Without knowing what you are trying to do, it's hard to answer definitively.

Related

Register and Resolving Dependencies on Request Based on Param (Autofac WEB API)

I have an Application with autofac dependency injection and I wanted to use a specific dll extension based on the parameter I have on the request.
Here's my global.asax where I initialize autofac.
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterApiControllers(Assembly.GetExecutingAssembly());
containerBuilder.RegisterModule<ExModule>();
var container = containerBuilder.Build();
container.Resolve<IArtigoErp>();
Here's the autofac module where I load register my DLL's
public class ExModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
//Load DLL1 from folder and register it
RegistaDepedencias<IArtigoErp>(builder, "DLL1");
//Load DLL2 from folder and register it
RegistaDepedencias<IArtigoErp>(builder, "DLL2");
}
private void RegistaDepedencias<T>(ContainerBuilder builder, string NomeDll)
{
RegisterDep<T>(GetEnumerableTypes<T>(NomeDll), builder);
}
private void RegisterDep<T>(IEnumerable<Type> types, ContainerBuilder builder)
{
foreach (var t in types)
{
builder.RegisterType(t).As<T>();
}
}
private IEnumerable<Type> GetEnumerableTypes<T>(string NomeDll)
{
return Directory.EnumerateFiles(Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "Engine"))
.Where(x => x.Contains(NomeDll) && x.EndsWith(NomeDll +".dll"))
.Select(x => Assembly.LoadFrom(x))
.SelectMany(x => x.GetTypes()
.Where(t => typeof(T).IsAssignableFrom(t) && t.IsClass));
}
}
Both my DLL's have a class that extend from IArtigoErp.
So the ideia is, based on the parameter I get on my request, I want to run the method in either DLL1 or DLL2.
Example:
if(param == 1)
_artigoErp.GetLista(); // In DLL1
if(param == 2)
_artigoErp.GetLista(); // In DLL2
EDIT 1:
The parameter comes from the post method as it follows (Guid IdLoja)
public class ArtigoController : ApiController
{
private readonly IArtigoErp _artigoErp;
private readonly IArtigoLoja _artigoLoja;
public ArtigoController(IArtigoErp artigoErp, IArtigoLoja artigoLoja)
{
_artigoErp = artigoErp;
_artigoLoja = artigoLoja;
}
[Route("PostArtigos")]
public CallResponse PostArtigos([FromBody] Guid IdLoja)
{
}
}
I guess we can also process this in the begin_request method in global.asax
Thanks in advance.

Issue with Simple Injector while using with Web API

I am having issue using Simple Injector with WebAPI project that gets created default with VS 2015.
I am having the AccountController having the below constructor
public AccountController()
{
}
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
UserManager = userManager;
AccessTokenFormat = accessTokenFormat;
}
In order to register these I used the below code in Simple Injector
// Create the container.
var apiContainer = new Container();
apiContainer.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
apiContainer.Options.ConstructorResolutionBehavior = new ConstructorBehavior();
//register the classes that we are going to use for dependency injection
apiContainer.Register<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>(new ApplicationDbContext()),Lifestyle.Scoped);
apiContainer.Register<IDataProtector>(() => new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider().Create("ASP.NET Identity"),Lifestyle.Transient);
apiContainer.Register<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>(Lifestyle.Transient);
apiContainer.Register<ITextEncoder, Base64UrlTextEncoder>(Lifestyle.Scoped);
apiContainer.Register<IDataSerializer<AuthenticationTicket>, TicketSerializer>(Lifestyle.Scoped);
//apiContainer.RegisterCommonClasses();
//register the webapi controller
apiContainer.RegisterWebApiControllers(configuration);
but after this I am getting the warning message that says
[Disposable Transient Component] ApplicationUserManager is registered as transient, but implements IDisposable.
Can someone Please help me with this how to resolve this ? With Default Web api project with VS 2015 it adds Account controller and that use ApplicationUserManager and has below details
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
Another issue I am getting as below
The constructor of type HttpConfiguration contains the parameter with name 'routes' and type HttpRouteCollection that is not registered. Please ensure HttpRouteCollection is registered, or change the constructor of HttpConfiguration.
This is with the HelpController as it uses the below details:
public HelpController()
: this(GlobalConfiguration.Configuration)
{
}
public HelpController(HttpConfiguration config)
{
Configuration = config;
}

Structure Map parameterless constructor error

I am trying to set up structure map ver 3.0.5.0 with Web API 2.
I have followed this implementation: Configuring dependency injection with ASP.NET Web API 2.1
However, I am getting this error when doing a get against my ComplexesController:
An error occurred when trying to create a controller of type 'ComplexesController'. Make sure that the controller has a parameterless public constructor.
Can anyone see what is wrong with my structuremap config? The Create method never gets called.
This is my implementation:
public class StructureMapControllerActivator : IHttpControllerActivator
{
private readonly IContainer _container;
public StructureMapControllerActivator(IContainer container)
{
if (container == null) throw new ArgumentNullException("container");
_container = container;
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
try
{
var scopedContainer = _container.GetNestedContainer();
scopedContainer.Inject(typeof(HttpRequestMessage), request);
request.RegisterForDispose(scopedContainer);
return (IHttpController)scopedContainer.GetInstance(controllerType);
}
catch (Exception e)
{
// TODO : Logging
throw e;
}
}
}
This method is in my startup...
public void InitializeContainer()
{
// STRUCTURE MAP
Container container = new Container();
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new StructureMapControllerActivator(container));
container.Configure(x => x.For<IForumRepository>().Use<ForumRepository>());
container.Configure(x => x.For<IComplexRepository>().Use<ComplexRepository>());
}
.. and this is the controller:
public class ComplexesController : ApiController
{
private IComplexRepository _repo;
public ComplexesController(IComplexRepository repo)
{
_repo = repo;
}
// GET: api/Complexes
public IList<Complex> GetComplexes()
{
var complexes = _repo.GetList();
return complexes;
}
...
My full Startup class
[assembly: OwinStartup(typeof(AngularJSAuthentication.API.Startup))]
namespace AngularJSAuthentication.API
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
}
}
}
The problem here is that you are registering your service activator with a GlobalConfiguration object and not your HttpConfiguration object. In this scenario The GlobalConfiguration object is never used as it is replaced by the HttpConfiguration object. In order to solve your issue you should replace your InitializeContainer() method with the following.
public void InitializeContainer(HttpConfiguration config)
    {
        // STRUCTURE MAP
        Container container = new Container();
        config.Services.Replace(typeof(IHttpControllerActivator), new StructureMapControllerActivator(container));
        container.Configure(x => x.For<IForumRepository>().Use<ForumRepository>());
        container.Configure(x => x.For<IComplexRepository>().Use<ComplexRepository>());        
    }
you should then pass the HttpConfiguration object from your Startup class to the new InitializeContainer() method.
Hope this helps.
-B
I am trying to gain a solid understanding of the complete lifecycle. I think my setup may be slightly different to the above. Here is what worked for me.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
var container = IocConfig.Setup();
// Allow a controller to be declared without a parameterless constructor
config.DependencyResolver = new DependencyResolver(container);
config.Services.Add( typeof(IExceptionLogger), new GlobalExceptionLogger( container.GetInstance<ILoggingService>()));
// Web API routes
config.MapHttpAttributeRoutes();
// Setup Authentication
ConfigureOAuth(app, container);
var corsOptions = CorsOptions.AllowAll;
app.UseCors(corsOptions);
// Add ASP.Net Web API to OWIN pipeline
app.UseWebApi(config);
}
}
It worked after I added this line:
// Allow a controller to be declared without a parameterless constructor
config.DependencyResolver = new DependencyResolver(container);
You have to get that my var container loads from a static class called IocConfig with a static Setup method. This is where the interfaces are mapped to their concrete implementations.
Also, you can probably ignore the GlobalExceptionLogger line if you want to use my complete example.

Autofac, ASP.NET MVC 3 httpRequest scope and AutoMapper: No scope with a Tag matching 'httpRequest' is visible

When I use a web type registered with autofac from an automapper mapping, I get this error:
No scope with a Tag matching 'httpRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being reqested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
When another type is resolved in the mapping it works.
When a web type is resolved from the controller it works.
Why doesnt web (or any other httprequest scoped?) types get successfully resolved in my mapping?
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.AssignableTo<Profile>()
.As<Profile>()
;
builder.Register(c => Mapper.Engine)
.As<IMappingEngine>();
builder.RegisterType<AnotherType>()
.As<IAnotherType>();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
var profiles = container.Resolve<IEnumerable<Profile>>();
Mapper.Initialize(c => profiles.ToList().ForEach(c.AddProfile));
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public class HomeController : Controller
{
private readonly IMappingEngine _mapper;
private readonly Func<HttpContextBase> _httpContext;
public HomeController(IMappingEngine mapper, Func<HttpContextBase> httpContext)
{
_mapper = mapper;
_httpContext = httpContext;
}
public ActionResult Index()
{
var test = _httpContext.Invoke();
return View(_mapper.Map<Model, ViewModel>(new Model()));
}
}
public class MyProfile : Profile
{
private readonly Func<HttpContextBase> _httpContext;
private readonly Func<IAnotherType> _anotherType;
public MyProfile(Func<HttpContextBase> httpContext, Func<IAnotherType> anotherType)
{
_httpContext = httpContext;
_anotherType = anotherType;
}
protected override void Configure()
{
CreateMap<Model, ViewModel>()
.ForMember(d => d.Url, o => o.ResolveUsing(s =>
{
var test = _anotherType.Invoke().GetAValue();
return _httpContext.Invoke().Request.Url;
}))
;
}
}
public interface IAnotherType
{
string GetAValue();
}
public class AnotherType : IAnotherType
{
public string GetAValue() { return "a value"; }
}
public class ViewModel
{
public string Url { get; set; }
}
public class Model
{
}
EDIT: Its easy to create an empty MVC project, paste the code and try it out and see for yourself.
EDIT: Removed the ConstructServicesUsing call because its not required by the example. No services are resolved through AutoMapper in the example.
#rene_r above is on the right track; adapting his answer:
c.ConstructServicesUsing(t => DependencyResolver.Current.GetService(t))
Still might not compile but should get you close.
The requirement is that the call to DependencyResolver.Current is deferred until the service is requested (not kept as the value returned by Current when the mapper was initialised.)
I think you should use DependencyResolver.Current.Resolve instead of container.Resolve in
Mapper.Initialize(c =>
{
c.ConstructServicesUsing(DependencyResolver.Current);
profiles.ToList().ForEach(c.AddProfile);
});
I recently had a similar problem and it turned out to be a bad setup in my bootstrapper function. The following autofac setup did it for me.
builder.Register(c => new ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers))
.AsImplementedInterfaces()
.SingleInstance();
builder.Register(c => Mapper.Engine)
.As<IMappingEngine>()
.SingleInstance();
builder.RegisterType<TypeMapFactory>()
.As<ITypeMapFactory>()
.SingleInstance();
I did not have to specify resolver in the Mapper.Initialize() function. Just called
Mapper.Initialize(x =>
{
x.AddProfile<DomainToDTOMappingProfile>();
});
after the bootstrapped and it works fine for me.

Beginners Moq question on Verifying

I'm just playing around with Moq and I cannot work out how to get a call to Verify to work as expected. My problem seems to be that the method I'm calling on the SUT is not being called. Here's my code to test:
public class ImageHandler : BaseHttpHandler
{
public override void ProcessRequest(HttpContextBase context)
{
var person = new Person();
this.DoPerson(person);
context.Response.ContentType = "image/jpeg";
if (context.Request.RawUrl.ToLower().Contains("jellyfish.jpg"))
{
context.Response.TransmitFile(#"C:\Temp\jf.jpg");
}
else if (context.Request.RawUrl.ToLower().Contains("koala.jpg"))
{
context.Response.TransmitFile(#"C:\Temp\k.jpg");
}
else
{
context.Response.Write("File not found.");
}
}
public virtual void DoPerson(Person person)
{
}
}
Here is my MSpec test:
[Subject("Process")]
public class When_Given_Person
{
private static Mock<HttpContextBase> httpContext;
private static Mock<HttpRequestBase> httpRequest;
private static Mock<HttpResponseBase> httpResponse;
private static Mock<ImageHandler> mockSut;
private static BaseHttpHandler sut;
private Establish context = () =>
{
httpContext = new Mock<HttpContextBase>();
httpResponse = new Mock<HttpResponseBase>();
httpRequest = new Mock<HttpRequestBase>();
mockSut = new Mock<ImageHandler>();
httpContext.SetupGet(context => context.Response).Returns(httpResponse.Object);
httpContext.SetupGet(context => context.Request).Returns(httpRequest.Object);
httpRequest.SetupGet(r => r.RawUrl).Returns("http://logicsoftware/unkown.jpg");
sut = mockSut.Object;
};
private Because of = () => sut.ProcessRequest(httpContext.Object);
private It should_call_person_with_expected_age = () =>
{
mockSut.Verify(s => s.DoPerson(Moq.It.IsAny<Person>()),Times.AtLeastOnce());
};
}
This is really basic stuff, nothing too fancy. Now, when I run the test I get:
Expected invocation on the mock at least once, but was never
performed: s => s.DoPerson(It.IsAny()) No setups configured.
I believe this is due to the fact that sut.ProcessRequest() is not actually called - I have a breakpoint at the start of ProcessRequest(), but it's never hit. Can someone show me how to setup my mockSut so that ProcessRequest() is called.
Cheers.
Jas.
When you make a Mock of an object with Moq, it will mock the whole object and set it up to return defaults or do nothing on every method and property. So sut.ProcessRequest, won't actually do anything: DoPerson will never be called.
You'll only want to mock out dependencies to the classes you want to test, never the class itself.

Resources