Using Ninject in .NET RESTful application? - c#

I'm new to RESTful services and haven't had to freshly wire up a stack using IoC in a while, so this is giving me a mild stroke.
I have a WCF service that looks like this (simplified):
public interface IESIID
{
[OperationContract]
[WebGet(UriTemplate = "/{guid}/{id}", ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
Message LookupESIID(string guid, string id);
}
public class ESIID : BaseREST<ESI>, IESIID
{
private readonly ITXESIIDService _bllSvc;
public ESIID(ITXESIIDService svc)
{
_bllSvc = svc;
}
public Message LookupESIID(string guid, string id)
{
return GetById(guid, id);
}
private Message GetById(string guid, string id)
{
apiAuthentication = new APIKeyAuthentication();
if (!apiAuthentication.IsValidAPIKey(guid))
return APIError();
//_bllSvc = new TXESIIDService(); <--- WANTING TO AVOID THIS!!!!
var results = _bllSvc.SelectByID(id);
return results.Count == 0 ? NoResults() : CreateMessage(results);
}
}
Fine, that's pretty straight forward. I did add a constructor parameter because with the call to the BLL TXESIIDService method.
So now, I've altered my Global file for Ninject which now looks something like this:
public class Global : NinjectWcfApplication
{
protected override void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new RestServiceModel());
}
private static void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("ESIID", new NinjectServiceHostFactory(), typeof(ESIID)));
}
}
and also added my module:
public class RestServiceModel : NinjectModule
{
public override void Load()
{
Bind<ITXESIIDService>().To<TXESIIDService>();
Bind<IDoNotSolicitService>().To<DoNotSolicitService>();
}
}
And for troubleshooting I added by own NinjectServiceHostFactory
public class NinjectServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var serviceTypeParameter = new ConstructorArgument("serviceType", serviceType);
var baseAddressesParameter = new ConstructorArgument("baseAddresses", baseAddresses);
return KernelContainer.Kernel.Get<NinjectServiceHost>(serviceTypeParameter, baseAddressesParameter);
}
}
When I run this as in I get an error that the line:
return KernelContainer.Kernel.Get<NinjectServiceHost>(serviceTypeParameter, baseAddressesParameter);
cannot be null.
Obviously I'm missing something here, but I can't figure out what. I've tried various things at this point and most examples I see are for WCF services and the RESTful ones I've manage to find are just a bit too geared for those familiar w/Ninject or IoC regulars.
Also, In my Business and Data layers (using entity framework), I'm looking to implement Ninject there as well, is it best practice to have the layers wired up separately or is it possible to do it all in one spot?
Thanks.
UPDATE 1
I have corrected the binding issue, but this still bombs on me. I'm using Ninject.Extensions.Wcf and it's bombing looking for NinjectWcfApplication.cs file which doesn't seem right at all. I used NuGet to include a package for Ninject, could this be a version issue?

This may be a typo, but are you meaning to bind interfaces to themselves in your module? Usually you bind an interface to a concrete type. If Ninject tries to instantiate an interface type, it will definitely fail, and depending on specific error-handling behavior of your Ninject setup it'll either throw out or return null. So, make sure the module is configured to look for a real class:
public class RestServiceModel : NinjectModule
{
public override void Load()
{
Bind<ITXESIIDService>().To<TXESIIDService>();
...
}
}

You always have to call the base method when overriding a virtual method. See Application_Start().

Regarding your update: I am new to ninject so I don't know anything about older versions but I suppose you try out the Example Ninject Extensions first. If they run, you know it must be something else.

Related

C# -> Windows service -> WCF ServiceHost -> ? How to implement long running process

I'm developing a service, which is to run 24/7 and is to be controlled over MVC web-site, but it's not that important.
What does matter though, is that What I have now is (for windows service):
protected override void OnStart(string[] args)
{
if (this.ServiceHost != null)
this.ServiceHost.Close();
this.ServiceHost = new ServiceHost(typeof(ParserService));
this.ServiceHost.Open();
}
And ParserService is as the following at the moment:
public class ParserService : IParserService
{
private ParserFacade FacadeForParser;
public void Start()
{
if(FacadeForParser == null)
this.FacadeForParser = new ParserFacade();
this.FacadeForParser.Start();
}
public bool IsRunning()
{
return true;
}
public void Stop()
{
this.FacadeForParser.Stop();
}
public List<string> GetAllTitles()
{
return this.FacadeForParser.GetAllTitles();
}
}
And the problem is: In Parser service, FacadeForParser is never seaved for the next call. Seems like I misunderstood lifecycle of WCF classes... So Can anyone tell me correct way to implement this part?
I do need: 1 instance of ParserFacade to work with it through all the requests ever handled by WCF part of the service.
I have found a solution for this case. It's not what I originally was thinking about, but result is exactly what I was looking for..
In ParserService I have added the following attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class ParserService : IParserService
And now any request coming to ParserService is handled by single original instance of the class..
If anybody knows another way of achieving the same result without such attribute, you are welcome to share.

Ninject Providers -> Get another dependency inside the provider

