<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9" -->

---
title: Tricked by WebRequest | daily.dev
description: A Datadog .NET tracer engineer recounts switching their HTTP transport layer from HttpClient to HttpWebRequest due to .NET Framework instrumentation conflicts,...
canonical: https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Tricked by WebRequest | daily.dev
og:description: A Datadog .NET tracer engineer recounts switching their HTTP transport layer from HttpClient to HttpWebRequest due to .NET Framework instrumentation conflicts,...
og:url: https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9
og:image: https://api.daily.dev/og/posts/ZG7xXMKt9.png
og:image:alt: Tricked by WebRequest
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Tricked by WebRequest

**[Kevin Gosse \(minidump.net\)](https://daily.dev/sources/minidump)** · 4 min read · 0 upvotes · 0 comments

## Summary

A Datadog .NET tracer engineer recounts switching their HTTP transport layer from HttpClient to HttpWebRequest due to .NET Framework instrumentation conflicts, and the surprising bug that followed: WebRequest.Create can return a custom type if a consumer globally registers a factory via WebRequest.RegisterPrefix, breaking code that casts the result to HttpWebRequest. The fix was switching to WebRequest.CreateHttp, which guarantees an HttpWebRequest instance regardless of registered prefixes. The piece also covers the challenge of unit testing this behavior, since WebRequest has no supported way to unregister a custom prefix factory, requiring reflection to manipulate the internal PrefixList property to reset state between tests.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://minidump.net/c-tricked-by-webrequest-209014d99653>

## Questions this post answers

### Why does casting the result of WebRequest.Create to HttpWebRequest throw an InvalidCastException?

It happens when something in the process has called WebRequest.RegisterPrefix to globally override the factory used for a URL prefix like "http://". Once registered, WebRequest.Create returns an instance of the custom registered type instead of HttpWebRequest, so a direct cast to HttpWebRequest fails with InvalidCastException.

_Developers hardening HTTP code against this cast failure can track .NET gotchas like this on daily.dev._

### How do I guarantee WebRequest.Create returns an HttpWebRequest even if a custom prefix factory is registered?

Use WebRequest.CreateHttp instead of casting the result of WebRequest.Create. Unlike WebRequest.Create, which can be hijacked by a factory registered through WebRequest.RegisterPrefix for a given URL prefix, WebRequest.CreateHttp always returns an actual HttpWebRequest instance regardless of any overridden factory.

_Teams debugging HttpWebRequest casting issues can follow practical .NET fixes like this on daily.dev._

### How can I unregister a custom WebRequest prefix factory after a unit test in .NET?

There is no supported public API to unregister a prefix; the UnregisterPrefix method exists in the .NET Framework source but is commented out. A workaround is using reflection to read and store the private static WebRequest.PrefixList property before registering a custom factory, then restoring the saved value afterward to reset global state between tests.

_Developers writing isolated unit tests around global static state can find workarounds like this on daily.dev._

## Similar posts on daily.dev

- [OpenTelemetry HttpClient Instrumentation in .NET: Tracing Outbound HTTP Calls](https://daily.dev/posts/opentelemetry-httpclient-instrumentation-in-net-tracing-outbound-http-calls-t7uo304xd) · We Are .NET · 1 upvotes · 0 comments
- [Capturing HTTP Request and Response Bodies in .NET Traces with PHI Redaction](https://daily.dev/posts/capturing-http-request-and-response-bodies-in-net-traces-with-phi-redaction-anqr488g5) · Last9 · 6 upvotes · 1 comments
- [Understanding the worst .NET vulnerability ever: request smuggling and CVE-2025-55315](https://daily.dev/posts/understanding-the-worst-net-vulnerability-ever-request-smuggling-and-cve-2025-55315-qljqff7f0) · .NET Escapades · 8 upvotes · 0 comments

---

Tags: [#testing](https://daily.dev/tags/testing), [#.net](https://daily.dev/tags/.net)

[View this post on daily.dev](https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Tricked by WebRequest","url":"https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9"},"datePublished":"2026-10-04T13:06:53.799Z","dateModified":"2026-10-04T13:13:21.130Z","description":"A Datadog .NET tracer engineer recounts switching their HTTP transport layer from HttpClient to HttpWebRequest due to .NET Framework instrumentation conflicts,...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/c4657bdd67cc34bd70a973c45ca51f78?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/c4657bdd67cc34bd70a973c45ca51f78?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Kevin Gosse (minidump.net)","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Kevin Gosse (minidump.net)","logo":"https://media.daily.dev/image/upload/s--8KHn1aFB--/f_auto,q_auto/v1791119046/logos/minidump?_a=BAMAMicg0","url":"https://daily.dev/sources/minidump"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"testing,.net","timeRequired":"PT4M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Kevin Gosse (minidump.net)","item":"https://daily.dev/sources/minidump"},{"@type":"ListItem","position":3,"name":"Tricked by WebRequest"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/tricked-by-webrequest-zg7xxmkt9#faq","mainEntity":[{"@type":"Question","name":"Why does casting the result of WebRequest.Create to HttpWebRequest throw an InvalidCastException?","acceptedAnswer":{"@type":"Answer","text":"It happens when something in the process has called WebRequest.RegisterPrefix to globally override the factory used for a URL prefix like \"http://\". Once registered, WebRequest.Create returns an instance of the custom registered type instead of HttpWebRequest, so a direct cast to HttpWebRequest fails with InvalidCastException. Developers hardening HTTP code against this cast failure can track .NET gotchas like this on daily.dev."}},{"@type":"Question","name":"How do I guarantee WebRequest.Create returns an HttpWebRequest even if a custom prefix factory is registered?","acceptedAnswer":{"@type":"Answer","text":"Use WebRequest.CreateHttp instead of casting the result of WebRequest.Create. Unlike WebRequest.Create, which can be hijacked by a factory registered through WebRequest.RegisterPrefix for a given URL prefix, WebRequest.CreateHttp always returns an actual HttpWebRequest instance regardless of any overridden factory. Teams debugging HttpWebRequest casting issues can follow practical .NET fixes like this on daily.dev."}},{"@type":"Question","name":"How can I unregister a custom WebRequest prefix factory after a unit test in .NET?","acceptedAnswer":{"@type":"Answer","text":"There is no supported public API to unregister a prefix; the UnregisterPrefix method exists in the .NET Framework source but is commented out. A workaround is using reflection to read and store the private static WebRequest.PrefixList property before registering a custom factory, then restoring the saved value afterward to reset global state between tests. Developers writing isolated unit tests around global static state can find workarounds like this on daily.dev."}}]}
```

