簡體   English   中英

我應該如何在asp.net mvc 5中使用autofac向TokenProvider注入Autorest Client?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM