@@ -40,8 +40,13 @@ public static class GraphClientFactory
40
40
private static readonly string _baseAddress = "https://graph.microsoft.com/" ;
41
41
42
42
/// Microsoft Graph service nationa cloud endpoints
43
- private static readonly Dictionary < string , string > cloudList ;
44
-
43
+ private static readonly Dictionary < string , string > cloudList = new Dictionary < string , string >
44
+ {
45
+ { Global_Cloud , "https://graph.microsoft.com" } ,
46
+ { USGOV_Cloud , "https://graph.microsoft.com" } ,
47
+ { China_Cloud , "https://microsoftgraph.chinacloudapi.cn" } ,
48
+ { Germany_Cloud , "https://graph.microsoft.de" }
49
+ } ;
45
50
46
51
/// Global endpoint
47
52
public const string Global_Cloud = "Global" ;
@@ -52,98 +57,22 @@ public static class GraphClientFactory
52
57
/// Germany endpoint
53
58
public const string Germany_Cloud = "Germany" ;
54
59
55
- static GraphClientFactory ( )
56
- {
57
- cloudList = new Dictionary < string , string > ( ) ;
58
- cloudList . Add ( Global_Cloud , "https://graph.microsoft.com" ) ;
59
- cloudList . Add ( USGOV_Cloud , "https://graph.microsoft.com" ) ;
60
- cloudList . Add ( China_Cloud , "https://microsoftgraph.chinacloudapi.cn" ) ;
61
- cloudList . Add ( Germany_Cloud , "https://graph.microsoft.de" ) ;
62
- }
63
-
64
-
65
- /// Property Version for version value
66
- public static string Version { set ; get ; } = "v1.0" ;
67
-
68
- /// <summary>
69
- /// Creates a new <see cref="HttpClient"/> instance configured with the handlers provided.
70
- /// </summary>
71
- /// <param name="handlers">An ordered list of <see cref="DelegatingHandler"/> instances to be invoked as an
72
- /// <see cref="HttpRequestMessage"/> travels from the <see cref="HttpClient"/> to the network and an
73
- /// <see cref="HttpResponseMessage"/> travels from the network back to <see cref="HttpClient"/>.
74
- /// The handlers are invoked in a top-down fashion. That is, the first entry is invoked first for
75
- /// an outbound request message but last for an inbound response message.</param>
76
- /// <returns>An <see cref="HttpClient"/> instance with the configured handlers.</returns>
77
- public static HttpClient CreateClient ( params DelegatingHandler [ ] handlers )
78
- {
79
- return Create ( null , handlers ) ;
80
- }
81
-
82
- /// <summary>
83
- /// Creates a new <see cref="HttpClient"/> instance configured with the handlers provided.
84
- /// </summary>
85
- /// <param name="innerHandler">The inner handler represents the destination of the HTTP message channel.</param>
86
- /// <param name="handlers">An ordered list of <see cref="DelegatingHandler"/> instances to be invoked as an
87
- /// <see cref="HttpRequestMessage"/> travels from the <see cref="HttpClient"/> to the network and an
88
- /// <see cref="HttpResponseMessage"/> travels from the network back to <see cref="HttpClient"/>.
89
- /// The handlers are invoked in a top-down fashion. That is, the first entry is invoked first for
90
- /// an outbound request message but last for an inbound response message.</param>
91
- /// <returns>An <see cref="HttpClient"/> instance with the configured handlers.</returns>
92
- public static HttpClient CreateClient ( HttpMessageHandler innerHandler , params DelegatingHandler [ ] handlers )
93
- {
94
- return Create ( innerHandler , handlers ) ;
95
- }
96
60
/// <summary>
97
- /// Creates a new <see cref="HttpClient"/> instance configured with the handlers provided.
61
+ /// Proxy to be used with created clients
98
62
/// </summary>
99
- /// <param name="sovereignCloud">The <see cref="string"/>value to pass the national cloud root endpoint to client.</param>
100
- /// <param name="handlers">An ordered list of <see cref="DelegatingHandler"/> instances to be invoked as an
101
- /// <see cref="HttpRequestMessage"/> travels from the <see cref="HttpClient"/> to the network and an
102
- /// <see cref="HttpResponseMessage"/> travels from the network back to <see cref="HttpClient"/>.
103
- /// The handlers are invoked in a top-down fashion. That is, the first entry is invoked first for
104
- /// an outbound request message but last for an inbound response message.</param>
105
- /// <returns>An <see cref="HttpClient"/> instance with the configured handlers.</returns>
106
- public static HttpClient CreateClient ( string sovereignCloud , params DelegatingHandler [ ] handlers )
107
- {
108
- if ( sovereignCloud == null )
109
- {
110
- throw new ArgumentNullException ( String . Format ( "{0} is null." , sovereignCloud , "sovereignCloud" ) ) ;
111
- }
112
- string cloud = "" ;
113
- if ( ! cloudList . TryGetValue ( sovereignCloud , out cloud ) )
114
- {
115
- throw new ArgumentException ( String . Format ( "{0} is an unexpected national cloud." , sovereignCloud , "sovereignCloud" ) ) ;
116
- }
117
- string cloudAddress = cloud + "/" + Version ;
118
- Uri address = new Uri ( cloudAddress ) ;
119
- HttpClient client = Create ( null , handlers ) ;
120
- client . BaseAddress = address ;
121
- return client ;
122
- }
63
+ public static IWebProxy Proxy { get ; set ; }
123
64
124
65
/// <summary>
125
- /// Creates a new <see cref="HttpClient"/> instance configured with the handlers, timeout, baseAddress,
126
- /// cacheControlHeaderValue and proxy provided.
66
+ /// DefaultHandler is a Func that returns the HttpMessageHandler for actually making the HTTP calls.
67
+ /// The default implementation returns a new instance of HttpClientHandler for each HttpClient.
127
68
/// </summary>
128
- /// <param name="proxy">A <see cref="IWebProxy"/> object to be passed to client to configure InnderHandler's proxy property.</param>
129
- /// <param name="handlers">An ordered list of <see cref="DelegatingHandler"/> instances to be invoked as an
130
- /// <see cref="HttpRequestMessage"/> travels from the <see cref="HttpClient"/> to the network and an
131
- /// <see cref="HttpResponseMessage"/> travels from the network back to <see cref="HttpClient"/>.
132
- /// The handlers are invoked in a top-down fashion. That is, the first entry is invoked first for
133
- /// an outbound request message but last for an inbound response message.</param>
134
- /// <returns>An <see cref="HttpClient"/> instance with the configured handlers.</returns>
135
- public static HttpClient CreateClient ( IWebProxy proxy = null , params DelegatingHandler [ ] handlers )
136
- {
137
- HttpClientHandler handler = new HttpClientHandler ( ) ;
138
- if ( proxy != null )
69
+ public static Func < HttpMessageHandler > DefaultHttpHandler = ( ) => {
70
+ return new HttpClientHandler
139
71
{
140
- handler . Proxy = proxy ;
141
- }
142
-
143
- return Create ( handler , handlers ) ;
144
-
145
- }
146
-
72
+ Proxy = Proxy
73
+ } ;
74
+ } ;
75
+
147
76
148
77
/// <summary>
149
78
/// Creates a new <see cref="HttpClient"/> instance configured with the handlers provided and with the
@@ -156,19 +85,49 @@ public static HttpClient CreateClient(IWebProxy proxy = null, params DelegatingH
156
85
/// The handlers are invoked in a top-down fashion. That is, the first entry is invoked first for
157
86
/// an outbound request message but last for an inbound response message.</param>
158
87
/// <returns>An <see cref="HttpClient"/> instance with the configured handlers.</returns>
159
- private static HttpClient Create ( HttpMessageHandler innerHandler , params DelegatingHandler [ ] handlers )
88
+ public static HttpClient Create ( string version = "v1.0" , string nationalCloud = Global_Cloud , IEnumerable < DelegatingHandler > handlers = null )
160
89
{
161
- HttpMessageHandler pipeline = CreatePipeline ( innerHandler , handlers ) ;
90
+ HttpMessageHandler pipeline ;
91
+ if ( handlers == null )
92
+ {
93
+ pipeline = CreatePipeline ( CreateDefaultHandlers ( ) , DefaultHttpHandler ( ) ) ;
94
+ } else
95
+ {
96
+ pipeline = CreatePipeline ( handlers , DefaultHttpHandler ( ) ) ;
97
+ }
98
+
162
99
HttpClient client = new HttpClient ( pipeline ) ;
163
100
client . DefaultRequestHeaders . Add ( SdkVersionHeaderName , SdkVersionHeaderValue ) ;
164
101
client . Timeout = defaultTimeout ;
165
- string address = _baseAddress + Version ;
166
- client . BaseAddress = new Uri ( address ) ;
102
+ client . BaseAddress = DetermineBaseAddress ( nationalCloud , version ) ;
167
103
client . DefaultRequestHeaders . CacheControl = new CacheControlHeaderValue { NoCache = true , NoStore = true } ;
168
104
return client ;
169
105
}
170
106
107
+ /// <summary>
108
+ /// Create a default set of middleware for calling Microsoft Graph
109
+ /// </summary>
110
+ /// <returns></returns>
111
+ public static IEnumerable < DelegatingHandler > CreateDefaultHandlers ( )
112
+ {
113
+ return new List < DelegatingHandler > {
114
+ new RetryHandler ( ) ,
115
+ new RedirectHandler ( )
116
+ } ;
117
+ }
118
+
119
+ private static Uri DetermineBaseAddress ( string nationalCloud , string version )
120
+ {
121
+ string cloud = "" ;
122
+ if ( ! cloudList . TryGetValue ( nationalCloud , out cloud ) )
123
+ {
124
+ throw new ArgumentException ( String . Format ( "{0} is an unexpected national cloud." , nationalCloud , "nationalCloud" ) ) ;
125
+ }
126
+ string cloudAddress = cloud + "/" + version ;
127
+ return new Uri ( cloudAddress ) ;
171
128
129
+ }
130
+
172
131
/// <summary>
173
132
/// Creates an instance of an <see cref="HttpMessageHandler"/> using the <see cref="DelegatingHandler"/> instances
174
133
/// provided by <paramref name="handlers"/>. The resulting pipeline can be used to manually create <see cref="HttpClient"/>
@@ -180,11 +139,11 @@ private static HttpClient Create(HttpMessageHandler innerHandler, params Delegat
180
139
/// The handlers are invoked in a top-down fashion. That is, the first entry is invoked first for
181
140
/// an outbound request message but last for an inbound response message.</param>
182
141
/// <returns>The HTTP message channel.</returns>
183
- public static HttpMessageHandler CreatePipeline ( HttpMessageHandler innerHandler , IEnumerable < DelegatingHandler > handlers )
142
+ public static HttpMessageHandler CreatePipeline ( IEnumerable < DelegatingHandler > handlers , HttpMessageHandler innerHandler = null )
184
143
{
185
144
if ( innerHandler == null )
186
145
{
187
- innerHandler = new HttpClientHandler ( ) ;
146
+ innerHandler = DefaultHttpHandler ( ) ;
188
147
}
189
148
190
149
if ( handlers == null )
@@ -214,35 +173,36 @@ public static HttpMessageHandler CreatePipeline(HttpMessageHandler innerHandler,
214
173
}
215
174
216
175
217
- /// <summary>
218
- /// Configure an instance of an <see cref="HttpClient"/>
219
- /// </summary>
220
- /// <param name="client">The <see cref="HttpClient"/> client instance need to be configured.</param>
221
- /// <param name="timeout">A <see cref="TimeSpan"/> value for the HTTP client timeout property.</param>
222
- /// <param name="baseAddress">A <see cref="Uri"/> value to set the HTTP client BaseAddress property.</param>
223
- /// <param name="cacheControlHeaderValue">A <see cref="CacheControlHeaderValue"/> value to set HTTP client DefaultRequestHeaders property.</param>
224
- /// <returns></returns>
225
- public static HttpClient Configure ( HttpClient client , TimeSpan timeout , Uri baseAddress , CacheControlHeaderValue cacheControlHeaderValue )
226
- {
227
- try
228
- {
229
- client . Timeout = timeout ;
230
- }
231
- catch ( InvalidOperationException exception )
232
- {
233
- throw new ServiceException (
234
- new Error
235
- {
236
- Code = ErrorConstants . Codes . NotAllowed ,
237
- Message = ErrorConstants . Messages . OverallTimeoutCannotBeSet ,
238
- } ,
239
- exception ) ;
240
- }
241
176
242
- client . BaseAddress = baseAddress == null ? new Uri ( _baseAddress + Version ) : baseAddress ;
243
- client . DefaultRequestHeaders . CacheControl = cacheControlHeaderValue ?? new CacheControlHeaderValue { NoCache = true , NoStore = true } ;
244
- return client ;
245
- }
177
+ ///// <summary>
178
+ ///// Configure an instance of an <see cref="HttpClient"/>
179
+ ///// </summary>
180
+ ///// <param name="client">The <see cref="HttpClient"/> client instance need to be configured.</param>
181
+ ///// <param name="timeout">A <see cref="TimeSpan"/> value for the HTTP client timeout property.</param>
182
+ ///// <param name="baseAddress">A <see cref="Uri"/> value to set the HTTP client BaseAddress property.</param>
183
+ ///// <param name="cacheControlHeaderValue">A <see cref="CacheControlHeaderValue"/> value to set HTTP client DefaultRequestHeaders property.</param>
184
+ ///// <returns></returns>
185
+ //public static HttpClient Configure(HttpClient client, TimeSpan timeout, Uri baseAddress, CacheControlHeaderValue cacheControlHeaderValue)
186
+ //{
187
+ // try
188
+ // {
189
+ // client.Timeout = timeout;
190
+ // }
191
+ // catch (InvalidOperationException exception)
192
+ // {
193
+ // throw new ServiceException(
194
+ // new Error
195
+ // {
196
+ // Code = ErrorConstants.Codes.NotAllowed,
197
+ // Message = ErrorConstants.Messages.OverallTimeoutCannotBeSet,
198
+ // },
199
+ // exception);
200
+ // }
201
+
202
+ // client.BaseAddress = baseAddress == null ? new Uri(_baseAddress + Version) : baseAddress;
203
+ // client.DefaultRequestHeaders.CacheControl = cacheControlHeaderValue ?? new CacheControlHeaderValue { NoCache = true, NoStore = true };
204
+ // return client;
205
+ //}
246
206
247
207
}
248
208
}
0 commit comments