In .NET 6 API controller, I'm returning data with Ok IActionResult, below is my code, there I want to pass a string message along with return Ok(employee);
Is it possible if so, please suggest how to do it.
[Route("{Id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Employee))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetEmployeeDetails(int Id)
{
var listEmployees = new List<Employee>()
{
new Employee(){ Id = 1001, Name = "Anurag", Age = 28, City = "Mumbai", Gender = "Male", Department = "IT" },
new Employee(){ Id = 1002, Name = "Pranaya", Age = 28, City = "Delhi", Gender = "Male", Department = "IT" },
new Employee(){ Id = 1003, Name = "Priyanka", Age = 27, City = "BBSR", Gender = "Female", Department = "HR"},
};
var employee = listEmployees.FirstOrDefault(emp => emp.Id == Id);
if (employee != null)
{
**return Ok(employee);**
}
else
{
return NotFound();
}
}
In order to return the message with the data as well, I would suggest creating a model class that allows returning multiple values.
For example, an ApiResponse class that support generic type.
public class ApiResponse<T>
{
public string Message { get; set; }
public T Data { get; set; }
}
And your controller action to return the value of ApiResponse<Employee> type for the status 200 scenario as below:
[Route("{Id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ApiResponse<Employee>))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetEmployeeDetails(int Id)
{
var listEmployees = new List<Employee>()
{
new Employee(){ Id = 1001, Name = "Anurag", Age = 28, City = "Mumbai", Gender = "Male", Department = "IT" },
new Employee(){ Id = 1002, Name = "Pranaya", Age = 28, City = "Delhi", Gender = "Male", Department = "IT" },
new Employee(){ Id = 1003, Name = "Priyanka", Age = 27, City = "BBSR", Gender = "Female", Department = "HR"},
};
var employee = listEmployees.FirstOrDefault(emp => emp.Id == Id);
if (employee != null)
{
return Ok(new ApiResponse<Employee>
{
Message = "Assign your message here",
Data = employee
});
}
else
{
return NotFound();
}
}
Unfortunately don't think that is possible to do. The workaround could be that you add an extra field to the Employee object such as a string of description that gets returned as a whole.
Related
I've created a list of courses that students are enrolled in. However, I can't figure out how to access the objects from the list in the Main. Below, I've tried to get the Student-Id and pull the information from there, but it isn't working. I'm new to coding please help
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;
namespace Jvstt_College
{
class Admin
{
##
## Dictionary<int, Student> studentList = new Dictionary<int, Student>();
Dictionary<int, Professor> professorList = new Dictionary<int, Professor>();
List<Course> courseList = new List<Course>();
Dictionary<int, Student> studentCourses = new Dictionary<int, Student>();
public Dictionary<int, Student> StudentList()
{
var Student1 = new Student() { FirstName = "Tom", LastName = " Jones", Password = "Test", EnrollmentId = 111111};
var Student2 = new Student() { FirstName = "Mark", LastName = " Thomas", Password = "Grace", EnrollmentId = 101203 };
var Student3 = new Student() { FirstName = "Jake", LastName = " Riley", Password = "SavedbyChrist1", EnrollmentId = 568903 };
var Student4 = new Student() { FirstName = "Olivia", LastName = " Beckam", Password = "GodisGood", EnrollmentId = 951357 };
var Student5 = new Student() { FirstName = "Myrai", LastName = " Bailey", Password = "ChildofGod", EnrollmentId = 741369 };
var Student6 = new Student() { FirstName = "Majea", LastName = " Bailey", Password = "CoastLand", EnrollmentId = 852146 };
studentList.Add(111111, Student1);
studentList.Add(101203, Student2);
studentList.Add(568903, Student3);
studentList.Add(951357, Student4);
studentList.Add(741369, Student5);
studentList.Add(852146, Student6);
return studentList;
}
public Dictionary<int, Professor> ProfessorList()
{
professorList.Add(654321, new Professor { FirstName = "Grace", LastName = "Riley", Password = "Gracey1983", EnrollmentId = 654321 });
enter code here professorList.Add(852963, new Professor { FirstName = "Liam", LastName = "Beckam", Password = "Password", EnrollmentId = `enter code here`852963 });
professorList.Add(359861, new Professor { FirstName = "Martha", LastName = "Hart", Password = "QwertYy00", EnrollmentId = 359861 });
professorList.Add(612832, new Professor { FirstName = "George", LastName = "Washington", Password = "Kid$nExtD00r", EnrollmentId = 612832 });
return professorList;
}
public List<Course> CourseList()
{
var Accounts = new Course() { CourseID = 101, CourseName = " Accounts " };
var Bio_Psychology = new Course() { CourseID = 102, CourseName = " Bio_Psychology " };
var Business = new Course() { CourseID = 103, CourseName = " Business " };
var Chemistry = new Course() { CourseID = 104, CourseName = " Chemistry " };
var CSWDCA = new Course() { CourseID = 105, CourseName = " Computer Science/Web Design/Cybersecurity Accounts" };
var Psychology = new Course() { CourseID = 106, CourseName = " Psychology " };
var Statistics = new Course() { CourseID = 107, CourseName = " Statistics " };
var Advance_Math = new Course() { CourseID = 108, CourseName = "Advance Math" };
courseList.Add(Accounts);
courseList.Add(Bio_Psychology);
courseList.Add(Business);
courseList.Add(Chemistry);
courseList.Add(CSWDCA);
courseList.Add(Psychology);
courseList.Add(Statistics);
courseList.Add(Advance_Math);
return courseList;
}
public Dictionary<int, Student> StudentEnrollments()
{
var Student1 = studentList[111111];
{
if(Student1.Courses == null)
{
Student1.Courses = new List<Course>();
Student1.Courses?.Add(courseList[0]);
Student1.Courses?.Add(courseList[2]);
Student1.Courses?.Add(courseList[4]);
}
}
var Student2 = studentList[101203];
{
if(Student2.Courses == null)
{
Student2.Courses = new List<Course>();
Student2.Courses?.Add(courseList[1]);
Student2.Courses?.Add(courseList[4]);
Student2.Courses?.Add(courseList[5]);
Student2.Courses?.Add(courseList[6]);
Student2.Courses?.Add(courseList[7]);
}
}
var Student3 = studentList[568903];
{
if (Student3.Courses == null)
{
Student3.Courses = new List<Course>();
Student3.Courses?.Add(courseList[1]);
Student3.Courses?.Add(courseList[4]);
}
}
var Student4 = studentList[951357];
{
if (Student4.Courses == null)
{
Student4.Courses = new List<Course>();
Student4.Courses?.Add(courseList[1]);
Student4.Courses?.Add(courseList[5]);
Student4.Courses?.Add(courseList[7]);
}
}
var Student5 = studentList[741369];
{
if (Student5.Courses == null)
{
Student5.Courses = new List<Course>();
Student5.Courses?.Add(courseList[0]);
Student5.Courses?.Add(courseList[2]);
Student5.Courses?.Add(courseList[3]);
Student5.Courses?.Add(courseList[6]);
Student5.Courses?.Add(courseList[7]);
}
}
var Student6 = studentList[852146];
{
if (Student6.Courses == null)
{
Student6.Courses = new List<Course>();
Student6.Courses?.Add(courseList[0]);
Student6.Courses?.Add(courseList[1]);
Student6.Courses?.Add(courseList[2]);
Student6.Courses?.Add(courseList[3]);
Student6.Courses?.Add(courseList[4]);
Student6.Courses?.Add(courseList[5]);
Student6.Courses?.Add(courseList[6]);
}
}
studentCourses.Add(111111,Student1);
studentCourses.Add(101203,Student2);
studentCourses.Add(568903,Student3);
studentCourses.Add(951357,Student4);
studentCourses.Add(741369,Student5);
studentCourses.Add(852146,Student6);
return studentCourses;
}
}
}
}
First, let's declare the Professor, Student and Course classes. Since Professor and Student have similar properties and since they both are persons, it makes sense to derive them both from an abstract Person class. An abstract class cannot be instantiated.
abstract class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public int EnrollmentId { get; set; }
}
class Professor : Person
{
}
class Student : Person
{
public List<Course> Courses { get; } = new List<Course>();
}
class Course
{
public int CourseID { get; set; }
public string CourseName { get; set; }
}
In class Student I created the Courses list as read-only property and initialized it with a property initializer. This saves you from having to do something like if (Student2.Courses == null) { Student2.Courses = new List<Course>(); ... } later.
You have several method initializing lists and dictionaries. Those should declare and create the collections they return. Otherwise, if the collections are declared in a surrounding scope, the return statement would not be required and the responsibilities would not be clear. Add also, a dictionary is not a list. Since these methods do rely on instance fields anymore, we make them static (and simplify them):
// In class Admin
private static Dictionary<int, Student> CreateStudents()
{
return new Dictionary<int, Student> {
{ 111111, new Student { FirstName = "Tom", LastName = " Jones", Password = "Test", EnrollmentId = 111111 } },
{ 101203, new Student { FirstName = "Mark", LastName = " Thomas", Password = "Grace", EnrollmentId = 101203 } },
{ 568903, new Student { FirstName = "Jake", LastName = " Riley", Password = "SavedbyChrist1", EnrollmentId = 568903 } },
{ 951357, new Student { FirstName = "Olivia", LastName = " Beckam", Password = "GodisGood", EnrollmentId = 951357 } },
{ 741369, new Student { FirstName = "Myrai", LastName = " Bailey", Password = "ChildofGod", EnrollmentId = 741369 } },
{ 852146, new Student { FirstName = "Majea", LastName = " Bailey", Password = "CoastLand", EnrollmentId = 852146 } }
};
}
private static Dictionary<int, Professor> CreateProfessors()
{
return new Dictionary<int, Professor> {
{ 654321, new Professor { FirstName = "Grace", LastName = "Riley", Password = "Gracey1983", EnrollmentId = 654321 } },
{ 852963, new Professor { FirstName = "Liam", LastName = "Beckam", Password = "Password", EnrollmentId = 852963 } },
{ 359861, new Professor { FirstName = "Martha", LastName = "Hart", Password = "QwertYy00", EnrollmentId = 359861 } },
{ 612832, new Professor { FirstName = "George", LastName = "Washington", Password = "Kid$nExtD00r", EnrollmentId = 612832 } }
};
}
private static List<Course> CreateCourses()
{
return new List<Course> {
new Course { CourseID = 101, CourseName = "Accounts" },
new Course { CourseID = 102, CourseName = "Bio_Psychology" },
new Course { CourseID = 103, CourseName = "Business" },
new Course { CourseID = 104, CourseName = "Chemistry" },
new Course { CourseID = 105, CourseName = "Computer Science/Web Design/Cybersecurity Accounts" },
new Course { CourseID = 106, CourseName = "Psychology" },
new Course { CourseID = 107, CourseName = "Statistics" },
new Course { CourseID = 108, CourseName = "Advance Math" }
};
}
Now, we can declare and initialize the collections like this:
class Admin
{
public readonly Dictionary<int, Student> students = CreateStudents();
public readonly Dictionary<int, Professor> professors = CreateProfessors();
public readonly List<Course> courses = CreateCourses();
...
}
I made them read-only. This only means that we cannot assign it another collection later. The collections themselves are still read/write.
We do not need another collection studentCourses, we can directly add the courses to the students in our existing students dictionary.
If we declare an instance method EnrollStudents in class Admin, then it can access the fields of this class.
public void EnrollStudents()
{
Student student = students[111111];
student.Courses.Add(courses[0]);
student.Courses.Add(courses[2]);
student.Courses.Add(courses[4]);
student = students[101203]; // It is okay to reuse the student variable
student.Courses.Add(courses[1]);
student.Courses.Add(courses[4]);
student.Courses.Add(courses[5]);
student.Courses.Add(courses[6]);
student.Courses.Add(courses[7]);
student = students[568903];
student.Courses.Add(courses[1]);
student.Courses.Add(courses[4]);
student = students[951357];
student.Courses.Add(courses[1]);
student.Courses.Add(courses[5]);
student.Courses.Add(courses[7]);
student = students[741369];
student.Courses.Add(courses[0]);
student.Courses.Add(courses[2]);
student.Courses.Add(courses[3]);
student.Courses.Add(courses[6]);
student.Courses.Add(courses[7]);
student = students[852146];
student.Courses.Add(courses[0]);
student.Courses.Add(courses[1]);
student.Courses.Add(courses[2]);
student.Courses.Add(courses[3]);
student.Courses.Add(courses[4]);
student.Courses.Add(courses[5]);
student.Courses.Add(courses[6]);
}
Note that we do not have to return anything. Since classes are reference types, all the students in the original students dictionary have now been updated with courses. Of course we must call this method somewhere (probably in Main).
But we can simplify this method with a new helper method, because we have a lot of repetitions we can avoid:
private void AddStudentCourses(Student student, params int[] courseIndexes)
{
foreach (int index in courseIndexes) {
student.Courses.Add(courses[index]);
}
}
public void EnrollStudents()
{
AddStudentCourses(students[111111], 0, 2, 4);
AddStudentCourses(students[101203], 1, 4, 5, 6, 7);
AddStudentCourses(students[568903], 1, 4);
AddStudentCourses(students[951357], 1, 5, 7);
AddStudentCourses(students[741369], 0, 2, 3, 6, 7);
AddStudentCourses(students[852146], 0, 1, 2, 3, 4, 5, 6);
}
Test:
var admin = new Admin();
admin.EnrollStudents();
var orderedStudents = admin.students.Values
.OrderBy(s => s.LastName)
.ThenBy(s => s.FirstName);
foreach (var student in orderedStudents) {
Console.WriteLine($"{student.LastName} {student.FirstName} ({student.EnrollmentId})");
IOrderedEnumerable<Course> orderedCourses = student.Courses.OrderBy(c => c.CourseName);
foreach (var course in orderedCourses) {
Console.WriteLine($" {course.CourseName} ({course.CourseID})");
}
Console.WriteLine();
}
Prints
Bailey Majea (852146)
Accounts (101)
Bio_Psychology (102)
Business (103)
Chemistry (104)
Computer Science/Web Design/Cybersecurity Accounts (105)
Psychology (106)
Statistics (107)
Bailey Myrai (741369)
Accounts (101)
Advance Math (108)
Business (103)
Chemistry (104)
Statistics (107)
Beckam Olivia (951357)
Advance Math (108)
Bio_Psychology (102)
Psychology (106)
Jones Tom (111111)
Accounts (101)
Business (103)
Computer Science/Web Design/Cybersecurity Accounts (105)
Riley Jake (568903)
Bio_Psychology (102)
Computer Science/Web Design/Cybersecurity Accounts (105)
Thomas Mark (101203)
Advance Math (108)
Bio_Psychology (102)
Computer Science/Web Design/Cybersecurity Accounts (105)
Psychology (106)
Statistics (107)
I have a previous question that shows how my models look and it was adding FAKE data. Add to Existing Model based on a POCO with need to add to List<T>
Now I am wanting to add REAL data and i'm wondering how to do this. Should or need I loop over the result ??
public IActionResult FindPerson (FindPersonViewModel findPersonViewModel)
{
var firstName = findPersonViewModel.FirstName;
var middleName = findPersonViewModel.MiddleName;
var lastName = findPersonViewModel.LastName;
var emailAddress = findPersonViewModel.EmailAddress;
var genderTypeId = findPersonViewModel.GenderTypeId;
// GET REAL DATA
using (AzEdsIdentityContext context = new AzEdsIdentityContext(AzEdsIdentityContext.Options))
{
var result = context.FindPerson(firstName, lastName, genderTypeId);
// for loop on the result to hydrate new List<FindPersonResultsViewModel>() ?
}
// Note: here is exactly how I hydrated the model with fake data
findPersonViewModel.findPersonResultsViewModel = new List<FindPersonResultsViewModel>()
{ new FindPersonResultsViewModel { AZEDID = 33423432, PersonID = 3534454, FirstName = "John", LastName = "Williamson", MiddleName = "K", ExistInContactManager = false, ActionType = true, ContactType = "Principal", DOB = "5/1/1985", PhysicalAddress = "123 main st. mesa, az.", PreferredEmail = "john#aol.com", PreferredPhone = "602-393-4443"},
new FindPersonResultsViewModel { AZEDID = 33423432, PersonID = 3534454, FirstName = "Jon", LastName = "Williamson", MiddleName = "K", ExistInContactManager = false, ActionType = true, ContactType = "Principal", DOB = "5/1/1985", PhysicalAddress = "123 main st. mesa, az.", PreferredEmail = "john#aol.com", PreferredPhone = "602-393-4443"},
};
}
Given the Person model
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
And you obtain the result from your context
List<Person> result = context.getPersons();
You need a collection of a different but similar type, so you use a projection
List<PersonViewModel> result =
context.getPersons()
.Select(p => new FindPersonResultsViewModel
{
Name = p.Name,
Email = p.Email
}).ToList();
Then assign the collection property to another model
var model = new ResultViewModel
{
...
findPersonResultsViewModel = result
};
If you're getting back IEnumerable, do .ToList() to get the List<T>.
I'm having Two models Person and Boss. Boss is derived from Person. Here the property ID and SID both are speaking about the Employee ID. The ID Speaks about the Boss and SID speaks about the Assistant Staff.
Kindly refer the Model Classes and the Collection
public class Person
{
public int ID { get; set; }
public int SID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string Gender { get; set; }
public string Role { get; set; }
}
public class Boss
{
public int ID { get; set; }
public int SID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string Gender { get; set; }
public string Role { get; set; }
public List<Person> Employees { get; set; }
}
void Main()
{
List<Boss> BossList = new List<Boss>()
{
new Boss()
{
ID = 101,
Name = "Harry",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {ID = 101, SID = 102, Name = "Peter", Department = "Development", Gender = "Male", Role = "Assistant"},
new Person() {ID = 101, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
}
},
new Boss()
{
ID = 104,
Name = "Raj",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {ID = 104, SID = 105, Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
new Person() {ID = 104, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
}
},
new Boss()
{
ID = 102,
Name = "Peter",
Department = "Development",
Gender = "Male",
Role = "Manager",
Employees = new List<Person>()
{
new Person() {ID = 102, SID = 105, Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
new Person() {ID = 102, SID = 103, Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
}
}
};
}
My Required Collection should be
List<Person> Members = new List<Person>()
{
new Person() {Name = "Harry", Department = "Development", Gender = "Male", Role = "Manager"},
new Person() {Name = "Peter", Department = "Development", Gender = "Male", Role = "Manager"},
new Person() {Name = "Emma Watson", Department = "Development", Gender = "Female", Role = "Assistant"},
new Person() {Name = "Raj", Department = "Development", Gender = "Male", Role = "Manager"},
new Person() {Name = "Kaliya", Department = "Development", Gender = "Male", Role = "Assistant"},
}
Here My Requirement is I need to make the Distinct list of Employees including Boss. But the Distinct list contains Peter has an unique ID 102 in both Boss as well as in Assistant Staff, but here I need to select the Manager Role not a Assistant Role record.
Kindly assist me how to achieve this. Kindly provide your answer instead on suggestions to change the Model structure or any other suggestions.
Explanation of ID and SID:
ID : It has an Employee ID of Boss
SID : It has an Employee ID of Assistant
The Collection - Role is marked as Manager, then he/she don't have an SID, because he is a Boss (or) Manager. He/She is the Superior so the Employee ID is assigned in ID. In other case Role is marked as Assistant, then he/she is under any one of the Boss (or) Manager. So, the ID is marked with the Manager ID and the actual Employee ID is marked in SID.
The first thing to do is to create custom IEqualityComparer<Person> class which will be used as Distinct argument.
Edit #2: taking into account role
public class PersonEqualityComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if(x == null && y == null) return true;
int xid = x.Role == "Manager" ? x.ID : x.SID;
int yid = y.Role == "Manager" ? y.ID : y.SID;
return xid == yid;
}
public int GetHashCode(Person obj)
{
return obj.Role == "Manager" ? obj.ID : obj.SID;
}
}
Then you can write this:
// take employees first
var personList = BossList.SelectMany(x => x.Employees).ToList();
// add bosses to list
personList.AddRange(BossList.AsEnumerable());
// take distinct persons
var result = personList.Distinct(new PersonEqualityComparer()).ToList();
I have noticed some issues with your code:
SID = "Emma Watson" is used twice. I assume that something like SID = 103, Name = "Emma Watson" was intended.
You've said that Boss is derived from Person, however code does not stick with this statement. I assume Boss : Person should be written and duplicate fields should be omitted.
Edit:
If it is possible kindly give your answer in a single inline LINQ Statement.
var result = BossList.SelectMany(x => x.Employees)
.Union(BossList.AsEnumerable())
.Distinct(new PersonEqualityComparer())
.ToList();
Still you need to have PersonEqualityComparer code.
Edit #3
var personList = BossList.SelectMany(x => x.Employees).Union(BossList.AsEnumerable()).ToList();
var ids = personList.Select(x => x.Role == "Manager" ? x.ID : x.SID).Distinct().ToList();
var result = ids.GroupJoin(personList, id => id, person => person.Role == "Manager" ? person.ID : person.SID,
(id, persons) =>
persons.OrderBy(p => p.Role == "Manager" ? 0 : 1).First()).ToList();
I have a school project with a one to many relationship (Contact can have many Addresses). But I don't know how to seed it correctly.
In my Data models Contact has a virtual ICollection<Address> Addresses and the address object has the foreign key of ContactId.
So here is my seed data (code first) And i need to make it so when i type in the contacts last name in a search bar it will pull up all the info on that contact (address Info).
So how do i associate the info together in my seed data so when you search it pulls up what it is supposed to?
namespace Success.Data.Migrations
{
public class Seeder
{
public static void Seed(SuccessContext context,
bool seedContacts = true,
bool seedAddresses = true)
{
if (seedContacts) SeedContacts(context);
if (seedAddresses) SeedAddresses(context);
}
private static void SeedContacts(SuccessContext context)
{
context.Contacts.AddOrUpdate(l => l.LastName,
new Contact() { FullName = "Darth Vader", FirstName = "Darth", LastName = "Vader", },
new Contact() { FullName = "Luke Skywalker", FirstName = "Luke", LastName = "Skywalker", },
new Contact() { FullName = "Tony Stark", FirstName = "Tony", LastName = "Stark", },
new Contact() { FullName = "Ricky Bobby", FirstName = "Ricky", LastName = "Bobby", },
new Contact() { FullName = "Trix Rabbit", FirstName = "Trix", LastName = "Rabbit", });
context.SaveChanges();
}
private static void SeedAddresses(SuccessContext context)
{
context.Addresses.AddOrUpdate(h => h.HomeAddress,
new Address() { HomeAddress = "1300 DeathStar", BusinessAddress = "444 Imperial Fleet", PoBox = "PO Box 1335", ContactId = 1, },
new Address() { HomeAddress = "1997 Endor", BusinessAddress = "448 Rebel Fleet", PoBox = "PO Box 1339", ContactId = 2, },
new Address() { HomeAddress = "1224 Malibu Point", BusinessAddress = "657 Stark Industries", PoBox = "PO Box 1337", ContactId = 3, },
new Address() { HomeAddress = "9978 Fast LN.", BusinessAddress = "532 NASCAR Race Track", PoBox = "PO Box 1333", ContactId = 4, },
new Address() { HomeAddress = "9864 Cerial Box LN", BusinessAddress = "8432 Kellog Dr.", PoBox = "PO Box 1338", ContactId = 5, });
context.SaveChanges();
}
}
}
You could have another method that seeds both the contacts and address. You will need an extra if/else switch
if (seedContacts && seedAddresses)
{
SeedContactsAndAddress(context);
}
else
{
if (seedContacts) SeedContacts(context);
if (seedAddresses) SeedAddresses(context);
}
And the SeedContactsAndAddress Method would look like this:
private static void SeedContactsAndAddress(StoreContext context)
{
// Each Address, which I believe is a collection in this case, but there is only
// one, will have to be created and added to each contact.
var addressesForDarthVader = new List<Address>
{
new Address { HomeAddress = "1300 DeathStar", BusinessAddress = "444 Imperial Fleet", PoBox = "PO Box 1335" }
// Add more addresses for Darth Vader if you need to
};
// Rinse and repeat for the other contacts;
context.Contacts.AddOrUpdate(l => l.LastName,
new Contact() { FullName = "Darth Vader", FirstName = "Darth", LastName = "Vader", Addresses = addressesForDarthVader },
new Contact() { FullName = "Luke Skywalker", FirstName = "Luke", LastName = "Skywalker", },
new Contact() { FullName = "Tony Stark", FirstName = "Tony", LastName = "Stark", },
new Contact() { FullName = "Ricky Bobby", FirstName = "Ricky", LastName = "Bobby", },
new Contact() { FullName = "Trix Rabbit", FirstName = "Trix", LastName = "Rabbit", });
context.SaveChanges();
}
I am trying to unit test this code,
public bool IsCityAvailable(Appointment appointment)
{
var city = _customerRepository.Find(appointment.CustomerId).City;
return _employeeRepository.Get.Count(x => x.City == city) > 0;
}
Here is my test,
[SetUp]
public void Setup()
{
MockAppointmentRepository = new Mock<IRepository<Appointment>>();
MockCustomerRepository = new Mock<IRepository<Customer>>();
MockShiftRepository = new Mock<IRepository<Shift>>();
MockEmployeeRepository = new Mock<IRepository<Employee>>();
AppointmentService = new AppointmentService(MockCustomerRepository.Object, MockAppointmentRepository.Object, MockShiftRepository.Object, MockEmployeeRepository.Object);
Customer = new Customer()
{
Address = "88 Taraview Road NE",
City = "Calgary",
Email = "charles.norris#outlook.com",
FirstName = "Charles",
LastName = "Norris",
Id = 1,
Phone = "587-888-8882",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee1 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee2 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Appointment = new Appointment()
{
Id = 1,
Customer = Customer,
CustomerId = Customer.Id,
Employee = Employee1,
EmployeeId = Employee1.Id,
ScheduledTime = new DateTime(2013,10,15,18,30,00)
};
}
[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
var employees = new List<Employee> { Employee1, Employee2 };
var result = new Mock<IQueryable<Employee>>();
result.Setup(r => r.GetEnumerator()).Returns(employees.GetEnumerator());
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(result.Object);
// ACT
AppointmentService.IsCityAvailable(Appointment);
// ASSERT
MockCustomerRepository.Verify(x => x.Find(It.IsAny<int>()), Times.Once);
MockEmployeeRepository.Verify(x => x.Get, Times.Once);
}
I have debugged and stepped through can't find the value null it is referring to, my city variable is correct, the appointment parameter is fully populated. Is there something missing I am not seeing?
This is the output error from the unit test:
System.ArgumentNullException : Value cannot be null. Parameter name:
arguments
Here is the stacktrace:
System.ArgumentNullException : Value cannot be null.
Parameter name: arguments
at System.Linq.Expressions.Expression.RequiresCanRead(Expression expression, String paramName)
at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection`1 arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at System.Linq.Queryable.Count(IQueryable`1 source, Expression`1 predicate)
at Zenwire.Services.AppointmentService.IsCityAvailable(Appointment appointment) in AppointmentService.cs: line 81
at Tests.Unit.Zenwire.Services.AppointmentServiceTests.IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound() in AppointmentServiceTests.cs: line 100
To test that everyhing has been called correctly:
[SetUp]
public void Setup()
{
MockAppointmentRepository = new Mock<IRepository<Appointment>>();
MockCustomerRepository = new Mock<IRepository<Customer>>();
MockShiftRepository = new Mock<IRepository<Shift>>();
MockEmployeeRepository = new Mock<IRepository<Employee>>();
AppointmentService = new AppointmentService(MockCustomerRepository.Object, MockAppointmentRepository.Object, MockShiftRepository.Object, MockEmployeeRepository.Object);
Customer = new Customer()
{
Address = "88 Taraview Road NE",
City = "Calgary",
Email = "charles.norris#outlook.com",
FirstName = "Charles",
LastName = "Norris",
Id = 1,
Phone = "587-888-8882",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee1 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee2 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Appointment = new Appointment()
{
Id = 1,
Customer = Customer,
CustomerId = Customer.Id,
Employee = Employee1,
EmployeeId = Employee1.Id,
ScheduledTime = new DateTime(2013,10,15,18,30,00)
};
}
[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(new List<Employee> { Employee1, Employee2 }.AsQueryable());
// ACT
AppointmentService.IsCityAvailable(Appointment);
// ASSERT
MockCustomerRepository.Verify(x => x.Find(It.IsAny<int>()), Times.Once);
MockEmployeeRepository.Verify(x => x.Get, Times.Once);
}
Test the return value:
[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(new List<Employee> { Employee1, Employee2 }.AsQueryable());
// ACT
var actual = AppointmentService.IsCityAvailable(Appointment);
// ASSERT
Assert.IsTrue(actual);
}