ASP.NET MVC 5 Controller custom constructor [duplicate] - c#

I have my own inherited App.Controller from Mvc.Controller which then all of my controllers inherit from. I wrote a provider utilizing an interface and implemented it as MyService and the constructor takes the Server property of Mvc.Controller which is of HttpServerUtilityBase.
However, I instantiate MyService in App.Controller's constructor. The problem is that the Server property of the Controller is null when constructing MyService. I have used public Controller () : base() { } to get the base to be constructed. However, Server remains null.
I would like to avoid Web.HttpContext.Current.Server if possible.
Has any one have a work around for this problem?
Edit: Well, I have implemented tvanfosson's suggestion, and when my app constructs MyService in the property get method, Server is still null.
Edit 2: Nevermind, I was a goof. I had another Controller using Server aswell and did not change that. Case closed.

Use delayed initialization to construct your service.
private MyService service;
public MyService Service
{
get
{
if (this.service == null)
{
this.service = new MyService(this.Server);
}
return this.service;
}
}
Then, your service isn't actually instantiated until it is used in the controller action and by that time the Server property has been set.

I instantiate MyService in App.Controller's constructor.
There's your problem. You need to pass an instance of MyService which has already been constructed into your App.Controller's constructor. Take a look at the Inversion of Control / Dependency Injection patterns, and take a look at some of the libraries which make these patterns easy (see this list).

Why do you need the Server reference? Are you doing stuff like url/html encoding? If so, you could use HttpUtility instead and get rid of the context reference entirely.

This is a very old question, but the subject is still relevant. So, one hint in 2017 that was possibly not available in 2009:
It is true that in the Controller constructor Server is null. But you can use the OnActionExecuting event:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
CurrentServer = Server; // CurrentServer is some instance variable I need later.
}
This works fine for me.

According to this site, if you have this Controller:
public class MyController : Controller
{
private string folderPath;
public MyController()
{
// Throws an error because Server is null
folderPath = Server.MapPath("~/uploads");
// Throws an error because this.ControllerContext is null
folderPath = this.ControllerContext.HttpContext.Server.MapPath("~/uploads");
}
}
Then you want to initialize it this way:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
// now Server has been initialized
folderPath = Server.MapPath("~/uploads");
}

Related

Orchard CMS, Autofac Relationship

