Using Spring.Net to inject dependencies into ASP.NET MVC ActionFilters - asp.net

I'm using MvcContrib to do my Spring.Net ASP.Net MVC controller dependency injection.
My dependencies are not being injected into my CustomAttribute action filter.
How to I get my dependencies into it?
Say you have an ActionFilter that looks like so:
public class CustomAttribute : ActionFilterAttribute, ICustomAttribute
{
private IAwesomeService awesomeService;
public CustomAttribute(){}
public CustomAttribute(IAwesomeService awesomeService)
{
this.awesomeService= awesomeService;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Do some work
}
}
With a Spring.Net configuration section that looks like so:
<object id="CustomAttribute " type="Assembly.CustomAttribute , Assembly" singleton="false">
<constructor-arg ref="AwesomeService"/>
</object>
And you use the Attribute like so:
[Custom]
public FooController : Controller
{
//Do some work
}

The tough part here is that ActionFilters seem to get instantiated new with each request and in a context that is outside of where Spring is aware. I handled the same situations using the Spring "ContextRegistry" class in my ActionFilter constructor. Unfortunately it introduces Spring specific API usage into your code, which is a good practice to avoid, if possible.
Here's what my constructor looks like:
public MyAttribute()
{
CustomHelper = ContextRegistry.GetContext().GetObject("CustomHelper") as IConfigHelper;
}
Keep in mind that if you are loading multiple Spring contexts, you will need to specify which context you want in the GetContext(...) method.

Related

GetControllerName not being called in derived DefaultHttpControllerSelector implementation

I'm attempting to do versioning with ASP.NET Web API. I have created a simple controllerselector that derives from DefaultHttpControllerSelector.
public class MyHttpControllerSelector : DefaultHttpControllerSelector
{
public MyHttpControllerSelector(HttpConfiguration config) : base(config) { }
public override string GetControllerName(HttpRequestMessage request)
{
return "SomeControllerName";
}
}
In my WebApiConfig.Register:
config.MapHttpAttributeRoutes();
config.Services.Replace(typeof(IHttpControllerSelector), new MyHttpControllerSelector(config));
My problem is GetControllerName is never called. I may be misunderstanding the intent of this function, but I have seen plenty of examples, some right from Microsoft that use this method.
What am I missing?
In my case it was because I was not calling config.Routes.MapHttpRoute(). I was just using Attribute Routing. Once I used MapHttpRoute() it seemed to start calling GetControllerName.

MVC Web .Net: Intercept all calls before reaching controller?

I have a .Net MVC web application (Not WebAPI), and I want to intercept all calls to the web app before they reach the controller, check for a value in the request headers, and do something if the value isn't present (such as presenting a 404). What's the ideal way to do this? Keep in mind this is not a Web API application, just a simple web application.
Depending on what specifically you want to do, you could use a default controller which all other controllers extend. That way you can override OnActionExecuting or Initialize and do your check there.
public class ApplicationController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
//do your stuff here
}
}
public class YourController : ApplicationController
{
}
You're looking for global action filters.
Create a class that inherits ActionFilterAttribute, override OnActionExecuting() to perform your processing, and add an instances to global filter collection in Global.asax.cs (inside RegisterGlobalFilters())

How to make this Spring Injection work

I have this inside my spring xml file:
<object type="Test.Web.Utilities.TestClass, Test.Web" singleton="false" id="TestClass">
<property name="TestService" ref="TestService"/>
</object>
In the TestClass I have this:
public ITestService TestService { get; set; }
and this:
public void TestMethod()
{
var x = TestService.ExampleMethod();
}
next, inside my controller I have this:
TestClass t = new TestClass();
t.TestMethod();
However, I don't seem to get this to work. other spring related stuff on the controller works well.
Any ideas how can I get this to work?
EDIT: Forgot to add, the error I get is a NullReferenceException
This cannot work since you're creating TestClass instance via new and Spring is of course not aware to inject dependencies into objects created via the frameworks new. You'll not find a .NET IOC framework that can do this (for good reasons!).
So what you need to do is to inject instances of TestClass into your controller. You could register these instances with a request or prototype scope.
You cannot use the normal "new" keyword, because this is handled via the .NET VM. You actually need to call Spring's Activator Context to give you an instance.
First you acquire the Spring.NET Activator context by calling:
IApplicationContext ctx = ContextRegistry.GetContext();
Then you can get an instance of your class specified in your configuration xml:
ITestService svc = (ITestService)ctx.GetObject("TestClass");
This enables you to configure via your XML file what concrete implementation class that implements the ITestService interface.