I'm wondering what the best practices is here.
I need to construct a DbContext for my multi tenanted application, so I have made a Dependency provider like this:
public class TenantContextFactoryProvider : Provider<DbContext>
{
protected override DbContext CreateInstance(IContext context)
{
var tenant = // How to get the tenant through ninject??
return new DbContext(tenant.ConnectionString);
}
}
I need ninject to resolve the tenant dependency, but I'm not sure how to do this?
While service locator certainly works, constructor injection is another choice.
public class TenantContextFactoryProvider : Provider<DbContext>
{
ITenant tenant;
public TenantContextFactoryProvider(ITenant tenant)
{
this.tenant = tenant;
}
protected override DbContext CreateInstance(IContext context)
{
return new DbContext(tenant.ConnectionString);
}
}
This is a bit embarassing, but I guess if it can happen to me, it can happen to someone else as well.
I forgot to include using Ninject, which is why the extension method context.Kernel.Get wasn't showing up, in IntelliSense.
So my code ended up looking like this:
using Ninject;
public class TenantContextFactoryProvider : Provider<DbContext>
{
protected override DbContext CreateInstance(IContext context)
{
var tenant = context.Kernel.Get<ITenant>();
return new DbContext(tenant.ConnectionString);
}
}

Autofac attribute injection failing on attributes

I've found a few questions on this, but they tend to point to the exact documentation I'm following... but it's still not working.
I'm building a fairly simple ASP.NET MVC 4 site, and the plan is to use ActionFilterAttribute-based logging. I have a DataAccessProvider class which opens transactions with the database and provides unit-of-work instances, and I'm trying to inject it into the filter attribute.
The documentation says that it's enough to just call RegisterFilterProvider(), and ensure that the relevant types are registered. It specifically says that there is no need to register the attribute, but I've tried both with and without. My code currently looks something like this:
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register(x => new EntityAccessProvider())
.As<IDataAccessProvider>()
.InstancePerHttpRequest();
builder.RegisterType<DebugLogAttribute>().PropertiesAutowired();
// ^ I've tried it with and without this line
builder.RegisterFilterProvider();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
The example in the docs then just places a property on the filter, so I've done the same:
public class DebugLogAttribute : ActionFilterAttribute
{
private IDataAccessProvider DataAccess { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext) { ... }
public override void OnActionExecuted(ActionExecutedContext filterContext) { ... }
}
The docs say that's all is required - not even a constructor to inject into; it's done by property injection. When I run this code, however, The DataAccess property is always null; Autofac seems to ignore it. I know the registration works properly because it's correctly injecting EntityAccessProvider into my controllers, but it's not working for attributes. What am I missing?
Your property of type IDataAccessProvider has to be public for injection to work. You can still mark DebugLogAttribute, IDataAccessProvider and it's implementation as internal if you prefer.
[DebugLogAttribute]
public class HOmeController : Controller
{
public ActionResult Index()
{
return View();
}
}
internal class DebugLogAttribute : ActionFilterAttribute
{
public IDataAccessProvider DataAccess { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Debugger.Break();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Debugger.Break();
}
}
internal interface IDataAccessProvider {}
internal class DataAccessProvider:IDataAccessProvider {}
I've been having the same issue in asp dotnet core but the current solution (making it public) doesn't seem to work. What I find odd is that the comment below is regarding a web-api but I'm using a normal ASP.NET Core MVC (MVC6). So if anyone has the same problem, try out the solution below.
https://docs.autofac.org/en/latest/integration/webapi.html#standard-web-api-filter-attributes-are-singletons
Unlike the filter provider in MVC, the one in Web API does not allow you to specify that the filter instances should not be cached. This means that all filter attributes in Web API are effectively singleton instances that exist for the entire lifetime of the application.
public override async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
MyService = context.HttpContext.
RequestServices.GetService(typeof(IMyService)) as IMyService;
}

using ninject with a remoting server

I have a class Server that implements interface IServer that is accessible using .net remoting (i have no chioce on the matter JICYAW).
internally this server uses other classes to implement logic and data access.
this server class has constructor injected dependencies that it needs to do its job.
when a client calls in (per call) the remoting framework will instatiate a Server instance using a parameterless constructor and not (of course) using Ninject.
how can i get Ninject to be the one in charge for new'ing up the class ?
i have seen this similar SO question but this isnt relevant for Ninject.
thanks for your help
You can create a service facade that will be called by the client. This facade will internally call your container to resolve the real service. For instance:
public class ServiceFacade : IService
{
private readonly IService service;
// default constructor
public ServiceFacade()
{
this.service = YourContainer.Current.Resolve<IService>();
}
void IService.ServiceOperation()
{
this.service.ServiceOperation();
}
}
What might work is to intercept the calls to those objects using a proxy and forward the calls to the real object. Note that I'm not very experienced with this, so I'm not sure if this actually works, but here goes:
public class DependencyInjectionProxy : RealProxy
{
private object realInstance;
public DependencyInjectionProxy(Type classToProxy,
object realInstance) : base(classToProxy)
{
this.realInstance = realInstance;
}
public static T MakeProxy<T>(T realInstance)
{
return (T)(new DependencyInjectionProxy(typeof(T),
realInstance).GetTransparentProxy());
}
public override IMessage Invoke(IMessage msg)
{
if (msg is IMethodCallMessage)
{
var message = (IMethodCallMessage)msg;
object value = message.MethodBase.Invoke(
this.realInstance, message.Args);
Console.WriteLine(value);
return new ReturnMessage(value, null, 0, null, message);
}
return msg;
}
}
This works when you do something like this:
var container = new YourContainer();
container.RegisterSingle<IService, Service>();
IService proxy = DependencyInjectionProxy.MakeProxy<IService>(
container.Resolve<IService>());
proxy.SomeMethod();
This works great, but to be honest, I have no idea how to configure this in a way that you can intercept incoming calls this way. Somewhere you need to register your DependencyInjectionProxy, but that's where my experience with remoting stops :-)

