Removing an inherited Attribute in .net - c#

I got a ASP.NET MVC controller like this
[Authorize]
public class ObjectController : Controller
{
public ObjectController(IDataService dataService)
{
DataService = dataService;
}
public IDataService DataService { get;set;}
}
The Authorize attribute is defined as "Inherited=true" in the framework. So when i make the next controller:
public class DemoObjectController : ObjectController
{
public DemoObjectController(IDataService dataService)
: base (dataService)
{
DataService = new DemoDataService(DataService);
}
}
It gets the authorize attribute, but i don't want it here. I want the Demo Object controller to be available to everyone, cause it just uses fake data.
I guess I'll implement my own Authorize attribute that don't get inherited, for i can't find any way to remove the attribute from the inherited class.

Since it is marked as inherited, there isn't much you can do in this case (since you don't control the code that is checking for the attribute via reflection). Implementing your own attribute seems the most practical option.
With MVC you can also often achieve the same functionality with overrides (the On* methods), which might be worth looking into.

If a base type requires authorization then all child types ought to require authorization as well. I think that you ought to inherit from a different type but a workaround would be to declare your own AthorizeAttribute that works for this particular instance.

Related

Could base class attribute be triggered first?

It looks like in .NET base class attributes are triggered after Attributes that belong to inherited classes. Seems off to me or am I doing something wrong ?.
All classes in my application inherit from a base class with [AuthorizationAttribute] but only some classes have [LoggingAttribute].
When I'm accessing a method in HomeController, why does my [LoggingAttribute] gets hit before Authorization and how can I trigger base class authorization attribute first and Logging second ?
[AuthorizationAttribute]
public class BaseController
{
//....class methods
}
[LoggingAttribute]
public class HomeController: BaseController
{
//....class methods
}
Attributes:
public class AuthorizationAttribute : ActionFilterAttribute
{
//...API token gets parsed into Id/Pw
}
public class LoggingAttribute: ActionFilterAttribute
{
//...Logging record saved with Id/pw established above
}
For this specific case, since it is about authorization, make sure to derive your custom AuthorizationAttribute from AuthorizeAttribute or implement IAuthorizationFilter.
Authorization filters get executed prior to action filter attributes.
This guarantees that controller action methods only get executed when authorized.

ActionResult<TValue> in vanilla ASP.NET (non ASP.NET Core)

I'm trying to integrate Swagger into a somewhat big vanilla ASP.NET MVC app. I was going to use Swashbuckle or NSwag after reading this article. The problem is my controllers are inhereted from the generic base class like this:
public class BookController : BaseController<Book>
And then I have a GET method in a base class:
public abstract class BaseController<T> : ApiController where T : SomeEntityConstraint
{
...
public virtual IHttpActionResult Get(int id)
{
T queryResult = _repository.Get(id)
...
return Ok(queryResult);
}
}
I was planning to add [SwaggerResponse(HttpStatusCode.OK, typeof(T))] attribute to a method and this is where I got CSharp'd hard. Apparetnly one can't simply use generic type parameters in an attribute. They must be known at compile time.
I can see from here that ASP.NET Core has a neat ActionResult<TValue> class. But I can't find a substitute in a vanilla ASP.NET. I wonder what I can do in situation like this without introducing unwanted coupling and methods overriding in concrete Controller classes implementation or moving the project to a brand new ASP.NET Core.
I’m pretty sure you can implement an own ActionResult class which inherits from IHttpActionResult and just acts as proxy... i think NSwag will pick it up as if it were the ASP.NET Core one...
Disclaimer: I’m one of the devs of NSwag...

How to determine which constructor Autofac uses when resolving