Using Autofac for DI into WCF service hosted in ASP.NET application

I'm having trouble injecting services dependencies into my WCF service using Autofac 1.4.5. I've read and followed the Autofac wiki page on WcfIntegration but my debugging shows me that my WCF service is created by the System.ServiceModel.Dispatcher.InstanceBehavior.GetInstance() method and not by the AutofacWebServiceHostFactory. What am I doing wrong?
I've set up my ajax.svc file to look like the one in the example for use with WebHttpBinding:
<%# ServiceHost Language="C#" Debug="true"
Service="Generic.Frontend.Web.Ajax, Generic.Frontend.Web"
Factory="Autofac.Integration.Wcf.AutofacWebServiceHostFactory,
Autofac.Integration.Wcf" %>
My WCF service class Ajax is defined like this:
namespace Generic.Frontend.Web
{
[ServiceContract]
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Ajax
{
public MapWebService MapWebService { get; set;}
public Ajax() {
// this constructor is being called
}
public Ajax(MapWebService mapWebService)
{
// this constructor should be called
MapWebService = mapWebService;
}
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[OperationContract(Name = "mapchange")]
public MapChangeResult ProcessMapChange(string args)
{
// use the injected service here
var result = MapWebService.ProcessMapChange(args);
return result;
}
}
}
Now I've used the wiring up in the Global.asax.cs as shown in the wiki mentioned above:
var builder = new ContainerBuilder();
builder.RegisterModule(new AutofacModuleWebservice());
var container = builder.Build();
AutofacServiceHostFactory.Container = container;
with
class AutofacModuleWebservice : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<Ajax>();
builder.Register<MapWebService>().ContainerScoped();
}
}
In my web.config I have
<services>
<service name="Generic.Frontend.Web.Ajax">
<endpoint address="http://mysite.com/ajax.svc/" binding="webHttpBinding"
contract="Generic.Frontend.Web.Ajax" />
</service>
</services>
.
The service already works fine but I can't get the Autofac bits (read: creation/injection) to work. Any ideas?
Edit:
Removing the default constructor unfortunately leads to the following exception:
System.InvalidOperationException:
The service type provided could not be loaded as a service because it does not
have a default (parameter-less) constructor. To fix the problem, add a default
constructor to the type, or pass an instance of the type to the host.
Cheers, Oliver
Is your service setup with InstanceContextMode.Single? If it is then wcf will create your service using the default constructor. To get around this change your instance context mode and let autofac manage the lifetime of your service.
Try deleting the default Ajax constructor and modifying your constructor to this. If it gets run with mapWebService == null that would indicate a resolution problem.
public Ajax(MapWebService mapWebService = null)
{
// this constructor should be called
MapWebService = mapWebService;
}
I just got the same System.InvalidOperationException and solved it by changing the ServiceBehavior InstanceContextMode of the implementation from InstanceContextMode.PerCall to InstanceContextMode.PerSession, perhaps your AutoFac lifetime scope is out of sync with your web service implementation?
For testing AutoFac service creation I recommend creating a unit test and directly resolving them as this will highlight any issues and give more meaningful exception messages. For services with a request lifetime scope create a test aspx page and again resolve them directly.
I had the same problem and came across this question while searching for an answer.
In my case, using property injection worked, and the code in the question already has a property that can be used:
namespace Generic.Frontend.Web
{
[ServiceContract]
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Ajax
{
// inject the dependency here
public MapWebService MapWebService { get; set;}
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[OperationContract(Name = "mapchange")]
public MapChangeResult ProcessMapChange(string args)
{
// use the injected service here
var result = MapWebService.ProcessMapChange(args);
return result;
}
}
}
and register to use property injection (sample code from the wiki and syntax has changed as this is now using version 2.5.2.830):
builder.RegisterType<Ajax>().PropertiesAutowired();
Following the instructions solved it for me:
code.google.com/p/autofac/wiki/… I simply do : builder.RegisterType();
and I've followed their instuructions for changing the .svc file.
When you look at your .svc file you do not get any hints about something being wrong there btw?
You host it throu the iis and do not utilize WAS, I do not see your code for overriding global.asax.cs
Add the global file to your solution and there you implement:
protected void Application_Start(object sender, EventArgs e)
{
// build and set container in application start
IContainer container = AutofacContainerBuilder.BuildContainer();
AutofacHostFactory.Container = container;
}
AutofacContainerBuilder is my container builder.

