I have relatively simple controller logic with ugly parts of object creation. Some of the objects are really huge and even though all the controller does is to return the object, it looks messy and hard to read. So I would like to ask how can I make such cases cleaner. Let me show you a few examples:
For instance, pay attention to the creation of viewmodel:
public async Task<ActionResult> Edit(Guid id){ if (id.IsValidGuid()) { // Get User Details var userTask = ApiGatewayService.GetUserDetail(id, AuthService.BearerToken); var nationalitiesTask = ApiGatewayService.GetNationalityList( new FilterParameters(), AuthService.BearerToken ); var countriesTask = ApiGatewayService.GetCountryList( new FilterParameters(), AuthService.BearerToken ); await Task.WhenAll(userTask, nationalitiesTask, countriesTask); var user = userTask.Result; var nationalities = nationalitiesTask.Result; var countries = countriesTask.Result; if (user is null) return NotFound(); var userAddress = user.PrimaryAddress; var userHomePhone = user.Phones.FirstOrDefault( x => x.Type == PhoneType.LandLine ); var userMobilePhone = user.Phones.FirstOrDefault( x => x.Type == PhoneType.Mobile ); // View Model var viewModel = new EditUserViewModel { User = user, Id = user.Id, FirstName = user.FirstName, LastName = user.LastName, BirthDay = user.Detail?.BirthDay, Email = user.Email, Nationality = user.Detail?.Nationality?.Id, Title = user.Detail != null ? user.Detail.Title : TitleType.Mr, ProfilePhotoName = user.Detail?.ProfilePhotoName, MarketingOptin = user.Detail != null ? user.Detail.MarketingOptin : false, ChangePassword = false, Password = null, Address_City = userAddress?.City, Address_Country = userAddress?.Country.Id, Address_HouseName = userAddress?.HouseName, Address_HouseNumber = userAddress?.HouseNumber, Address_Line = userAddress?.AddressLine, Address_PostCode = userAddress?.PostCode, Address_StreetName = userAddress?.StreetName, Home_CountryCode = userHomePhone?.CountryCode?.ToString(), Home_PhoneNumber = userHomePhone?.PhoneNumber, Mobile_CountryCode = userMobilePhone?.CountryCode?.ToString(), Mobile_PhoneNumber = userMobilePhone?.PhoneNumber, CountriesList = countries.List, NationalitiesList = nationalities.List }; return View(viewModel); } else return RedirectToAction("Index");}
Or another one using LINQ with a huge select
public CompanyDetailModel GetCompanyDetails(Guid accountHolderId){ CompanyDetailModel companyDetailModel = new CompanyDetailModel(); var accountHolder = _dbContext.AccountHolders.FirstOrDefault( x => x.Id == accountHolderId ); var companyId = accountHolder.ObjectId; var company = _dbContext.Companies.FirstOrDefault(x => x.Id == companyId); companyDetailModel.CompanyId = company.Id; companyDetailModel.Description = company.Description; companyDetailModel.Name = company.Name; companyDetailModel.RegistrationNumber = company.RegistrationNumber; companyDetailModel.VATNumber = company.VATNumber; var users = from ah in _dbContext.AccountHolders join uc in _dbContext.UserCompanies on ah.ObjectId equals uc.CompanyId join u in _dbContext.Users on uc.UserId equals u.Id where ah.Id == accountHolderId select new CompanyUserModel { UserId = u.Id, CompanyId = (Guid)uc.CompanyId, FullName = u.FirstName +""+ u.LastName, Email = u.Email, PhoneNumber = u.PhoneNumber, UserCompanyRoleType = uc.Role } ; var invites = from ci in _dbContext.UserCompanyInvites select new CompanyUserInviteModel { Id = ci.Id, CompanyId = ci.CompanyId, IsAccepted = ci.IsAccepted, UserEmail = ci.UserEmail, RoleType = ci.RoleType } ; companyDetailModel.CompanyUsers = users.ToList(); companyDetailModel.CompanyUserInvites = invites.ToList(); return companyDetailModel;}
Is it sufficient to take the creation of objects to a private method, or is there a better way? Wouldn't it be really tedious to set up a mapper?