DEVKIT1009 - phuocle/Dynamics-Crm-DevKit GitHub Wiki
This analyzer warns when using HttpClient or WebRequest in plugins without setting KeepAlive to false. The sandbox environment has connection pool limitations that can cause issues when KeepAlive is enabled.
📚 Set KeepAlive to false when interacting with external hosts in a plug-in
When you interact with an external host from a plug-in, the KeepAlive property on the underlying connection must be set to false. Failure to set this property can cause intermittent connection failures.
Using KeepAlive (default behavior) in plugins causes:
- Connection Pool Issues: The sandbox environment has limited connection pooling capabilities
- Intermittent Failures: Connections may be dropped unexpectedly, causing sporadic errors
- Resource Leaks: Kept-alive connections may not be properly cleaned up
- Timeout Errors: Stale connections in the pool can cause unexpected timeouts
| Pattern | Issue |
|---|---|
new HttpClient() |
KeepAlive is true by default |
new WebRequest() |
KeepAlive is true by default |
WebRequest.Create() |
Returns request with KeepAlive = true |
The analyzer flags instantiation of HTTP client types within:
- Classes implementing
Microsoft.Xrm.Sdk.IPlugin - Classes inheriting from
System.Activities.CodeActivity
public class MyPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// ❌ HttpClient with default KeepAlive (true)
using (var client = new HttpClient())
{
var response = client.GetAsync("https://api.example.com").GetAwaiter().GetResult();
}
// ❌ WebRequest with default KeepAlive (true)
var request = WebRequest.Create("https://api.example.com");
var response = request.GetResponse();
}
}public class MyPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// ✅ HttpClient with ConnectionClose = true (KeepAlive = false)
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.ConnectionClose = true;
var response = client.GetAsync("https://api.example.com").GetAwaiter().GetResult();
}
// ✅ WebRequest with KeepAlive = false
var request = (HttpWebRequest)WebRequest.Create("https://api.example.com");
request.KeepAlive = false;
var response = request.GetResponse();
}
}-
For HttpClient: Set
DefaultRequestHeaders.ConnectionClose = trueafter creating the client -
For WebRequest/HttpWebRequest: Set
KeepAlive = falseon the request object - Always use using statements: Ensure proper disposal of HTTP clients
using (var client = new HttpClient())
{
+ client.DefaultRequestHeaders.ConnectionClose = true;
var response = client.GetAsync(url).GetAwaiter().GetResult();
} var request = (HttpWebRequest)WebRequest.Create(url);
+ request.KeepAlive = false;
var response = request.GetResponse();If you have a legitimate need to suppress this warning:
#pragma warning disable DEVKIT1009
using (var client = new HttpClient())
{
// Custom handling
}
#pragma warning restore DEVKIT1009Or in .editorconfig:
[*.cs]
dotnet_diagnostic.DEVKIT1009.severity = suggestion| Property | Value |
|---|---|
| Rule ID | DEVKIT1009 |
| Category | DynamicsCrm.DevKit |
| Severity | Warning |
| Enabled by default | Yes |