Alternatives to System.web.ui.page

I have an ASP.Net application and I've noticed through using profilers that there is a sizable amount of processing that happens before my page even runs. In my application, we don't used viewstate, asp.Net session, and we probably don't require most of the overhead that comes of a consequence of using the asp.net page lifecycle. Is there some other class I can easily inherit from that will cut out all the Asp.Net stuff, and just let my handle writing to the page by myself?
I've heard that ASP.Net MVC can cut down page loads considerably, simply because it doesn't use the old asp.net lifecycle, and handles pages differently. Is there an easy way, maybe by simply having my web pages inherit some other class to take advantage of something like this. I would like a solution that works in ASP.Net 2.0 if at all possible.
Most articles I found where talking about using the Page as a base class and implementing functionality on top of that, it looks like you need to make your own MyPage class that implements IHttpHandler
From the MSDN article
using System.Web;
namespace HandlerExample
{
public class MyHttpHandler : IHttpHandler
{
// Override the ProcessRequest method.
public void ProcessRequest(HttpContext context)
{
context.Response.Write("This is an HttpHandler Test.");
context.Response.Write("Your Browser:");
context.Response.Write("Type: " + context.Request.Browser.Type + "");
context.Response.Write("Version: " + context.Request.Browser.Version);
}
// Override the IsReusable property.
public bool IsReusable
{
get { return true; }
}
}
}
Again, from the article: To use this handler, include the following lines in a Web.config file.
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="handler.aspx" type="HandlerExample.MyHttpHandler,HandlerTest"/>
</httpHandlers>
</system.web>
</configuration>
I'd take a look at the source code for System.web.ui.page and take a look at what it does to guide you. My guess is that it mostly just calls the different methods in the asp.net page lifecycle in the right order. You'd do something similar by calling your own page_load from the ProcessRequest method. That would route to your individual implementation of your classes that implement your MyPage.
I've never thought of doing something like this before and it sounds pretty good since I really don't use any of the bloated webforms functionality. MVC may make this whole exercise futile, but it does seem pretty neat.
My Quick Example
new base:
using System.Web;
namespace HandlerExample
{
// Replacement System.Web.UI.Page class
public abstract class MyHttpHandler : IHttpHandler
{
// Override the ProcessRequest method.
public void ProcessRequest(HttpContext context)
{
// Call any lifecycle methods that you feel like
this.MyPageStart(context);
this.MyPageEnd(context);
}
// Override the IsReusable property.
public bool IsReusable
{
get { return true; }
}
// define any lifecycle methods that you feel like
public abstract void MyPageStart(HttpContext context);
public abstract void MyPageEnd(HttpContext context);
}
Implementation for the page:
// Individual implementation, akin to Form1 / Page1
public class MyIndividualAspPage : MyHttpHandler
{
public override void MyPageStart(HttpContext context)
{
// stuff here, gets called auto-magically
}
public override void MyPageEnd(HttpContext context)
{
// stuff here, gets called auto-magically
}
}
}
If you don't need all this "asp.net stuff", you may wish to implement a custom IHttpHandler. Afaik, there are no other standard IHttpHandlers to reuse except the Page class.
To do this you should start by looking at the System.Web.UI.PageHandlerFactory class and the corresponding System.Web.IHttpHandlerFactory interface.
From there you will probably look at the System.Web.IHttpHandler inferface and the System.Web.UI.Page class.
Basically you will write your own IHttpHandlerFactory that generates IHttpHandlers that handles the page requests.

Resources