Database injection into a validation attribute with ASP MVC and Castle Windsor

I need some help - I am trying to use a custom validation attribute in an ASP.NET MVC web project that needs to make a database call.
I have windsor successfully working for the controllers and the IRepository interface is injected normally. The problem arrises when I need to inject the repository into the attribute class.
The attribute class has the following code:
public class ValidateUniqueUrlNodeAttribute : AbstractValidationAttribute
{
private readonly string message;
private readonly IArticleRepository articleRepository;
public ValidateUniqueUrlNodeAttribute(string message)
{
this.message = message;
}
public ValidateUniqueUrlNodeAttribute(string message, IArticleRepository articleRepository):this(message)
{
this.articleRepository = articleRepository;
}
public override IValidator Build()
{
var validator = new UniqueUrlNodeValidator(articleRepository) { ErrorMessage = message };
ConfigureValidatorMessage(validator);
return validator;
}
My problem is that I cannot seem to make Windsor intercept the contruction of the attribute to pass in the IArticleRepository
The current code in my global.asax file is as follows:
container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(Container));
container
.RegisterControllers(Assembly.GetExecutingAssembly())
.AddComponent<IArticleRepository, ArticleRepository>()
.AddComponent<ValidateUniqueUrlNodeAttribute>();
Any help would be greatly appreciated.
AFAIK no dependency injection container can directly manage an attribute, since it's instantiated by the runtime and there's no way to intercept that.
However, they can cheat by either:
Using a static gateway to the container (example), or
Using a "BuildUp" feature that injects whatever dependencies are found within an already-constructed object. This is called BuildUp in Unity or InjectProperties in Autofac.
Windsor doesn't support #2 (ref1, ref2), so you can either:
Try one of the hacks to make Windsor support #2 (hack1, hack2)
Use a static gateway
Implement your own IValidatorBuilder and make it use Windsor to create validators. I'm sure this is implemented somewhere but I can't find it right now...
Don't know if this helps, but I subclassed ValidationAttribute to expose a Resolve<T>() method like so:
public abstract class IocValidationAttribute : ValidationAttribute
{
protected T Resolve<T>()
{
return IocHelper.Container().Resolve<T>();
}
}
Then it can be used in any custom ValidatorAttribute that needs to hit a database:
public class UniqueEmailAttribute : IocValidationAttribute
{
public override bool IsValid(object value)
{
ICustomerRepository customerRepository = Resolve<ICustomerRepository>();
return customerRepository.FindByEmail(value.ToString()) == null;
}
}
I think it's a variation of the 'Static Gateway' approach mentioned by Mauricio Scheffer. I don't know if this is a good design or not. I'm not a huge fan of it, I'd rather the dependency was injected more 'elegantly', though I can't use constructor injection obviously, I'd like to use Property injection but can't work out a way to hook into the ASP.NET MVC framework code to do this (I've even pored though the MVC2 source code).
I was able to wire it up [using Autofac as it happens, but it's just constructor injection via the ASP.NET MVC DependencyResolver] in this answer, enabling one to write:
class MyModel
{
...
[Required, StringLength(42)]
[ValidatorService(typeof(MyDiDependentValidator), ErrorMessage = "It's simply unacceptable")]
public string MyProperty { get; set; }
....
}
public class MyDiDependentValidator : Validator<MyModel>
{
readonly IUnitOfWork _iLoveWrappingStuff;
public MyDiDependentValidator(IUnitOfWork iLoveWrappingStuff)
{
_iLoveWrappingStuff = iLoveWrappingStuff;
}
protected override bool IsValid(MyModel instance, object value)
{
var attempted = (string)value;
return _iLoveWrappingStuff.SaysCanHazCheez(instance, attempted);
}
}
With some helper classes (look over there), you wire it up e.g. in ASP.NET MVC like so in the Global.asax :-
DataAnnotationsModelValidatorProvider.RegisterAdapterFactory(
typeof(ValidatorServiceAttribute),
(metadata, context, attribute) =>
new DataAnnotationsModelValidatorEx(metadata, context, attribute, true));
Hmm.
Can you test the effect of removing the (string message) ctor, and see if that at least forces Castle to use the ctor with the Repostiory ?
Otherwise we call AddComponent(name, type, type). Other than that it really should work...
Also does this hint at my first idea ? How do I use Windsor to inject dependencies into ActionFilterAttributes

Categories