Range requests enable you to retrieve partial content in lieu of the entire content for improved performance when working with WebAPI over HTTP. HTTP 1.1 provides support for range headers – it allows you to specify range headers to enable the client to retrieve partial response. This can be used to retrieve partial content when working over HTTP. It’s a technique that’s widely used when streaming video files, for instance. With this approach, rather than retrieving the entire data at one go, your application can retrieve the data partially, in chunks. This feature can be particularly helpful in scenarios when the client needs to recover the data from interrupted connections that might occur due to cancelled requests, or connections to the server that have been dropped. The HTTP 206 Partial Content status code and its associated headers enable the clients or the web browsers to retrieve partial content in lieu of the complete content when a request is sent. Note that most modern-day web servers provide support for range requests. The ByteRangeStreamContent class that has been added to WebAPI makes it easier to work with range requests. The ByteRangeStreamContent class works similarly to how, let’s say, StreamContent works – with the exception that it can provide a view over a stream that is seekable. Note that a MemoryStream or a FileStream is seekable, i.e., they can be used to do ranges over them. Let’s now implement a simple WebAPI with support for HTTP Range Header using the ByteRangeStreamContent class. Here’s a quick glance at how this all would work. The client connects to the server and requests for partial content by specifying the values in the Range header. The server responds by sending partial content if range is available with the status code as HTTP 206. If the requested range is not available, the server responds with HTTP 416. And, now the implementation. The following code snippet illustrates a WebAPI controller method with support for range headers. For the sake of simplicity I have hard-coded a string as data that would be retrieved as partial response by the client. You can change this implementation to work with data of much larger sizes, like files, large arrays, lists, etc. public HttpResponseMessage GetData () { try { MemoryStream memoryStream = new MemoryStream(data); if (Request.Headers.Range != null) { HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.PartialContent); response.Content = new ByteRangeStreamContent(memoryStream, Request.Headers.Range, MediaTypeHeaderValue.Parse(“application/json”)); return response; } else { HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StreamContent(memoryStream); response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(“application/json”); return response; } } catch (Exception ex) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex); } } Refer to the GetData method shown above. Please note that you should mention the appropriate media type specific to your needs. The GetData method checks if a request for partial content was made and depending on whether partial content was requested for, the content is generated and sent back as response. To be more precise, if the request is a range request, we create a ByteRangeStreamContentRequest and return it as part of the response. If the request is not a range request, an instance of StreamContent is created and returned as part of the response. Note that the response to a byte range request is HTTP 206 (Partial Content). If no range was requested, an HTTP status code of 200 (OK) is sent back as response. Note how the ByteRangeStreamContent class has been used to build the partial response. The constructor of this class accepts three arguments, i.e., the memory stream instance, the range and the media type. Here’s how the controller looks like. As I mentioned earlier, I’ve used a hardcoded string as data here for demonstration purposes only. public class DefaultController : ApiController { private static readonly byte[] data = Encoding.ASCII.GetBytes(“This is a test string to demonstrate range requests”); public HttpResponseMessage GetData() { //The complete source code of the GetData method is given earlier. } } The following code snippet illustrates how we can call the GetData method using HttpClient. using (var httpclient = new HttpClient()) { httpclient.DefaultRequestHeaders.Range = new RangeHeaderValue(0, 5); var response = await httpclient.GetAsync(url, HttpCompletionOption.ResponseContentRead); using (var stream = await response.Content.ReadAsStreamAsync()) { var data = new byte[5]; int count = stream.Read(data, 0, data.Length); MemoryStream memoryStream = new MemoryStream(data); StreamReader reader = new StreamReader(memoryStream); string text = reader.ReadToEnd(); } } And, that’s it! When the above piece of code is executed, the string variable “text” would contain the first 5 characters of the entire response. Related content how-to How to use FastEndpoints in ASP.NET Core Take advantage of the free open-source FastEndpoints library to build fast and lean APIs in your ASP.NET Core applications. By Joydip Kanjilal Jul 11, 2024 7 mins Microsoft .NET C# Development Libraries and Frameworks how-to How to use Refit to consume APIs in ASP.NET Core Take advantage of Refit REST library to simplify API consumption and make your code cleaner, more efficient, and easier to maintain. By Joydip Kanjilal Jul 04, 2024 10 mins C# Microsoft .NET Software Deployment how-to When to use an abstract class vs. interface in C# Understanding the differences between an abstract class and interface is key to designing loosely coupled and extensible applications. By Joydip Kanjilal Jun 20, 2024 10 mins Small and Medium Business Microsoft .NET C# how-to 6 security best practices for ASP.NET Core Learn the best practices and built-in safeguards for preventing attacks and protecting sensitive data in your ASP.NET Core web applications. By Joydip Kanjilal Jun 07, 2024 6 mins C# Microsoft .NET Web Development Resources Videos