I'm using a custom JsonConverter and JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Objects to create the required instances during deserialization. The instances are created by resolving the types from an Autofac IOC container. Everything works fine, except...
I have several "core objects" that request a unique Id in the constructor from a service (which is correctly injected into the constructor). When deserializing this should not happen because it is fairly expensive and the Ids will be populated from the Json file anyway once the instance has been created.
Currently, when resolving from within the custom JsonConverter I'm using _scope.Resolve<T>(new TypedParameter(typeof(IIdService), null)); to then - in the called constructor - check for null and act accordingly.
Some people apparently consider multiple constructors worse than a code-smell when using an IOC (which makes me wonder why Autofac offers several features regarding the topic), but in the context of deserialization I think it can make perfect sense.
As far as I can tell Autofac has mechanisms to decide which constructor to use during registration, but not when resolving. My preferred solution would be to add a custom attribute to a constructor (e.g. [CtorForDeserializing]) and use that for deciding. Is that possible?
There are a couple of extension points Autofac has for reflection-based activations but doesn't have well documented yet that may help you out: IConstructorFinder and IConstructorSelector.
IConstructorFinder is used to locate all the available constructors on a type. The core example is the DefaultConstructorFinder which locates only public constructors. If you wanted to, say, hide constructors with particular attributes or start finding internal/private constructors, you could create a custom finder. This really only happens once so you don't get to make runtime choices here.
IConstructorSelector is used to choose, at resolve time, which constructor should be used to instantiate the object. There are a couple of these in core Autofac, but the primary example is the MostParametersConstructorSelector which selects the constructor that has the most available matching parameters at the time. Constructors get found by the IConstructorFinder and then that set of constructors is what is presented to the IConstructorSelector to choose from. This is where you could make more runtime choices since it happens every time the object is resolved.
There are extension methods to help you add your finder/selector to a registration:
builder.RegisterType<MyType>()
.FindConstructorsWith(new MyConstructorFinder())
.UsingConstructor(new MyConstructorSelector());
You don't have to customize both things, you can just do one or the other if you want. I'm just showing you the extensions.
Actually Autofac is able to decide which constructor to use both ways - during registration or resolution. For resolution part here is the quote from documentation: "Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container" (see here).
Consider following example.
public interface ISomeService
{
Guid Id { get; }
}
public class SomeService : ISomeService
{
public Guid Id { get; }
public SomeService()
{
Id = Guid.NewGuid();
}
public SomeService(Guid id)
{
Id = id;
}
}
// Startup.cs:
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerLifetimeScope();
// TestController.cs:
[Route("api/[controller]")]
public class TestController : Controller
{
private readonly IComponentContext _context;
public TestController(IComponentContext context)
{
_context = context;
}
[HttpGet]
public IActionResult Get()
{
var service = _context.Resolve<ISomeService>();
return Ok(service.Id);
}
[HttpGet("{id}")]
public IActionResult Get(Guid id)
{
var service = _context.Resolve<ISomeService>(new NamedParameter("id", id));
return Ok(service.Id);
}
}
// GET http://localhost:5000/api/test/e0198f72-6337-4880-b608-68935122cdea
// each and every response will be the same: e0198f72-6337-4880-b608-68935122cdea
// GET http://localhost:5000/api/test
// this way it responds with some random guid each time endpoint is called
Travis Illig sent me in the right direction - thanks!
I ended up implementing a solution around the following details:
Implement custom attributes, e.g.: public class DeserializeCtorAttribute : Attribute { }, which will be used by the (also to be implemented) IConstructorFinder.
Implement an empty generic interface, e.g.: IDeserializable<T>, which will be used for resolving the services/components.
Let relevant component classes implement the interface (MyClass : IDeserializable<MyClass>) and add an extra registration for the component:
_builder.RegisterType<MyClass>().As<IDeserializable<MyClass>>()
.FindConstructorsWith(MyConstructorFinder);
Use the implemented DeserializeCtorAttribute in the desired constructor of MyClass.
Let the JsonConverter create the required instance by calling (MyClass) scope.Resolve(IDeserializable<MyClass>); casting is required, but safe. Due to the registration the instance will be created using the desired constructor.

Asp.net MVC employ a controller's Disposable Property in other controllers

We have a Disposable property in a controller is needed in other controllers too. For example, suppose the following property in a controller:
public ClassName<Template> Name { get; set; }
Which will be instantiated in the same controller's constructor like this:
public SomeController()
: this(new ClassName<Template>())
{
}
public SomeController(ClassName<Template> name)
{
Name = name;
}
Can I use the property by instantiating the container controller in other controllers?
If your question is: can I create an instance of the controller and use it in another one, the answer is yes, controllers are just classes which you can instantiate and use. Just like any other.
The thing that concerns me though, is that it seems you are using a property that should be a proper singleton as something that isn't, by re-instantiating another class that seems slightly related. If you can, move the property to an other class. Make it singleton, and use it accordingly.

Ninject WithConstructorArgument not overriding global binding for type?

I have my general bindings, and one of which is this:
Bind<IHasher>().To<SHA256Hasher>();
This works great, as there are a few classes throughout which use this hasher. However there are one or two controllers which require another type of hasher for using the hash with 3rd parties, such as gravatar which expect md5 hashes. So then I do the below:
Bind<ISomeController>().To<SomeController>().Named("SomeController").WithConstructorArgument("emailHasher", new Md5Hasher());
Then my controller looks like:
public class SomeController : Controller
{
private IHasher emailHasher;
public CampaignController(IHasher emailHasher)
{
this.emailHasher = emailHasher;
}
}
When debugging I would expect the IHasher to be Md5Hasher, however it is an Sha256Hasher. So is this expected behaviour and any way to make it use the overridden type?
I suppose this is an MVC controller. The MVC Framework will resolve a SomeController not an ISomeController. Hence your binding does not apply but Ninject will use the implicit binding SomeController ToSelf instead.
Create a binding for SomeController ToSelf instead.

Categories