ASP.NET

ASP.NET Core Web API with SQL Server & Image Upload

ASP.NET Core MVC REST API with SQL Server, Entity Framework & Image Upload

In this updated tutorial, we’ll build a complete REST API using ASP.NET Core MVC with SQL Server and Entity Framework Core, including image upload functionality. The model uses lowercase fields: first_name, last_name, email, and password to ensure compatibility with Angular JSON structure.

🧰 Step 1: Create ASP.NET Core Web API Project

dotnet new webapi -n DotNetRestApi

πŸ“ Recommended Project Structure

DotNetRestApi/
β”œβ”€β”€ Controllers/
β”‚   └── UsersController.cs
β”œβ”€β”€ Models/
β”‚   └── User.cs
        UserDto.cs
β”œβ”€β”€ Data/
β”‚   └── ApplicationDbContext.cs
β”œβ”€β”€ wwwroot/
β”‚   └── uploads/
β”œβ”€β”€ appsettings.json
β”œβ”€β”€ Program.cs
└── ...

πŸ“¦ Step 2: Install EF Core Packages

dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools

🧾 Step 3: Create User Model

namespace DotNetRestApi.Models;

public class User
{
    public int Id { get; set; }
    public string first_name { get; set; }
    public string last_name { get; set; }
    public string email { get; set; }
    public string password { get; set; }
    public string? image_url { get; set; }
}

🧾 Step 3: Create User DTO



namespace DotNetRestApi.Models;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace DotNetRestApi.Models
{
    public class UserDto
    {
     [FromForm(Name = "first_name")]
        public string FirstName { get; set; }

        [FromForm(Name = "last_name")]
        public string LastName { get; set; }

        [FromForm(Name = "email")]
        public string Email { get; set; }

        [FromForm(Name = "password")]
        public string Password { get; set; }

        [FromForm(Name = "image")]
        public IFormFile Image { get; set; }
    }
}

πŸ—ƒοΈ Step 4: Create Database Context



using Microsoft.EntityFrameworkCore;        // For DbContext, DbSet
using DotNetRestApi.Models;                 // For User model

namespace DotNetRestApi.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions options)
            : base(options)
        {
        }

        public DbSet Users { get; set; }
    }
}



βš™οΈ Step 5: Add Connection String



{
  "ConnectionStrings": {
  "DefaultConnection": "Server=localhost;Database=RestApi;Trusted_Connection=True;TrustServerCertificate=True;"
}
,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}


βš™οΈ Update Program.cs



using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using DotNetRestApi.Data;
using System.Text.Json;


var builder = WebApplication.CreateBuilder(args);

// Services
builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver
        {
            NamingStrategy = new Newtonsoft.Json.Serialization.SnakeCaseNamingStrategy()
        };
    });
builder.Services.AddEndpointsApiExplorer(); // For Swagger
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "DotNetRestApi", Version = "v1" });
});

builder.Services.AddDbContext(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

var app = builder.Build();

// Middleware
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "DotNetRestApi v1");
    });
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();


// Your custom snake_case naming policy:
public class SnakeCaseNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name)
    {
        if (string.IsNullOrEmpty(name))
            return name;

        var stringBuilder = new System.Text.StringBuilder();
        for (int i = 0; i < name.Length; i++) { var c = name[i]; if (char.IsUpper(c)) { if (i > 0)
                    stringBuilder.Append('_');
                stringBuilder.Append(char.ToLower(c));
            }
            else
            {
                stringBuilder.Append(c);
            }
        }
        return stringBuilder.ToString();
    }
}





🧾 Step 6: Create UsersController.cs



using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using DotNetRestApi.Data;
using DotNetRestApi.Models;

namespace DotNetRestApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class UsersController : ControllerBase
    {
        private readonly ApplicationDbContext _context;

        public UsersController(ApplicationDbContext context)
        {
            _context = context;
        }

        // GET: api/Users
        [HttpGet]
        public async Task<ActionResult<IEnumerable>> GetUsers()
        {
            return await _context.Users.ToListAsync();
        }

        // GET: api/Users/5
        [HttpGet("{id}")]
        public async Task<ActionResult> GetUser(int id)
        {
            var user = await _context.Users.FindAsync(id);
            if (user == null) return NotFound();
            return user;
        }

        // POST: api/Users
        [HttpPost]
        public async Task<ActionResult> CreateUser([FromForm] UserDto userDto)
        {
            string? imagePath = await SaveImage(userDto.Image);

            var user = new Users
            {
                FirstName = userDto.FirstName,
                LastName = userDto.LastName,
                Email = userDto.Email,
                Password = userDto.Password,
                ImageUrl = imagePath // store image path in DB
            };

            _context.Users.Add(user);
            await _context.SaveChangesAsync();

            return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
        }

        // PUT: api/Users/5
        [HttpPut("{id}")]
        public async Task UpdateUser(int id, Users user)
        {
            if (id != user.Id)
                return BadRequest();

            _context.Entry(user).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!_context.Users.Any(u => u.Id == id))
                    return NotFound();
                else
                    throw;
            }

            return NoContent();
        }

        // DELETE: api/Users/5
        [HttpDelete("{id}")]
        public async Task DeleteUser(int id)
        {
            var user = await _context.Users.FindAsync(id);
            if (user == null) return NotFound();

            _context.Users.Remove(user);
            await _context.SaveChangesAsync();

            return NoContent();
        }

        // Save uploaded image and return the public path
        private async Task<string?> SaveImage(IFormFile image)
        {
            if (image == null || image.Length == 0)
                return null;

            var uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads");
            if (!Directory.Exists(uploadsFolder))
                Directory.CreateDirectory(uploadsFolder);

            var uniqueFileName = Guid.NewGuid().ToString() + Path.GetExtension(image.FileName);
            var filePath = Path.Combine(uploadsFolder, uniqueFileName);

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

            return "/uploads/" + uniqueFileName;
        }
    }
}


🧱 Step 7: Run Migrations

dotnet tool install --global dotnet-ef
dotnet ef migrations add InitialCreate
dotnet ef database update

πŸ“‘ Step 8: Test API

  • GET /api/users – All users
  • GET /api/users/{id} – Single user
  • POST /api/users – Create with image
  • PUT /api/users/{id} – Update with optional image
  • DELETE /api/users/{id} – Delete

βœ… Frontend Form (Angular or Postman)

Send as multipart/form-data with:

  • first_name
  • last_name
  • email
  • password
  • image (optional)

🎯 Done!

You now have a complete ASP.NET Core Web API with SQL Server, Entity Framework, and image upload supportβ€”ready to connect with Angular or React!

Leave a Reply

Your email address will not be published. Required fields are marked *