English 中文(简体)
Authorization and Windsor
原标题:

I m trying to implement my custom authorize attribute like:

 public class MyCustomAuth : AuthorizeAttribute
{
    private readonly IUserService _userService;

    public MyCustomAuth(IUserService userService)
    {
        _userService= userService;
    }
... continued
 }

I am using Castle Windsor for automatically resolve the dependency.

When I try to use it as an attribute of an action method obviously I am asked to pass the parameter or I need to have a parameter-less constructor that should resolve in some way it s dependency.

I tried to inject the dependency with a property but Windsor is not injecting it.

The only option I see now would be to instantiate manually the concrete object dependency loosing the benefit of Windsor.

How would you solve this problem?

最佳回答

You cannot use DI with attributes - they re metadata;

public class MyCustomAuth : AuthorizeAttribute
{
    public void OnAuthorization(...)
    {
         IUserService userService = ServiceLocator.Current.GetInstance<IUserService>();
    }
}

Learn about Windsor/ServiceLocator here.

See similar question here.

问题回答

You can use a custom ControllerActionInvoker and inject property dependencies (you can t do constructor injection because the framework handles instantiation of attributes). You can see a blog post I just did on this technique.

You did not supply any castle code or configuration examples. Therefore, I am assuming you are new to castle and unfimilar with the registration process.

First of all, any object you want to act upon must come from Castle Windsor via a registered type. With that said, you are going down the wrong path by trying to use castle windsor with attributes - because attributes are not referenced in code, but instead are reflected upon. Therefore, there is not a place for IoC (Castle Windsor in this case) to create the object.

I say this, because what you are trying to accomplish has already been done via different means. First of all, put your dependency injection on your controllers.

public class PostController
{
  private IUserService _userService;
  public PostController (IUserService userService)
  {
    _userService = userService;
  }

  // other logic

}

For Castle to work, you have register all types. So, you have to register IUserService, and what services implement that interface, within Castle Windsor. You can do this via a manual process in your global.asax with container.AddComponentWithLifeStyle; or the more preferred method is to use a configuration file.

Using a configuration file, your IUserService would look something like this:

<?xml version="1.0" encoding="utf-8" ?>
<castle>
    <components>
        <!--lifestyle="singleton|thread|transient|pooled|webrequest|custom"-->

        <component
            id="UserService"
            service="MyMvcProject.IUserService, MyMvcProject"
            type="MyMvcProject.UserService, MyMvcProject"
            lifestyle="transient">
        </component>
    </components>
</castle>

MyMvcProject is the name of your project and make sure to use the exact namespace and fully qualified name of the interface, and type. Please give code samples of your actual namespaces, else we cannot help you any further.

Before that will work, you will need to modify your app.config or web.config to register the searchGroup for Castle Windsor:

<configSections>

    <section name="castle" 
        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"/>

</configSections>

<castle configSource="castle.config"/>

Now that you are all registered and setup, it is time to tell your MVC application to "Use Castle Windsor to create each instance of my Controllers." Doing this means that Castle Windsor, being an Inversion-of-Control (aka IoC) container, will inspect the dependencies of your controller and see that it depends on IUserService and implement an instance of UserService. Castle will look into its configuration of registered types and see that you have registered a service for IUserService. And, it will see in your configuration file that you want to implement the concrete class of UserService that implements IUserService. So, the IoC container will return UserService when a dependency on IUserService is requested.

But before that can happen, you have to tell your MVC application to use your configuired IoC container. You do this by registering a new ControllerFactory. To do that, see my answer over at this question:

Why is Castle Windsor trying to resolve my Content and Scripts folder as a controller?

And notice the global.asax part of how to register that code. It works quite well!

Now, when all of that is said and done, you want to authorize a user. Use the normal [Authorize] that implements Forms Authentication, and use your _userService to grab any user details of the signed in user.





相关问题
WebForms and ASP.NET MVC co-existence

I am trying to make a WebForms project and ASP.NET MVC per this question. One of the things I ve done to make that happen is that I added a namespaces node to the WebForms web.config: <pages ...

Post back complex object from client side

I m using ASP.NET MVC and Entity Framework. I m going to pass a complex entity to the client side and allow the user to modify it, and post it back to the controller. But I don t know how to do that ...

Create an incremental placeholder in NHaml

What I want to reach is a way to add a script and style placeholder in my master. They will include my initial site.css and jquery.js files. Each haml page or partial can then add their own required ...

asp.net mvc automapper parsing

let s say we have something like this public class Person { public string Name {get; set;} public Country Country {get; set;} } public class PersonViewModel { public Person Person {get; ...

structureMap mocks stub help

I have an BLL that does validation on user input then inserts a parent(PorEO) and then inserts children(PorBoxEO). So there are two calls to the same InsertJCDC. One like this=>InsertJCDC(fakePor)...

ASP.NET MVC: How should it work with subversion?

So, I have an asp.net mvc app that is being worked on by multiple developers in differing capacities. This is our first time working on a mvc app and my first time working with .NET. Our app does not ...

System.Web.Mvc.Controller Initialize

i have the following base controller... public class BaseController : Controller { protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (...

热门标签