I am trying to create a "A(UserManager) needs to create instances of B(UserClient)" relationship (http://code.google.com/p/autofac/wiki/RelationshipTypes) where B(UserClient) needs a HttpSessionStateBase..
UserClient
public class UserClient : IUserClient
{
public UserClient(HttpSessionStateBase session)
{
//...
}
//...
}
UserManager
public class UserManager : IUserManager
{
private readonly Func<IUserClient> userClientPerRequest;
private IUserClient UserClient
{
get
{
return userClientPerRequest();
}
}
public UserManager(Func<IUserClient> userClientPerRequest)
{
this.userClientPerRequest = userClientPerRequest;
}
public void DoStuff()
{
UserClient.DoStuff();
}
This is where is register autofac stuff
public class MyModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<UserManager>().As<IUserManager>().SingleInstance();
builder.RegisterType<UserClient>().As<IUserClient>().InstancePerHttpRequest();
builder.RegisterModule(new AutofacWebTypesModule());
//If i try this, i get Error 1 (printing errors after this code-block)
builder.Register<Func<IUserClient>>(c => c.Resolve<IUserClient>);
//If i try this, i get Error 2
builder.Register<Func<IUserClient>>(c => {
var ctx = c.Resolve<IComponentContext>();
return ctx.Resolve<IUserClient>;
});
//If i try this, well i always get null from GetService..
builder.Register<Func<IUserClient>>(c =>
DependencyResolver.Current.GetService<IUserClient>);
}
Looking at Autofac: Reference from a SingleInstance'd type to a HttpRequestScoped , they use some RequestContainer but i can find no such thing. :)
Error 1
This resolve operation has already ended. When registering components using lambdas, the IComponentContext 'c' parameter to the lambda cannot be stored. Instead, either resolve IComponentContext again from 'c', or resolve a Func<> based factory to create subsequent components from.
Error 2
No scope with a Tag matching 'AutofacWebRequest' 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.
I have tried switching .InstancePerHttpRequest() to .InstancePerLifetimeScope() and a whole other different stuff.. Anyone have any ideas?
Thanks
When adding Autofac registrations manually in Orchard, use InstancePerMatchingLifetimeScope("shell"), if you need a singleton or InstancePerMatchingLifetimeScope("work"), if you need per-request instance.
I'm not sure if HttpSessionStateBase ctor argument can actually be resolved from the container. You could put IHttpContextAccessor there instead and use it to access the session state object inside IUserClient implementation.
And as Jim Bolla suggested - Func<IUserClient> (factory) is already available out of the box.
I don't think you need to do either of those registrations. Because of Relationship Types, Func<IUserClient> should already be available to you.

DependencyResolver.Current.GetService always returns null

According to this tutorial, to use Ninject in my Asp.net MVC 3 application , all I have to do is install package via Nuget and configure dependencies.
Follow these steps
Install Package-Ninject.MVC3
In NinjectMVC3.cs
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IReCaptchaValidator>().To<ReCaptchaValidate>();
}
In Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Registe(RegisterModel model)
{
var myObject = DependencyResolver.Current.GetService<IReCaptchaValidator>(); //always null
}
myObject always returns null.
I've tried kernel.Bind<IReCaptchaValidator>().To<ReCaptchaValidate>().InRequestScope(), but not effect!
myObject continues null
In this post here on StackOverflow, I was told to use DependencyResolver.Current.GetService(TYPE) to retrieve the instance of an object.
In the post you refer to, you were not told to use DependencyResolver, just that it's possible to use it. You shouldn't use it, as it's a well known anti-pattern.
While using the DependencyResolver directly should work, you really shouldn't do it that way.
Instead, you should use Constructor Injection, which would be to have your class take the type as a parameter of your constructor.
public class MyController : Controller {
IReCaptchaValidator _validator;
public MyController(IReCaptchaValidator validator)
{
_validator = validator;
}
}
Then, in your method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Registe(RegisterModel model)
{
var myObject = _validator;
}
I had the same problem.
On the same function, I could resolve an interface just fine, while another interface did not resolve. They were both registered!
When resolving manually, it seems that you don't get errors!
Pretty funny, but I just found about!
Once I injected the interface in a controller constructor and enabled all exceptions, then I get an exception saying that there was no public constructor for my implementation!
Try that and you will most likely find the root cause.

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 :-)

Property Injection into an Action Filter

I'm trying to get Property Injection working on a Custom Action Filter Attribute. It is working as it is supposed to, however, I'd like to use DI on the Property itself. My filter looks like this
[AttributeUsage(AttributeTargets.Class)]
public sealed class HeaderFilterAttribute : ActionFilterAttribute
{
public IMarketService MarketService
{ get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var view = (ViewResultBase)filterContext.Result;
if (view != null)
{
BaseViewModel viewModel = view.ViewData.Model as BaseViewModel;
if (viewModel != null)
viewModel.Header = GetHeaderScript();
}
base.OnActionExecuted(filterContext);
}
private string GetHeaderScript()
{
//Use MarketService here and return header script
return "script";
}
}
This is how I'm configuring the property using StructureMap inside my BootStrapper class.
//HeaderFilterAttribute
IMarketRepository marketRepository = new SqlMarketRepository();
IMarketService marketService = new MarketService(marketRepository);
ObjectFactory.Container.Configure(r => r.ForConcreteType<HeaderFilterAttribute>().
Configure.WithProperty("MarketService").
EqualTo(marketService));
My problem is I do not have access to SqlMarketRepository since all my concrete types are injected via DI and I really don't want to use concrete types in my bootstrapper. So the ultimate question now is, how do I inject MarketService into the Filter attribute without resorting to the above? :)
In your ObjectFactory.Initialize() call, add the following line:
SetAllProperties(x => x.OfType<IMarketService>());
That will inject the configured IMarketService instance into any property of type IMarketService, on any object retrieved from the container.
I think you need a custom action invoker implementation that will resolve the filters. You can dig a Windsor sample out of my company's implementation (about 1/2 way down). There should be several more available online. I know I've seen some on this site.
PS. I noticed you're using a base view model to populate a header. I'd recommend using the ViewData[] collection with a static key instead of inheritance in your view model. :)

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