Я хочу правильно внедрить клиентскую зависимость autorest, которая использует api (у пользователей будет свой собственный токен для использования после входа в систему, но они могут использовать 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
в типMicrosoft.Rest.ServiceClientCredentials
.