I have a WCF web service hosted on my Local IIS (not Express). I've included a Global.asax in its root directory, where it is supposed to be. Since I'm using Ninject with WCF extensions, the class Global extends NinjectHttpApplication instead of HttpApplication (as seen here).
Also, I'm using the AutoMapper library in order to circumvent writing boring boilerplate code.
The problem arises because a static method I defined for configuring AutoMapper isn't being called causing AutoMapper to throw exceptions when I call Mapper.Map(). That static method's call is defined in Global.asax's Application_Start() method since I want these mappings to be performed once per the web service's lifetime.
Ninject's CreateKernel() method gets called just fine, by the way.
Am I missing something here? I've tried debugging it, it doesn't hit the breakpoint even though I've attached the debugger to w3wp.exe and also tried putting an explicit Debugger.Break() call in its body.
This is how it looks like so far:
Global.asax
<%# Application Codebehind="Global.asax.cs" Inherits="MyApp.WebHost.Global" Language="C#" %>
Global.asax.cs
public class Global : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel();
/* various bindings */
return kernel;
}
protected void Application_Start(object sender, EventArgs e)
{
AutoMapperConfig.RegisterMappings();
}
/* rest of Global.asax methods (Session_Start, Application_BeginRequest, etc.) with empty bodies */
RegisterMappings method
public static class AutoMapperConfig
{
public static void RegisterMappings()
{
/* multiple calls to Mapper.CreateMap() */
Mapper.AssertConfigurationIsValid();
}
}
Svc file markup
<%# ServiceHost Language="C#"
Debug="true"
Service="MyApp.Services.MyAppService"
Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>
Everything else works, I've already created a test client (a simple console app) and added a service reference. Service methods get called just fine, it is just that these mappings are a bit problematic since AutoMapper keeps throwing AutoMapperMappingException exceptions ("Missing type map configuration or unsupported mapping.") for the obvious reasons.
The application's app pool is DefaultAppPool. Should I create a separate one?
I really don't understand the problem here. Thank you in advance.
Well, it required some additional searching but I found the answer here - https://groups.google.com/forum/#!topic/ninject/wRy3ELSV4bU
The problem was that NinjectHttpApplication class itself implements the Application_Startup method so it is impossible to implement it in your own derived class (Global class).
To simulate such behavior one needs to override the OnApplicationStarted Ninject's method.
This is how it looks like regarding my particular problem:
protected override void OnApplicationStarted()
{
AutoMapperConfig.RegisterMappings();
}
Related
I would like to reuse a library class that I made for some projects in Asp .Net Framework within an Asp .Net Core project on which I am now working.
For that project I have to use a MySQL database so I added the MySqlConnector NuGet package to my library class.
As the registered .NET Data Providers are not automatically added to the Global Assembly Cache I must register it manually thanks the call of that method DbProviderFactories.RegisterFactory("MySqlConnector", MySqlClientFactory.Instance) during application startup as mentionned here.
It's my first .Net core project so I don't know if that's how I should do it but I called that method in the Startup.cs file like this :
It is working but I am wondering if it's the right way to do it. Would you advise me another proper way to do it?
Thanks
There is nothing fundamentally wrong with your approach, IMO.
One problem I see is the task you're trying to run takes too long, in which case you're better off spawning a task.
The other is reusability, your code is coupled together. You could solve that by wrapping it in a class and injecting it into a middleware component by interface, and then calling a method. For example:
public interface ITask { void Run(); }
class RegisterMySqlTask : ITask { public void Run() { DbProviderFactories.RegisterFactory("MySqlConnector", MySqlClientFactory.Instance); } }
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITask, RegisterMySqlTask>();
//rest goes here
}
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
context.RequestServices.GetRequiredService<ITask>().Run();
await next(context);
});
//rest goes here
}
Note, however, that this may be overcomplicating things. As I said, I believe that you are not doing anything wrong.
I have a WCF service hosted in IIS7. The service has a static class with a static list containing strings (sort of log). It periodically write the entries to a file or db.
However when the IIS decides the recyle the app or terminate for whatever reason, the entries in the static field are lost.
Is there any way I can handle the service shuttingdown kind event and persist the data from memory?
Thanks
Shreedhar
I've implemented several services via IIS with a custom service host (originally I did this so I could implement IErrorHandler for global error handling).
You'll need two things - an implementation of ServiceHost and an implementation of ServiceHostFactory, which will call your custom service host. For example (just the relevant parts of code shown):
public class MyCustomServiceHost : ServiceHost
{
protected override void OnClosing()
{
// logic to save off your static data
base.OnClosing();
}
}
public class MyCustomServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyCustomServiceHost(serviceType, baseAddresses);
}
}
In your .svc file, you'd have something like this:
<%# ServiceHost Service="MyCompany.MyServiceName" Factory="MyCompany.MyCustomServiceHostFactory" %>
<%# Assembly Name="MyCustomServiceHost" %>
This is one way to do this (and this dates back to .NET 3.5 days); there are quite likely other ways to accomplish this, but at least this should give you some direction.
I am trying to create an IOC container in Castle Windsor that's configuration is shared across assemblies.
(What follows is an example of how this works in Unity. What I want to do is to make it work the same way using Castle Windsor)
I have the following project configuration...
TestCompany.Services.Host
(Web project hosting a number of .svc files)
PrintService.svc
Web.Config
Unity.Config
TestCompany.Services.PrintService
IPrintService.cs
PrintService.cs
The actual implementation of my "PrintService" is not implemented inside my Services.Host but in the TestCompany.Services.PrintService assembly.
As part of my shared project code (not shown) I have a container helper which is responsible for loading the unity configuration...
public static IUnityContainer GetContainer()
{
// Checks for existance of container (_container == null) ommitted.
var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
section.Configure(_container, name);
...
...
}
This method loads the unity configuration section from the Unity.Config and uses it to configure the container.
The advantage of this method is that one Unity.Config loaded inside (I presume) the AppDomain can service a number of assemblies. Simply calling GetContainer() from any of the assemblies consumed by my service host will return a container populated with the same type resolution's etc.
I really want to use the fluent configuration in Castle Windsor but I dont see how without this "shared" configuration file that can be acheived. PrintService and any future services will all need to resolve the same dependencies and I dont want to have to repeat my fluent configuration between these services.
Ideally I need some sort of container configured in the service host app that can "flow" into all of the assemblies that it makes use of.
Thanks.
I think I may not be understanding your question but I think I understand your scenario and here is how I do something similar, if it helps at all...
My Philosophy:
Each part of the application should be in charge of registering what
it knows about and nothing more, so there is no need for a single
central configuration file and things that are shared between
components are registered in one place and their interfaces are
available everywhere via a common library.
So let's take an example...
First of all, let us just say (for the purposes of my example) that IPrintService is something that you want to register an implementation of once and use throughout the application and that we have some other component that needs to be implemented by some external module from the main application. We, therefore, create an assembly called Common like so:
Common
public interface IPrintService
{
void Print();
}
public interface IMyService
{
void DoSomething();
}
Now let us think about the main part of the application (maybe it is an ASP .NET application, maybe justa console application, does not really matter). Here we construct the container and ask it to find all the possible components. We can do that like so:
Main Application
// Could be the Global.asax code behind but for simplicity this is
// just a console application
class Program
{
private static readonly IWindsorContainer Mycontainer
= BootstrapContainer();
// Allow access to the raw container - this is probably a bad idea but
// in the rare case that you need it you can get it from here
public static IWindsorContainer Container { get { return Mycontainer; } }
private static IWindsorContainer BootstrapContainer()
{
// Here we will just install every IWindsorInstaller found in any
// assembly in the same folder as the application (so no need for
// references or anything).
var c = new WindsorContainer();
string folder = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
c.Install(FromAssembly.InDirectory(new AssemblyFilter(folder)));
return c;
}
}
// Here is the print service implementation
public class MyPrintService : IPrintService
{
public void Print()
{
// Print!
}
}
// This is the installer for the main module - here we are saying exactly
// what is implementing the interface
public class MainApplicationInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IPrintService>()
.ImplementedBy<MyPrintService>());
}
}
So now we have a common library with our shared inetrfaces and a main application that will register an implementation for our shared interface and also load up any other modules in the system.
The only thing, therefore, left to do is to consume that print service and use it. We can do this anywhere that is using the container so let's create a third assembly that references only Common (we will call it test module.
Test Module
// This installer installs just the things inside this module since that
// is all it knows about but those things can use things that are
// registered in the container by anybody.
public class TestModuleInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IMyService>()
.ImplementedBy<MyServiceThatDoesSomething>());
}
}
public class MyServiceThatDoesSomething : IMyService
{
private readonly IPrintService _printService;
public MyServiceThatDoesSomething(IPrintService printService)
{
_printService = printService;
}
public void DoSomething()
{
// Use the print service!
_printService.Print();
}
}
Finally compile everything and copy the test module to the same folder as the main application and then from the main you can do this:
Container.Resolve<IMyService>().DoSomething();
And then the magic happens! Well, some code runs and you find that the print service is called by the class from the module even though it knows nothing about it.
Anyway, maybe that helps a little bit, maybe not, good luck!
I am trying to use Ninject with Common Service Locator in my asp.net mvc3 project. I've added Ninject.dll and CommonServiceLocator.NinjectAdapter.dll to the project.
I wrote following code in my global.asax.cs file.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ServiceLocator.SetLocatorProvider(() => new NinjectServiceLocator(CreateKernel()));
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
private static IKernel CreateKernel()
{
IKernel kernel = new StandardKernel();
kernel.Bind(typeof(IUserService)).To(typeof(UserService));
return kernel;
}
But it does not compile because it couldn't find ServiceLocator and giving me the error
"The name 'ServiceLocator' does not exist in the current context"
What am I doing wrong here? Am I missing a reference?
I think you won't get an answer to your question because using the Common ServiceLocator is very uncommon especially for MVC3. The service locator anti-pattern you seem to use is considered bad practice.
Almost everyone is using some IDependencyResolver implementation instead. See https://github.com/ninject/ninject.web.mvc/wiki/MVC3
I'm using Ninject for DI in my asp.net application, so my Global class inherits from NinjectHttpApplication.
In my CreateKernel(), I'm creating my custom modules and DI is working fine for me.
However, I notice that there is a Logger property in the NinjectHttpApplication class, so I'm trying to use this in Application_Error whenever an exception is not caught.
I think I'm creating the nlog module correctly for Ninject, but my logger is always null. Here's my CreateKernel:
protected override Ninject.Core.IKernel CreateKernel()
{
IKernel kernel = new StandardKernel(new NLogModule(), new NinjectRepositoryModule());
return kernel;
}
But in the following method, Logger is always null.
protected void Application_Error(object sender, EventArgs e)
{
Exception lastException = Server.GetLastError().GetBaseException();
Logger.Error(lastException, "An exception was caught in Global.asax");
}
To clarify, Logger is a property on NinjectHttpApplication of type ILogger and has the [Inject] attribute
Any idea how to inject correctly into Logger?
Download the latest version from GitHub. The logging was removed. The reason you are not seeing the logger injected is that Ninject isn't creating the HttpApplication class, so it doesn't know to inject it, you have to assign it manually. Ninject can only initialize components activated by the kernel.
Are you actually wiring up an ILogger in your NLogModule? If not then Ninject probably won't know what to use when you use the Logger of your implemented NinjectHttpApplication class.
I would check what is in your NLogModule, and I would also suggest putting it in your question. I think it might help us to solve your problem.