Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时使用网络凭据更新HttpMessageHandler或创建类型化HttpClient_C#_Asp.net Core_.net Core_Asp.net Core Mvc - Fatal编程技术网

C# 在运行时使用网络凭据更新HttpMessageHandler或创建类型化HttpClient

C# 在运行时使用网络凭据更新HttpMessageHandler或创建类型化HttpClient,c#,asp.net-core,.net-core,asp.net-core-mvc,C#,Asp.net Core,.net Core,Asp.net Core Mvc,我需要根据使用应用程序的最终用户,在应用程序运行时传递网络凭据以模拟域用户。我还不知道如何通过Services.AddHttpClient和HttpClientFactory生成HttpClient,其中绑定到单个用户 var httpClientBuilder = services .AddHttpClient<SomeHttpClint>() .ConfigurePrimaryHttpMessageHandler(s

我需要根据使用应用程序的最终用户,在应用程序运行时传递网络凭据以模拟域用户。我还不知道如何通过Services.AddHttpClient和HttpClientFactory生成HttpClient,其中绑定到单个用户

        var httpClientBuilder = services
            .AddHttpClient<SomeHttpClint>()
            .ConfigurePrimaryHttpMessageHandler(sp => new HttpClientHandler
            {
                AllowAutoRedirect = false,
                UseCookies = false,
                Credentials = new NetworkCredential("user", "pass", "domain")
            });
var httpClientBuilder=services
.AddHttpClient()
.ConfigurePrimaryHttpMessageHandler(sp=>new HttpClientHandler
{
AllowAutoRedirect=false,
UseCookies=false,
凭据=新网络凭据(“用户”、“通过”、“域”)
});
因此,我的问题如下:

  • 是否可以使用命名或类型化的HttpClientFactorys来生成代表单个用户的HttpClient?或者,有没有更好的解决方案来生成绑定到单个用户的一组HttpClient

  • 在将http客户端工厂注入控制器(例如中间件类型)之外,是否可以访问http客户端工厂


  • 您可以在运行时注册客户端。这是我的变通代码。 定义2类:

    public class DynamicHttpClientFactoryOptions : IConfigureNamedOptions<HttpClientFactoryOptions>
    {
        private readonly DynamicHttpClientFactoryWrapper _options;
    
        public DynamicHttpClientFactoryOptions(DynamicHttpClientFactoryWrapper options)
        {
            _options = options;
        }
    
        public void Configure(HttpClientFactoryOptions options)
        {
        }
    
        public void Configure(string name, HttpClientFactoryOptions options)
        {
            if (!_options.TryGetValue(name, out var configure)) return;
    
            configure(options);
        }
    }
    public class DynamicHttpClientFactoryWrapper : ConcurrentDictionary<string, Action<HttpClientFactoryOptions>>
    {
        
        public HttpClient GetOrCreateClient(string name, Action<HttpClientFactoryOptions> optionsBuilder)
        {
            if (!ContainsKey(name) || !TryGetValue(name, out var action))
            {
                TryAdd(name, optionsBuilder);
            }
    
            
            //you can store serviceProvider in startup class
            var factory = _serviceProvider.GetRequiredService<IHttpClientFactory>();
            return factory.CreateClient(name);
        }
    }
    

    此代码为HttpClient配置依赖项注入。这意味着,如果您的控制器或可由DI创建的任何其他类型需要
    SomeHttpClient
    依赖项,它将从DI容器接收该依赖项。也可以要求指定客户。在最坏的情况下,您可以将工厂添加为DI依赖项,而不是为#2添加类型化的clienta,这实际上是在要求做DI已经做过的事情。那样你什么也得不到。显示如何将HttpClientFactory本身作为依赖项注入,并请求命名客户端。仅与命名客户端一起使用
    IHttpClientFactory
    ,无法解决此问题。您仍然需要在编译时注册命名的客户机。也许您可以使用委派处理程序@ChrisPratt我曾研究过委托处理程序,但根据我在源代码中看到的情况,我认为这是不可能的。凭据绑定到客户端处理程序,并且在初始化客户端后无法更改客户端处理程序。
    services.AddHttpClient(...);
    services.AddSingleton<DynamicHttpClientFactoryWrapper>();
    services.ConfigureOptions<DynamicHttpClientFactoryOptions>();
    
    public class SomeClass
    {
        private readonly DynamicHttpClientFactoryWrapper _wrapper;
    
        public SomeClass(DynamicHttpClientFactoryWrapper wrapper)
        {
            _wrapper = wrapper;
        }
        
        public async Task Work()
        {
            var client = _wrapper.GetOrCreateClient(name/*userid or something else*/, options =>
            {
                options.HttpClientActions.Add(c =>
                {
                    c.BaseAddress = new Uri("...");
                });
                options.HttpMessageHandlerBuilderActions.Add(handlerBuilder =>
                {
                    var handler = new HttpClientHandler
                    {
                        Credentials = new NetworkCredential("user", "pass", "domain")
                    }
    
                    handlerBuilder.PrimaryHandler = handler;
                });
            });
    
            var response = await client.SendAsync(request);
            //do your work...
        }
    }