Parallel request handling in .NET Framework v.4.7.2 and .NET 8 Issue ?

Kirankumar Bharsadiya 40 Reputation points
2024-09-12T12:50:30.16+00:00

Following is the controller method for uploading product images. We are using Dropzone jquery for uploading products

from client side. It sends 2 parallel requests to server at once if uploaded multiple images simultaneously.

In .NET Framework

public async Task<ActionResult> UploadProductImage(string productId)
{
    try
    {
        Product product = await _productService.FindById(productId, SelectedStoreView);
        if (product == null)
        {
            return Failure($"Product with Id {productId} does not exist");
        }
        Debug.WriteLine($"PRODUCT ETAG WHILE READING AT {DateTime.Now:O} : {product.ETag}");
        int totalUploaded = 0;
        foreach (string fileFromRequest in Request.Files)
        {
            HttpPostedFileBase file = Request.Files[fileFromRequest];
            if (file == null || file.ContentLength <= 0) continue;
            byte[] fileContent;
            using (var reader = new BinaryReader(file.InputStream))
            {
                fileContent = reader.ReadBytes(file.ContentLength);
            }
			//Uploading product to blob storage
            var image = await _productService.UploadProductImage(product, ApplicationSettings, file.FileName, Request.ContentType, fileContent, null, SelectedStoreViewCode);
            if (product.Images.Exists(e => e.Url == image.Url)) continue;
			//adding uploaded image to product object with url
            product.Images.Add(image);
            if (product.Images.Count > 0)
            {
                await ProcessImageAttributeValues(product);
            }
			//saving product to cosmos db
            var updatedProduct = await _productService.UpsertAsync(product);
			Debug.WriteLine($"PRODUCT ETAG AFTER UPDATE AT {DateTime.Now:O} : {updatedProduct.ETag}");
            totalUploaded += 1;
        }
        return Success($"{totalUploaded}");
    }
    catch (Exception ex)
    {
        return Exception(ex);
    }
}

In .NET 8

public async Task<IActionResult> UploadProductImage(string productId)
{
    try
    {
        Product product = await _productService.FindById(productId, SelectedStoreView);
        Debug.WriteLine($"PRODUCT ETAG WHILE READING AT {DateTime.Now:O} : {product.ETag}");
        if (product == null)
        {
            return Failure($"Product with Id {productId} does not exist");
        }
        int totalUploaded = 0;
        foreach (string fileFromRequest in Request.Form.Files.Select(x => x.Name))
        {
            var file = Request.Form.Files[fileFromRequest];
            if (file == null || file.Length <= 0) continue;
            byte[] fileContent;
            using (var mstream = new MemoryStream())
            {
                file.OpenReadStream().CopyTo(mstream);
                fileContent = mstream.ToArray();
            }
            var image = await _productService.UploadProductImage(product, ApplicationSettings, file.FileName, Request.ContentType, fileContent, null, SelectedStoreViewCode);
            if (product.Images.Exists(e => e.Url == image.Url)) continue;
            image.Position = product.Images.Count + 1;
            product.Images.Add(image);
            var updatedProduct = await _productService.UpsertAsync(product);
			Debug.WriteLine($"PRODUCT ETAG AFTER UPDATE AT {DateTime.Now:O} : {updatedProduct.ETag}");
            totalUploaded += 1;
        }
        return Success($"{totalUploaded}");
    }
    catch (Exception ex)
    {
        return Exception(ex);
    }
}

Following are the logs from the .NET Framework application when dropped two images simultaneously.

PRODUCT ETAG WHILE READING AT 2024-09-12T15:07:56.5250628+05:30 : "00000000-0000-0000-0377-85cf51a901db"

PRODUCT ETAG AFTER UPDATE AT 2024-09-12T15:07:58.7006044+05:30 : "00000000-0000-0000-04f7-73faf3de01db"

PRODUCT ETAG WHILE READING AT 2024-09-12T15:07:59.0344485+05:30 : "00000000-0000-0000-04f7-73faf3de01db"

PRODUCT ETAG AFTER UPDATE AT 2024-09-12T15:08:00.7209253+05:30 : "00000000-0000-0000-04f7-752eee6a01db"

Following are the logs from the .NET Framework application when dropped two images simultaneously.

PRODUCT ETAG WHILE READING AT 2024-09-12T15:11:48.9364483+05:30 : "00000000-0000-0000-0371-aaa244bf01db"

PRODUCT ETAG WHILE READING AT 2024-09-12T15:11:48.9364480+05:30 : "00000000-0000-0000-0371-aaa244bf01db"

PRODUCT ETAG AFTER UPDATE AT 2024-09-12T15:12:00.8437338+05:30 : "00000000-0000-0000-04f8-043f320d01db"

PRODUCT ETAG AFTER UPDATE AT 2024-09-12T15:12:00.9038454+05:30 : "00000000-0000-0000-04f8-044da3eb01db"

Both the application are hosted on azure app service.

Here the functionality is working properly in .NET Framework, we can see the logs and ETags, though the request to server are concurrently but executes in a proper manner so there is no issue of overwriting data. But in .NET 8, we can see the logs here both the request reads the same objects and later one request overwrites the data updated by the another request. I can't find why the behavior has been changes in .NET 8 from .NET Framework.

Code is same in both but what causes this issue I can't understand ? Why the behavior in .NET Framework is sequential for simultaneous requests ?

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,802 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,523 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,457 questions
Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
7,676 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.