You can use message handlers from ASP.NET Web API. It is a typical security scenation, when you need to get some user token from query string, URL or HTTP Header
http://www.asp.net/web-api/overview/advanced/http-message-handlers
1.When you need simply to extract userId from URL, then use it as parameter for your Api method and ASP.NET WebAPI will do work for you, like
[HttpGet, Route("{userId}/roles")]
public UserRoles GetUserRoles(string userId, [FromUri] bool isExternalUser = true)
It work for such request
http://.../15222/roles?isExternalUser=false
2.If it is security scenario, please refer to http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
Basically you will need some MessageHandler or you can use filter attributes as well, it is mechanism in ASP.NET Web API to intercept each call.
If you need to process each request then MessageHandler is your way. You need implement MessageHanler and then register it.
To say easily, typical MessageHandler is class derived from MessageHandler or DelegatingHandler with SendAsync method overriden:
class AuthenticationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Your code here
return base.SendAsync(request, cancellationToken);
}
}
And you need register it
static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Other code for WebAPI registerations here
config.MessageHandlers.Add(new AuthenticationHandler());
}
}
and call it from Global.asax.cs
WebApiConfig.Register(GlobalConfiguration.Configuration);
Some example dummy hypotetical implementation of such handler (here you need to imeplement your UidPrincipal from IPrincipal and UidIdentity from IIdentity)
public class AuthenticationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
var queryString = actionContext.Request.RequestUri.Query;
var items = HttpUtility.ParseQueryString(queryString);
var userId = items["uid"];
// Here check your UID and maybe some token, just dummy logic
if (userId == "D8CD2165-52C0-41E1-937F-054F24266B65")
{
IPrincipal principal = new UidPrincipal(new UidIdentity(uid), null);
// HttpContext exist only when hosting as asp.net web application in IIS or IISExpress
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
else
{
Thread.CurrentPrincipal = principal;
}
return base.SendAsync(request, cancellationToken);
}
catch (Exception ex)
{
this.Log().Warn(ex.ToString());
return this.SendUnauthorizedResponse(ex.Message);
}
}
else
{
return this.SendUnauthorizedResponse();
}
}
catch (SecurityTokenValidationException)
{
return this.SendUnauthorizedResponse();
}
}
}
And lets access it from some ASP.NET WebApi method or some property in WebAPI class
var uid = ((UidIdentity)User.Identity).Uid
Like the all other DI containers, it will dispose IDisposable instances for you with respecting life time of instance.
In your stuation, if instance is registered as Scoped
(Instance Per Request). It will dispose this instance after request is completed.
Edit:
In official documents they don't mention this.
So Let's check source code to be sure:
When a scope is created, ServiceScopeFactory returns a new ServiceScope which is depended with ServiceProvider and disposable.
ServiceProvider
has private List<IDisposable> _transientDisposables;
which keeps disposable services when TransientCallSite
is invoke
d in CaptureDisposable
method. Also ServiceProvider
has private readonly Dictionary<IService, object> _resolvedServices = new Dictionary<IService, object>();
which keeps all services for Scoped
.
When liftime/scope finishes, the ServiceScope
is disposed. Then it disposes ServiceProvider
which disposes all _transientDisposables
and then it checks _resolvedServices
and disposes disposable services in the dictionary in ServiceProvider
.
Edit(13.06.2017): They mention in official documents now. Service Lifetimes
Best Solution
A controller contains information (state) about the incoming request.
If you had only one controller to handle many requests then they would all be confused and users would likely get some strange results.