1616
1717#endregion
1818
19+ using  System ; 
1920using  System . Diagnostics . CodeAnalysis ; 
2021using  Grpc . Net . ClientFactory ; 
2122using  Grpc . Net . ClientFactory . Internal ; 
@@ -289,9 +290,7 @@ private static IHttpClientBuilder AddGrpcClientCore<
289290        // because we access it by reaching into the service collection. 
290291        services . TryAddSingleton ( new  GrpcClientMappingRegistry ( ) ) ; 
291292
292-         IHttpClientBuilder  clientBuilder  =  services . AddGrpcHttpClient < TClient > ( name ) ; 
293- 
294-         return  clientBuilder ; 
293+         return  services . AddGrpcHttpClient < TClient > ( name ) ; 
295294    } 
296295
297296    /// <summary> 
@@ -306,25 +305,22 @@ private static IHttpClientBuilder AddGrpcHttpClient<
306305    { 
307306        ArgumentNullThrowHelper . ThrowIfNull ( services ) ; 
308307
309-         services 
310-             . AddHttpClient ( name ) 
311-             . ConfigurePrimaryHttpMessageHandler ( ( )  => 
312-             { 
313-                 // Set PrimaryHandler to null so we can track whether the user 
314-                 // set a value or not. If they didn't set their own handler then 
315-                 // one will be created by PostConfigure. 
316-                 return  null ! ; 
317-             } ) ; 
308+         var  builder  =  services . AddHttpClient ( name ) ; 
318309
319-         services . PostConfigure < HttpClientFactoryOptions > ( name ,  options  => 
310+         builder . Services . AddTransient < TClient > ( s  => 
320311        { 
321-             options . HttpMessageHandlerBuilderActions . Add ( builder => 
312+             var  clientFactory  =  s . GetRequiredService < GrpcClientFactory > ( ) ; 
313+             return  clientFactory . CreateClient < TClient > ( name ) ; 
314+         } ) ; 
315+ 
316+         // Insert primary handler before other configuration so there is the opportunity to override it. 
317+         // This should run before ConfigureDefaultHttpClient so the handler can be overriden in defaults. 
318+         var  configurePrimaryHandler  =  ServiceDescriptor . Singleton < IConfigureOptions < HttpClientFactoryOptions > > ( new  ConfigureNamedOptions < HttpClientFactoryOptions > ( name ,  options => 
319+         { 
320+             options . HttpMessageHandlerBuilderActions . Add ( b => 
322321            { 
323-                 if  ( builder . PrimaryHandler   ==   null ) 
322+                 if  ( HttpHandlerFactory . TryCreatePrimaryHandler ( out   var   handler ) ) 
324323                { 
325-                     // This will throw in .NET Standard 2.0 with a prompt that a user must set a handler. 
326-                     // Because it throws it should only be called in PostConfigure if no handler has been set. 
327-                     var  handler  =  HttpHandlerFactory . CreatePrimaryHandler ( ) ; 
328324#if NET5_0_OR_GREATER 
329325                    if  ( handler  is  SocketsHttpHandler  socketsHttpHandler ) 
330326                    { 
@@ -336,37 +332,34 @@ private static IHttpClientBuilder AddGrpcHttpClient<
336332                    } 
337333#endif
338334
339-                     builder . PrimaryHandler  =  handler ; 
335+                     b . PrimaryHandler  =  handler ; 
336+                 } 
337+                 else 
338+                 { 
339+                     b . PrimaryHandler  =  UnsupportedHttpHandler . Instance ; 
340340                } 
341341            } ) ; 
342-         } ) ; 
343- 
344-         var  builder  =  new  DefaultHttpClientBuilder ( services ,  name ) ; 
342+         } ) ) ; 
343+         services . Insert ( 0 ,  configurePrimaryHandler ) ; 
345344
346-         builder . Services . AddTransient < TClient > ( s => 
345+         // Some platforms don't have a built-in handler that supports gRPC. 
346+         // Validate that a handler was set by the app to after all configuration has run. 
347+         services . PostConfigure < HttpClientFactoryOptions > ( name ,  options => 
347348        { 
348-             var  clientFactory  =  s . GetRequiredService < GrpcClientFactory > ( ) ; 
349-             return  clientFactory . CreateClient < TClient > ( builder . Name ) ; 
349+             options . HttpMessageHandlerBuilderActions . Add ( builder => 
350+             { 
351+                 if  ( builder . PrimaryHandler  ==  UnsupportedHttpHandler . Instance ) 
352+                 { 
353+                     throw  HttpHandlerFactory . CreateUnsupportedHandlerException ( ) ; 
354+                 } 
355+             } ) ; 
350356        } ) ; 
351357
352358        ReserveClient ( builder ,  typeof ( TClient ) ,  name ) ; 
353359
354360        return  builder ; 
355361    } 
356362
357-     private  class  DefaultHttpClientBuilder  :  IHttpClientBuilder 
358-     { 
359-         public  DefaultHttpClientBuilder ( IServiceCollection  services ,  string  name ) 
360-         { 
361-             Services  =  services ; 
362-             Name  =  name ; 
363-         } 
364- 
365-         public  string  Name  {  get ;  } 
366- 
367-         public  IServiceCollection  Services  {  get ;  } 
368-     } 
369- 
370363    private  static   void  ReserveClient ( IHttpClientBuilder  builder ,  Type  type ,  string  name ) 
371364    { 
372365        var  registry  =  ( GrpcClientMappingRegistry ? ) builder . Services . Single ( sd =>  sd . ServiceType  ==  typeof ( GrpcClientMappingRegistry ) ) . ImplementationInstance ; 
@@ -384,4 +377,14 @@ private static void ReserveClient(IHttpClientBuilder builder, Type type, string
384377
385378        registry . NamedClientRegistrations [ name ]  =  type ; 
386379    } 
380+ 
381+     private  sealed  class  UnsupportedHttpHandler  :  HttpMessageHandler 
382+     { 
383+         public  static   readonly  UnsupportedHttpHandler  Instance  =  new  UnsupportedHttpHandler ( ) ; 
384+ 
385+         protected  override  Task < HttpResponseMessage >  SendAsync ( HttpRequestMessage  request ,  CancellationToken  cancellationToken ) 
386+         { 
387+             return  Task . FromException < HttpResponseMessage > ( HttpHandlerFactory . CreateUnsupportedHandlerException ( ) ) ; 
388+         } 
389+     } 
387390} 
0 commit comments