C# - .NET Web Application

.NET Web Application - C#


This is a program written in C# using the .NET framework to implement a web application for a real estate market management system. The user can interact with the website to alter or input additional saved data.

The .NET web app is a client management system with functionalities related to brokerages and advertisements. The Clients/Index page allows users to view a list of clients and select individual clients to see their subscribed brokerages. The Clients/EditSubscriptions page enables users to register or unregister clients to brokerages, with separate controller actions for adding and removing subscriptions. The Brokerages/Index page lists brokerages and requires the addition of a "Ads" link that directs users to a page displaying the brokerage's ads. The Advertisements/Index/{id} page shows ads specific to a brokerage, allowing users to delete individual ads and providing a verification step through Advertisements/Delete/{ad id}. Deleting a brokerage is allowed only when all its ads are deleted. Lastly, the Advertisements/Create/{id} page enables users to upload ads for a particular brokerage. Overall, the web app focuses on managing clients, their subscriptions, and advertisements for brokerages.

A video demonstrating the output and the code is shown below:


Alternate Link

A Sample of the Source Code is below, view the full codebase on GitHub

Clinets Controller
Brokerages Controller
Advertisements Controller
Exported from Notepad++
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using Microsoft.AspNetCore.Mvc; 6 using Microsoft.AspNetCore.Mvc.Rendering; 7 using Microsoft.EntityFrameworkCore; 8 using RealEstateMarket.Data; 9 using RealEstateMarket.Models; 10 using RealEstateMarket.Models.ViewModels; 11 using Microsoft.AspNetCore.Mvc.Routing; 12 13 namespace RealEstateMarket.Controllers 14 { 15 public class ClientsController : Controller 16 { 17 private readonly MarketDbContext _context; 18 19 public ClientsController(MarketDbContext context) 20 { 21 _context = context; 22 } 23 24 // GET: Clients 25 public async Task<IActionResult> Index(int? id) 26 { 27 var viewModel = new BrokeragesViewModel 28 { 29 Clients = await _context.Clients 30 .Include(Client => Client.Subscriptions) 31 .ThenInclude(Subscription => Subscription.Brokerage) 32 .AsNoTracking() 33 .OrderBy(Client => Client.LastName) 34 .ToListAsync() 35 }; 36 37 if (id != null) 38 { 39 viewModel.Subscriptions = viewModel.Clients 40 .Where(Client => Client.Id == id).Single().Subscriptions; 41 } 42 43 return View(viewModel); 44 } 45 46 // GET: Clients/Details/Id 47 public async Task<IActionResult> Details(int? id) 48 { 49 if (id == null || _context.Clients == null) 50 { 51 return NotFound(); 52 } 53 54 var client = await _context.Clients 55 .FirstOrDefaultAsync(m => m.Id == id); 56 if (client == null) 57 { 58 return NotFound(); 59 } 60 61 return View(client); 62 } 63 64 // GET: Clients/Create 65 public IActionResult Create() 66 { 67 return View(); 68 } 69 70 // POST: Clients/Create 71 [HttpPost] 72 [ValidateAntiForgeryToken] 73 public async Task<IActionResult> Create([Bind("LastName,FirstName,BirthDate")] Client client) 74 { 75 if (ModelState.IsValid) 76 { 77 _context.Add(client); 78 await _context.SaveChangesAsync(); 79 return RedirectToAction(nameof(Index)); 80 } else 81 { 82 throw new Exception("Invalid Client model"); 83 } 84 // return View(client); 85 } 86 87 // GET: Clients/Edit/Id 88 public async Task<IActionResult> Edit(int? id) 89 { 90 if (id == null || _context.Clients == null) 91 { 92 return NotFound(); 93 } 94 95 var client = await _context.Clients.FindAsync(id); 96 if (client == null) 97 { 98 return NotFound(); 99 } 100 return View(client); 101 } 102 103 // POST: Clients/Edit/Id 104 [HttpPost] 105 [ValidateAntiForgeryToken] 106 public async Task<IActionResult> Edit(int id, [Bind("Id,LastName,FirstName,BirthDate")] Client client) 107 { 108 if (id != client.Id) 109 { 110 return NotFound(); 111 } 112 113 if (ModelState.IsValid) 114 { 115 try 116 { 117 _context.Update(client); 118 await _context.SaveChangesAsync(); 119 } 120 catch (DbUpdateConcurrencyException) 121 { 122 if (!ClientExists(client.Id)) 123 { 124 return NotFound(); 125 } 126 else 127 { 128 throw; 129 } 130 } 131 return RedirectToAction(nameof(Index)); 132 } 133 return View(client); 134 } 135 136 // GET: Clients/Delete/Id 137 public async Task<IActionResult> Delete(int? id) 138 { 139 if (id == null || _context.Clients == null) 140 { 141 return NotFound(); 142 } 143 144 var client = await _context.Clients 145 .FirstOrDefaultAsync(m => m.Id == id); 146 if (client == null) 147 { 148 return NotFound(); 149 } 150 151 return View(client); 152 } 153 154 // POST: Clients/Delete/Id 155 [HttpPost, ActionName("Delete")] 156 [ValidateAntiForgeryToken] 157 public async Task<IActionResult> DeleteConfirmed(int id) 158 { 159 if (_context.Clients == null) 160 { 161 return Problem("Entity set 'MarketDbContext.Clients' is null."); 162 } 163 var client = await _context.Clients.FindAsync(id); 164 if (client != null) 165 { 166 _context.Clients.Remove(client); 167 } 168 169 await _context.SaveChangesAsync(); 170 return RedirectToAction(nameof(Index)); 171 } 172 173 // GET: Clients/Edit/Id 174 public async Task<IActionResult> EditSubscriptions(int? id) 175 { 176 if (id == null || _context.Clients == null) 177 { 178 return NotFound(); 179 } 180 181 var viewModel = new ClientSubscriptionsViewModel 182 { 183 Client = await _context.Clients 184 .Include(Client => Client.Subscriptions) 185 .ThenInclude(Subscription => Subscription.Brokerage) 186 .ThenInclude(Brokerage => Brokerage.Subscriptions) 187 .SingleAsync(Client => Client.Id == id), 188 NonSubscribed = await _context.Brokerages 189 .Include(Brokerage=> Brokerage.Subscriptions) 190 .AsNoTracking() 191 .OrderBy(Brokerage => Brokerage.Title) 192 .ToListAsync() 193 }; 194 195 if (viewModel.Client == null) 196 { 197 return NotFound(); 198 } 199 200 // split brokerages into subscribed and unsubscribed 201 viewModel.Subscribed = viewModel.Client.Subscriptions.Select(Subscription => Subscription.Brokerage).OrderBy(Brokerage => Brokerage.Title); 202 viewModel.NonSubscribed = viewModel.NonSubscribed.Except(viewModel.Subscribed); 203 204 return View(viewModel); 205 } 206 207 public async Task<ActionResult> ChangeRegistration(int? clientId, string? brokerageId, bool? register) 208 { 209 if (clientId == null || brokerageId == null || register == null) 210 { 211 return NotFound(); 212 } 213 214 if (register == false) 215 { 216 var subscription = await _context.Subscriptions 217 .FindAsync(clientId, brokerageId); 218 219 if (subscription == null) 220 { 221 return NotFound(); 222 } 223 224 _context.Subscriptions.Remove(subscription); 225 } 226 else 227 { 228 // find client and brokerage 229 var brokerage = await _context.Brokerages.FindAsync(brokerageId); 230 var client = await _context.Clients.FindAsync(clientId); 231 232 if (brokerage == null || client == null) 233 { 234 return NotFound(); 235 } 236 237 var subscription = new Subscription(); 238 subscription.ClientId = client.Id; 239 subscription.BrokerageId = brokerage.Id; 240 subscription.Client = client; 241 subscription.Brokerage = brokerage; 242 243 // add to context 244 _context.Subscriptions.Add(subscription); 245 } 246 247 await _context.SaveChangesAsync(); 248 249 return RedirectToAction("EditSubscriptions", "Clients", new { id = clientId }); 250 } 251 252 private bool ClientExists(int id) 253 { 254 return _context.Clients.Any(e => e.Id == id); 255 } 256 } 257 } 258
Exported from Notepad++
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using Microsoft.AspNetCore.Mvc; 6 using Microsoft.AspNetCore.Mvc.Rendering; 7 using Microsoft.EntityFrameworkCore; 8 using RealEstateMarket.Data; 9 using RealEstateMarket.Models; 10 using RealEstateMarket.Models.ViewModels; 11 12 namespace RealEstateMarket.Controllers 13 { 14 public class BrokeragesController : Controller 15 { 16 private readonly MarketDbContext _context; 17 18 public BrokeragesController(MarketDbContext context) 19 { 20 _context = context; 21 } 22 23 // GET: Brokerages 24 public async Task<IActionResult> Index(string? Id) 25 { 26 var viewModel = new BrokeragesViewModel 27 { 28 Brokerages = await _context.Brokerages 29 .Include(i => i.Subscriptions) 30 .ThenInclude(Subscription => Subscription.Client) 31 .AsNoTracking() 32 .OrderBy(i => i.Id) 33 .ToListAsync() 34 }; 35 36 if (Id != null) 37 { 38 viewModel.Subscriptions = viewModel.Brokerages.Where( 39 x => x.Id == Id).Single().Subscriptions; 40 } 41 42 return View(viewModel); 43 } 44 45 // GET: Brokerages/Details/5 46 public async Task<IActionResult> Details(string id) 47 { 48 if (id == null || _context.Brokerages == null) 49 { 50 return NotFound(); 51 } 52 53 var brokerage = await _context.Brokerages 54 .FirstOrDefaultAsync(m => m.Id == id); 55 if (brokerage == null) 56 { 57 return NotFound(); 58 } 59 60 return View(brokerage); 61 } 62 63 // GET: Brokerages/Create 64 public IActionResult Create() 65 { 66 return View(); 67 } 68 69 // POST: Brokerages/Create 70 [HttpPost] 71 [ValidateAntiForgeryToken] 72 public async Task<IActionResult> Create([Bind("Id,Title,Fee")] Brokerage brokerage) 73 { 74 if (ModelState.IsValid) 75 { 76 _context.Add(brokerage); 77 await _context.SaveChangesAsync(); 78 return RedirectToAction(nameof(Index)); 79 } 80 return View(brokerage); 81 } 82 83 // GET: Brokerages/Edit/Id 84 public async Task<IActionResult> Edit(string id) 85 { 86 if (id == null || _context.Brokerages == null) 87 { 88 return NotFound(); 89 } 90 91 var brokerage = await _context.Brokerages.FindAsync(id); 92 if (brokerage == null) 93 { 94 return NotFound(); 95 } 96 return View(brokerage); 97 } 98 99 // POST: Brokerages/Edit/Id 100 [HttpPost] 101 [ValidateAntiForgeryToken] 102 public async Task<IActionResult> Edit(string id, [Bind("Id,Title,Fee")] Brokerage brokerage) 103 { 104 if (id != brokerage.Id) 105 { 106 return NotFound(); 107 } 108 109 if (ModelState.IsValid) 110 { 111 try 112 { 113 _context.Update(brokerage); 114 await _context.SaveChangesAsync(); 115 } 116 catch (DbUpdateConcurrencyException) 117 { 118 if (!BrokerageExists(brokerage.Id)) 119 { 120 return NotFound(); 121 } 122 else 123 { 124 throw; 125 } 126 } 127 return RedirectToAction(nameof(Index)); 128 } 129 return View(brokerage); 130 } 131 132 // GET: Brokerages/Delete/Id 133 public async Task<IActionResult> Delete(string id) 134 { 135 if (id == null || _context.Brokerages == null) 136 { 137 return NotFound(); 138 } 139 140 var brokerage = await _context.Brokerages 141 .Include(x => x.Advertisements) 142 .FirstOrDefaultAsync(m => m.Id == id); 143 if (brokerage == null) 144 { 145 return NotFound(); 146 } 147 148 return View(brokerage); 149 } 150 151 // POST: Brokerages/Delete/Id 152 [HttpPost, ActionName("Delete")] 153 [ValidateAntiForgeryToken] 154 public async Task<IActionResult> DeleteConfirmed(string Id) 155 { 156 if (_context.Brokerages == null) 157 { 158 return Problem("Entity set 'MarketDbContext.Brokerages' is null."); 159 } 160 161 var brokerage = await _context.Brokerages 162 .Include(x => x.Advertisements) 163 .FirstOrDefaultAsync(m => m.Id == Id); 164 165 if (brokerage != null) 166 { 167 if (brokerage.Advertisements.Count() > 0) 168 { 169 throw new Exception("Can not delete a brokerage with existing advertisements"); 170 } 171 _context.Brokerages.Remove(brokerage); 172 } 173 174 await _context.SaveChangesAsync(); 175 return RedirectToAction(nameof(Index)); 176 } 177 178 private bool BrokerageExists(string id) 179 { 180 return _context.Brokerages.Any(e => e.Id == id); 181 } 182 } 183 } 184
Exported from Notepad++
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading.Tasks; 5 using Microsoft.AspNetCore.Mvc; 6 using Microsoft.AspNetCore.Mvc.Rendering; 7 using Microsoft.EntityFrameworkCore; 8 using RealEstateMarket.Data; 9 using RealEstateMarket.Models; 10 using RealEstateMarket.Models.ViewModels; 11 using Azure.Storage.Blobs; 12 using Azure; 13 using System.Diagnostics; 14 using System.ComponentModel; 15 16 namespace RealEstateMarket.Controllers 17 { 18 public class AdvertisementsController : Controller 19 { 20 private readonly MarketDbContext _context; 21 private readonly BlobServiceClient _blobServiceClient; 22 23 private readonly long _fileSizeLimit = 20000000; 24 private readonly string[] permittedExtensions = { ".png", ".jpg", ".jpeg", ".gif" }; 25 private readonly string container = "adimages"; 26 27 public AdvertisementsController(MarketDbContext context, BlobServiceClient blobServiceClient) 28 { 29 _context = context; 30 _blobServiceClient = blobServiceClient; 31 } 32 33 // GET: Advertisements 34 public async Task<IActionResult> Index(string? Id) 35 { 36 if (Id != null) 37 { 38 // find the brokerage 39 var brokerage = await _context.Brokerages 40 .Include(b=>b.Advertisements) 41 .SingleAsync(b => b.Id == Id); 42 43 return View(brokerage); 44 45 } 46 else 47 { 48 return NotFound(); 49 } 50 } 51 52 53 // GET: Advertisements/Create 54 public async Task<IActionResult> Create(string? Id) 55 { 56 if (Id != null) 57 { 58 // find the brokerage 59 var brokerage = await _context.Brokerages 60 .SingleAsync(b => b.Id == Id); 61 62 return View(brokerage); 63 } 64 else 65 { 66 return NotFound(); 67 } 68 } 69 70 [BindProperty] 71 public Advertisement Advertisement { get; set; } 72 73 // POST: Advertisements/Create 74 [HttpPost] 75 [ValidateAntiForgeryToken] 76 public async Task<IActionResult> Create(IFormFile file, string brokerageId) 77 { 78 // perform validation checks 79 var ext = Path.GetExtension(file.FileName).ToLowerInvariant(); 80 if (string.IsNullOrEmpty(ext) || !permittedExtensions.Contains(ext)) 81 { 82 String message = "File extension must be one of "; 83 foreach (string extension in permittedExtensions) 84 { 85 message += extension + " "; 86 } 87 // Debug.WriteLine(message); 88 throw new Exception(message); 89 } 90 91 if (file.Length > _fileSizeLimit || file.Length == 0) 92 { 93 // Debug.WriteLine("File size must be greater than 0 bytes and upto 20MB"); 94 throw new Exception("File size must be greater than 0 bytes and upto 20MB"); 95 } 96 97 // create container client to attach to a container 98 BlobContainerClient containerClient; 99 try 100 { 101 // attempt to create a new container and make public 102 containerClient = await _blobServiceClient.CreateBlobContainerAsync(container); 103 containerClient.SetAccessPolicy(Azure.Storage.Blobs.Models.PublicAccessType.BlobContainer); 104 } 105 catch (RequestFailedException) 106 { 107 // container already exists 108 containerClient = _blobServiceClient.GetBlobContainerClient(container); 109 } 110 111 try 112 { 113 string filePath = Path.GetRandomFileName(); 114 // create the blob to hold the data 115 var blockBlob = containerClient.GetBlobClient(filePath); 116 // if blob exists already throw an error 117 if (await blockBlob.ExistsAsync()) 118 { 119 throw new Exception("Blob with specified url already exists"); 120 } 121 122 Advertisement.FileName = filePath; 123 Advertisement.Url = blockBlob.Uri.AbsoluteUri; 124 125 using (var memoryStream = new MemoryStream()) 126 { 127 // copy the file data into memory 128 await file.CopyToAsync(memoryStream); 129 130 // navigate back to the beginning of the memory stream 131 memoryStream.Position = 0; 132 133 // send the file to the cloud 134 await blockBlob.UploadAsync(memoryStream); 135 memoryStream.Close(); 136 } 137 138 139 } 140 catch (RequestFailedException) 141 { 142 throw new Exception("Image blob already exists"); 143 } 144 145 // find the brokerage 146 var brokerage = await _context.Brokerages 147 .Include(b=>b.Advertisements) 148 .SingleAsync(b => b.Id == brokerageId); 149 150 // add brokerage to the advertisement 151 Advertisement.Brokerage = brokerage; 152 153 // add advertisement to brokerage 154 brokerage.Advertisements.Add(Advertisement); 155 156 // update in context 157 _context.Advertisements.Add(Advertisement); 158 _context.Brokerages.Update(brokerage); 159 160 // save context 161 await _context.SaveChangesAsync(); 162 163 return RedirectToAction("Index", new { id = brokerageId }); 164 } 165 166 167 // GET: Advertisements/Delete/5 168 public async Task<IActionResult> Delete(int? id) 169 { 170 if (id == null || _context.Advertisements == null) 171 { 172 return NotFound(); 173 } 174 175 var advertisement = await _context.Advertisements 176 .Include(a => a.Brokerage) 177 .FirstOrDefaultAsync(m => m.AdId == id); 178 if (advertisement == null) 179 { 180 return NotFound(); 181 } 182 183 return View(advertisement); 184 } 185 186 187 // POST: Advertisements/Delete/Id 188 [HttpPost, ActionName("Delete")] 189 [ValidateAntiForgeryToken] 190 public async Task<IActionResult> DeleteConfirmed(int AdId) 191 { 192 // find the advertisement 193 var advertisement = await _context.Advertisements 194 .Include(b => b.Brokerage) 195 .SingleAsync(b => b.AdId == AdId); 196 var brokerageId = advertisement.Brokerage.Id; 197 198 BlobContainerClient containerClient; 199 try 200 { 201 // get the container and store container object 202 containerClient = _blobServiceClient.GetBlobContainerClient(container); 203 } 204 catch (RequestFailedException) 205 { 206 throw new Exception("Container does not exist"); 207 } 208 209 try 210 { 211 await containerClient.DeleteBlobAsync(advertisement.FileName); 212 } 213 catch (RequestFailedException) 214 { 215 throw new Exception("Specified blob does not exist"); 216 } 217 218 // find the brokerage and remove ad 219 //var brokerage = await _context.Brokerages 220 //.Include(b => b.Advertisements) 221 //.SingleAsync(b => b.Id == brokerageId); 222 223 // brokerage.Advertisements.Remove(advertisement); 224 225 // update in context 226 // _context.Brokerages.Update(brokerage); 227 _context.Advertisements.Remove(advertisement); 228 229 await _context.SaveChangesAsync(); 230 231 232 return RedirectToAction("Index", new { id = brokerageId }); 233 } 234 235 private bool AdvertisementExists(int id) 236 { 237 return _context.Advertisements.Any(e => e.AdId == id); 238 } 239 } 240 } 241