0

It has been decided we should have a common upload http api across different applications. I have a file upload controller which I want to use in multiple webapi projects.

My upload controller looks something like this

namespace MyNamespace
{
    [Authorize("PolicyName")]
    [Route("Upload")]
    public class UploadController : Controller
    {
        [HttpPost]
        [Route("Upload")]
        public async Task<IActionResult> Upload(UploadModel model)
        {
             // impl..
             return Ok();
        }
    }
}

Naively I thought I'd just extract this into a class library and I'd be able to register it, but I can't find how?

Regardless, I do not think this is the correct method to use. I want to be able to configure the Authorize policy name, and potentially the routes. So I'm thinking I want to perhaps build up the controller, its routes and authorize setting and register it some how?

My idea of an api would be like..

((IApplicationBuilder)app).UseUploadController(config => {
    config.PolicyName = "Whatever",
    config.UploadRoute = "UploadStuff"
});

... this would create and register the controller. No idea where to start though. I have absolutely no clue on how controllers are discovered or if they can be registered programatically.

Anyone got any pointers or libraries to look at for inspiration?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Mardoxx
  • 4,372
  • 7
  • 41
  • 67

2 Answers2

1

You can have your controller in class library that you reference (as you wanted) and then in any project you can inherit from that controller where you want. If you don't want any other functionality, you can leave child class empty, but if you want to add something, you can easily extend it it. Also, you can have any other name of controller and can set different routes, authorizations etc.

Shadowed
  • 956
  • 7
  • 19
  • Why didn't I think of this!! Very simple, and also means that permissions etc are in similar places -- i.e. on the controllers. I shall leave this question open as I'd still like to know out of interest if what I proposed is possible. – Mardoxx Jul 07 '17 at 12:27
0

If you have a controller in a different assembly, then you can make your MVC application discover it by adding the proper reference and modifying routes, as explained in this answer

As for the configuration, values passed to attributes need to be compile-time constants, so you cannot dynamically set them while running the MVC app. You can create a custom attribute which implements your logic. So for Authorize you would have something like this:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class SetPermissionsAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        // Get everyting you need, for example from Web.config
    }

    (...)
}

As stated in the code snippet's comment, different applications can store dynamic values for example as Web.config settings, and you can read these values inside the attribute.

Example of a custom AuthorizeAttribute:

Kapol
  • 6,383
  • 3
  • 21
  • 46