Obtain BLOB Data from a Web API Controller Endpoint
- 3 minutes to read
This topic demonstrates how you can use HTTP requests to download BLOB data (file attachments) available in your data model.
The application must use XPO or EF Core to enable such requests. You can access BLOB data stored in the objects that are part of your data model.
The endpoint can work with BLOB data stored in the following formats:
byte[]
System.Drawing.Image
- IFileData
- MediaDataObject (EF Core) / MediaDataObject (XPO)
Media File Controller Availability
The API described in this article is available in a specially designed MVC Controller - MediaFileController
. This controller is available to you regardless of how you added DevExpress Web API Service to your application. No additional option selection or customization is necessary.
Media File Controller API
The MediaFileController
class includes the following method:
[HttpGet(nameof(DownloadStream))]
public IActionResult DownloadStream(
string objectType, string objectKey, string propertyName) {
//...
}
Corresponding Web API Endpoint:
/api/MediaFile/DownloadStream?objectType=...&objectKey=...&propertyName=...
Parameters allow you to identify the object type, individual object/record, and the property that contains BLOB data:
Parameter | Description |
---|---|
objectType |
The business object type name. Use short or full format: “Employee” or “MainDemo.Module.BusinessObjects.Employee”. |
objectKey |
The value that identifies an object/record by its primary key value. |
propertyName |
The name of the property that contains BLOB data. |
Basic Usage Example
This example demonstrates how to obtain an image from a business object.
HttpClient httpClient = new HttpClient();
// Set up client Uri.
httpClient.BaseAddress = new Uri("https://localhost:5001/");
string objectTypeName = typeof(ApplicationUser).Name;
string objectKey = "C4890105-CF95-4DFA-8083-08DACE0F086B";
string propertyName = nameof(ApplicationUser.Photo);
// Send request for a photo.
string url = "/api/MediaFile/DownloadStream" +
$"?objectType={objectTypeName}" +
$"&objectKey={objectKey}" +
$"&propertyName={propertyName}";
var response = await httpClient.GetAsync(url);
// Parse the result from HttpResponseMessage.
var photo = await response.Content.ReadAsStringAsync();
Video Tutorial: Query Image Data from a MAUI Application
The following video shows how you can query media data from the secure data service and use that data for a Photo editor in your MAUI application.
Media File Controller Customization
The MediaFileController
class is marked with an Authorize attribute. You can only use the controller with active authorization. If you need to create an unprotected endpoint, derive your own controller from the ancestor class: MediaFilesControllerBase
.
MediaFileController
uses the following service to obtain data: IStreamService
. Use this service to modify controller implementation (obtain data in a custom manner). The complete service type name is as follows:
DevExpress.ExpressApp.AspNetCore.Streaming.IStreamService
Add Unit Tests for MediaFile Controller
Follow the steps below to add unit tests to your application. This example adds tests for code that queries BLOB data (uses MediaFileController
).
- If your solution does not include a testing project, add a new xUnit test project.
- Add a reference to the
{SolutionName}.Blazor.Server
project. - Add the
Microsoft.AspNetCore.Mvc.Testing
package reference. - Add the following test to the test project.
using System.Net.Http.Headers;
using System.Text;
using MySolution.Module.BusinessObjects;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
namespace MySolution.WebAPI.Tests {
public class MediaFileTests : IClassFixture<WebApplicationFactory<MySolution.Blazor.Server.Startup>> {
HttpClient httpClient;
public MediaFileTests(WebApplicationFactory<MySolution.Blazor.Server.Startup> webApplicationFactory) {
httpClient = webApplicationFactory.CreateClient();
}
[Fact]
public async System.Threading.Tasks.Task LoadApplicationUserPhotoTest() {
string tokenString = await GetUserTokenAsync("Admin", "", "/api/Authentication/Authenticate");
var authorizationToken = new AuthenticationHeaderValue("Bearer", tokenString);
string userKey = //"objectKey";
string url = $"/api/MediaFile/DownloadStream?objectType={typeof(ApplicationUser).Name}&objectKey={userKey}&propertyName={nameof(ApplicationUser.Photo)}";
var httpRequest = new HttpRequestMessage(HttpMethod.Get, url);
httpRequest.Headers.Authorization = authorizationToken;
var response = await httpClient.SendAsync(httpRequest);
var data = await response.Content.ReadAsStringAsync();
Assert.True(data.Length > 200);
}
async Task<string> GetUserTokenAsync(string userName, string password, string requestPath) {
var request = new HttpRequestMessage(HttpMethod.Post, requestPath);
request.Content = new StringContent(
$"{{ \"userName\": \"{userName}\", \"password\": \"{password}\" }}", Encoding.UTF8, "application/json");
var httpResponse = await httpClient.SendAsync(request);
if(!httpResponse.IsSuccessStatusCode) {
throw new UnauthorizedAccessException($"Authorization request failed! Code {(int)httpResponse.StatusCode}, '{httpResponse.ReasonPhrase}'");
}
var tokenString = await httpResponse.Content.ReadAsStringAsync();
return tokenString;
}
}
}