是否可以从 aspnet 核心 api 中的中间件向控制器发送值?
Is it possible to send values to controller from middleware in aspnet core api?
我想知道是否可以将值从中间件发送到 controllerAPI?
例如,我想捕获一个特定的 header 并发送到控制器。
类似的东西:
public class UserTokenValidatorsMiddleware
{
private readonly RequestDelegate _next;
//private IContactsRepository ContactsRepo { get; set; }
public UserTokenValidatorsMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Path.Value.Contains("auth"))
{
if (!context.Request.Headers.Keys.Contains("user-token"))
{
context.Response.StatusCode = 400; //Bad Request
await context.Response.WriteAsync("User token is missing");
return;
}
// Here I want send the header to all controller asked.
}
await _next.Invoke(context);
}
}
#region ExtensionMethod
public static class UserTokenValidatorsExtension
{
public static IApplicationBuilder ApplyUserTokenValidation(this IApplicationBuilder app)
{
app.UseMiddleware<UserTokenValidatorsMiddleware>();
return app;
}
}
#endregion
我所做的就是利用这些东西:
- 依赖注入(Unity)
ActionFilterAttribute
(因为我可以访问 IDependencyResolver)
HierarchicalLifetimeManager
(所以我每个请求都会得到一个新实例)(阅读依赖范围)
动作过滤器
public class TokenFetcherAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var token = actionContext.Request.Headers.Authorization.Parameter;
var scheme = actionContext.Request.Headers.Authorization.Scheme;
if (token == null || scheme != "Bearer")
return;
var tokenProvider = (TokenProvider) actionContext.Request.GetDependencyScope().GetService(typeof(TokenProvider));
tokenProvider.SetToken(token);
}
}
TokenProvider
public class TokenProvider
{
public string Token { get; private set; }
public void SetToken(string token)
{
if(Token != null)
throw new InvalidOperationException("Token is already set in this session.");
Token = token;
}
}
Unity配置
container.RegisterType<TokenProvider>(new HierarchicalLifetimeManager()); // Gets a new TokenProvider per request
控制器
[TokenFetcher]
public class SomeController : ApiController
{
private TokenProvider tokenProvider;
// The token will not be set when ctor is called, but will be set before method is called.
private string Token => tokenProvider.Token;
public SomeController(TokenProvider provider)
{
tokeProvider = provider;
}
public string Get()
{
return $"Token is {Token}";
}
}
更新
对于 asp.net 核心使用内置 DI 容器。
将 TokenProvider
注册为 Transient 以根据请求获得一个新的:
services.AddTransient<TokenProvider>();
我想知道是否可以将值从中间件发送到 controllerAPI?
例如,我想捕获一个特定的 header 并发送到控制器。
类似的东西:
public class UserTokenValidatorsMiddleware
{
private readonly RequestDelegate _next;
//private IContactsRepository ContactsRepo { get; set; }
public UserTokenValidatorsMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Path.Value.Contains("auth"))
{
if (!context.Request.Headers.Keys.Contains("user-token"))
{
context.Response.StatusCode = 400; //Bad Request
await context.Response.WriteAsync("User token is missing");
return;
}
// Here I want send the header to all controller asked.
}
await _next.Invoke(context);
}
}
#region ExtensionMethod
public static class UserTokenValidatorsExtension
{
public static IApplicationBuilder ApplyUserTokenValidation(this IApplicationBuilder app)
{
app.UseMiddleware<UserTokenValidatorsMiddleware>();
return app;
}
}
#endregion
我所做的就是利用这些东西:
- 依赖注入(Unity)
ActionFilterAttribute
(因为我可以访问 IDependencyResolver)HierarchicalLifetimeManager
(所以我每个请求都会得到一个新实例)(阅读依赖范围)
动作过滤器
public class TokenFetcherAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var token = actionContext.Request.Headers.Authorization.Parameter;
var scheme = actionContext.Request.Headers.Authorization.Scheme;
if (token == null || scheme != "Bearer")
return;
var tokenProvider = (TokenProvider) actionContext.Request.GetDependencyScope().GetService(typeof(TokenProvider));
tokenProvider.SetToken(token);
}
}
TokenProvider
public class TokenProvider
{
public string Token { get; private set; }
public void SetToken(string token)
{
if(Token != null)
throw new InvalidOperationException("Token is already set in this session.");
Token = token;
}
}
Unity配置
container.RegisterType<TokenProvider>(new HierarchicalLifetimeManager()); // Gets a new TokenProvider per request
控制器
[TokenFetcher]
public class SomeController : ApiController
{
private TokenProvider tokenProvider;
// The token will not be set when ctor is called, but will be set before method is called.
private string Token => tokenProvider.Token;
public SomeController(TokenProvider provider)
{
tokeProvider = provider;
}
public string Get()
{
return $"Token is {Token}";
}
}
更新
对于 asp.net 核心使用内置 DI 容器。
将 TokenProvider
注册为 Transient 以根据请求获得一个新的:
services.AddTransient<TokenProvider>();