How to Upload Images Using ASP.NET Web API

Sudip BhandariSudip Bhandari
2 min read

Step 1: Create a CreateProductDto

First, create a DTO (Data Transfer Object) that represents the product data along with the images:

public class CreateProductDto
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string? Description { get; set; }
    public int CategoryId { get; set; }
    public List<IFormFile> Images { get; set; }
}

Here, IFormFile is used to receive uploaded files via HTTP multipart form-data.

Step 2: Create the CreateProduct API Endpoint

Now, create a POST API method to handle incoming product data and image uploads:

[HttpPost]
public async Task<ActionResult<ProductDto>> CreateProduct([FromForm] CreateProductDto createDto)
{
    var uploadedImageUrls = new List<string>();

    if (createDto.Images != null && createDto.Images.Any())
    {
        var uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads/products");

        if (!Directory.Exists(uploadsFolder))
        {
            Directory.CreateDirectory(uploadsFolder);
        }

        foreach (var image in createDto.Images)
        {
            var extension = Path.GetExtension(image.FileName);
            var newFileName = $"{Guid.NewGuid()}{extension}";
            var filePath = Path.Combine(uploadsFolder, newFileName);

            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await image.CopyToAsync(stream);
            }

            // Store relative URL for frontend usage
            uploadedImageUrls.Add($"/uploads/products/{newFileName}");
        }
    }

    var product = new Product
    {
        Name = createDto.Name,
        Price = createDto.Price,
        Description = createDto.Description,
        CategoryId = createDto.CategoryId,
        Images = uploadedImageUrls.Select(url => new ProductImage
        {
            ImageUrl = url
        }).ToList()
    };

    _context.Products.Add(product);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

How It Works:

  • [FromForm] binding is used because files must be posted as form-data, not JSON.

  • The API saves each uploaded image to wwwroot/uploads/products.

  • A new filename is generated using Guid.NewGuid() to avoid name collisions.

  • The server stores the relative URL (like /uploads/products/xyz.jpg) for each image.

  • All product details (including images) are finally saved into the database.

Important Tips

  • Create wwwroot/uploads/products folder manually or ensure it's auto-created in code (we handle it above).

  • Configure Startup.cs / Program.cs (depending on your .NET version) to serve static files:

      app.UseStaticFiles();
    
  • Limit the allowed file types (e.g., only .jpg, .png) and size if needed for security.

  • Handle errors gracefully (e.g., invalid files, large uploads).

0
Subscribe to my newsletter

Read articles from Sudip Bhandari directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sudip Bhandari
Sudip Bhandari