![](/img/trans.png)
[英]How to inject HttpContextBase using Autofac in ASP.NET MVC 4
[英]How should i inject Autorest Client with TokenProvider using autofac in asp.net mvc 5?
我想通過使用autofac正確注入使用api的autorest客戶端依賴項(用戶在登錄后將擁有自己的令牌,但對於某些方法,他們可以在登錄前使用api,不需要令牌)。 我知道這不是直接涉及autofac的問題,而是更多關於autofac的問題,但是我想舉一個確切的例子,這樣我可以獲得更好的建議(也許我做錯了這是一個概念性問題)。 我尋找了一些示例,但發現了所有示例,但在所有示例中,它們只是針對一個用戶的實現,他們沒有使用tokenprovider,而是只是傳遞了一個預知的令牌(這不是應用程序的用戶令牌)。
我試過的是用包裝的參數(已經注冊的多個依賴項將彼此作為構造函數參數)注冊autorest客戶端到容器中。
這是我注冊服務的方式:
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
var sp = ServicePointManager.FindServicePoint(new Uri(ConfigurationManager.AppSettings["WebApiBaseUrl"]));
sp.ConnectionLeaseTimeout = 60 * 1000; // 1 minute
builder.Register(c => new HttpContextWrapper(HttpContext.Current))
.As<HttpContextBase>()
.InstancePerRequest();
builder.RegisterType<TokenProvider>().As<ITokenProvider>().InstancePerLifetimeScope();
builder.RegisterType<TokenCredentials>().Keyed<ServiceClientCredentials>("credentials").InstancePerLifetimeScope();
builder.RegisterType<WebApiClient>()
.As<IWebApiClient>()
.WithParameter("baseUri", new Uri(ConfigurationManager.AppSettings["WebApiBaseUrl"])
).WithParameter("credentials",
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ServiceClientCredentials),
(pi, ctx) => ctx.ResolveKeyed<ServiceClientCredentials>(pi.Name))
).SingleInstance();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
和我的服務:
public partial class WebApiClient : ServiceClient<WebApiClient>, IWebApiClient
{
public WebApiClient(System.Uri baseUri, ServiceClientCredentials credentials = null, params DelegatingHandler[] handlers) : this(handlers)
{
if (baseUri == null)
{
throw new System.ArgumentNullException("baseUri");
}
BaseUri = baseUri;
if (credentials != null)
{
Credentials = credentials;
Credentials.InitializeServiceClient(this);
}
}
}
public class TokenProvider : ITokenProvider
{
private readonly HttpContextBase _context;
public TokenProvider(HttpContextBase context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<AuthenticationHeaderValue> GetAuthenticationHeaderAsync(CancellationToken cancellationToken)
{
// this should be async i know(another topic to ask in mvc 5)
var token =_context.Session["ServiceToken"]?.ToString();
if (string.IsNullOrWhiteSpace(token))
{
throw new InvalidOperationException("Could not get an access token from HttpContext.");
}
return new AuthenticationHeaderValue("Bearer", token);
}
}
public class TokenCredentials : ServiceClientCredentials
{
//I want to use this constructor
public TokenCredentials(ITokenProvider tokenProvider);
}
這是我得到的例外
內部異常無法將類型為
Autofac.Core.ResolvedParameter
對象Autofac.Core.ResolvedParameter
轉換為Microsoft.Rest.ServiceClientCredentials
類型。
無法將類型為
Autofac.Core.ResolvedParameter
對象Autofac.Core.ResolvedParameter
轉換為Microsoft.Rest.ServiceClientCredentials
類型。
表示您正在使用ResolvedParameter
對象,而ServiceClientCredentials
是預期的。
您的代碼中有
.WithParameter("credentials",
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(ServiceClientCredentials),
(pi, ctx) => ctx.ResolveKeyed<ServiceClientCredentials>(pi.Name))
)
WithParameter
具有3個重載:
WithParameter(string parameterName, object parameterValue)
:知道參數名稱並可以在注冊時提供。 Autofac將為您創建一個NamedParameter
對象。 WithParameter(Func<ParameterInfo, IComponentContext, bool> parameterSelector, Func<ParameterInfo, IComponentContext, object> valueProvider)
:當您不知道參數名稱和/或在注冊時無法提供值時。 Autofac將為您創建一個ResolvedParameter
對象。 WithParameter(Parameter parameter)
:提供您自己創建的Parameter
對象。 在您的情況下,您正在使用第一個選項。 Autofac將為您創建一個NamedParameter,並提供ResolvedParameter
作為值。
要解決該錯誤,您不應以這種方式使用第一個重載,而可以使用第二個重載:
.WithParameter((pi, ctx) => pi.ParameterType == typeof(ServiceClientCredentials),
(pi, ctx) => ctx.ResolveKeyed<ServiceClientCredentials>(pi.Name)))
我的最終代碼現在就像。(現在可以正常使用了。但是,如果您對此代碼有任何建議或關注,請隨時告訴我。)
builder.Register(c => new HttpContextWrapper(HttpContext.Current) as HttpContextBase)
.As<HttpContextBase>().InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Request)
.As<HttpRequestBase>().InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Response)
.As<HttpResponseBase>().InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Server)
.As<HttpServerUtilityBase>().InstancePerLifetimeScope();
builder.Register(c => c.Resolve<HttpContextBase>().Session)
.As<HttpSessionStateBase>().InstancePerLifetimeScope();
builder.RegisterType<TokenProvider>().As<ITokenProvider>().InstancePerLifetimeScope();
builder.RegisterType<TokenCredentials>().Keyed<ServiceClientCredentials>("credentials").InstancePerLifetimeScope();
builder.RegisterType<WebApiClient>()
.As<IWebApiClient>()
.WithParameter("baseUri", new Uri(ConfigurationManager.AppSettings["WebApiBaseUrl"])
)
.WithParameter((pi, ctx) => pi.ParameterType == typeof(ServiceClientCredentials),
(pi, ctx) => ctx.ResolveKeyed<ServiceClientCredentials>(pi.Name))
.InstancePerLifetimeScope();
還有我的代幣提供商;
public async Task<AuthenticationHeaderValue> GetAuthenticationHeaderAsync(CancellationToken cancellationToken)
{
string token = "NonAuthorizedUserDummyToken";
await Task.Delay(500);
token = _context.Session?["ServiceToken"]?.ToString();
return new AuthenticationHeaderValue("Bearer", token);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.