C
C#•8mo ago
Natty

Code Review (Web Api)

Is this a proper set up for a web api project? If not, what should I change? https://pastebin.com/V4ky2YXX
25 Replies
Jake
Jake•8mo ago
You can rename the route to [Route("api/["controller"])] it gets the name of the controller from the filname e.g. FacilityController -> facility (it slices the controller from the name)
No description
Jake
Jake•8mo ago
other then that it looks fine from my pov
Jake
Jake•8mo ago
This basically lets you avoid the repetetive code here
No description
Natty
Natty•8mo ago
Gotcha, thanks @frostbyte. I should have mentioned, I'm more interested in if my pattern and the way I'm doing things is proper. I'm aware I probably need to handle a bit more like if GetAllFacilities() is empty, etc what to return, and so on. But just curious about my set up before I continue on with the whole project with this format.
Jake
Jake•8mo ago
yeh the pattern looks great youve got abstraction from the controller and business logic which is good
Natty
Natty•8mo ago
Is service for all this correct, or is it more repository? I always get confused because sometimes I swear I see the names used interchangably, and other times I see both services and repositories.
Jake
Jake•8mo ago
It would usually be called Repository The service would be the api itself
Natty
Natty•8mo ago
Ok so it would make more sense to rename everything with repository in place of service?
Jake
Jake•8mo ago
Yeh so rename to IFacilityRepository and FacilityRepository
Natty
Natty•8mo ago
Ok thank you! Why do some projects have both though? A service layer and a repository layer?
Jake
Jake•8mo ago
Its usually related to CQRS , so a seperation of concerns. The service layer is responsible for containing the business logic and application-specific functionality. So like any service to service communication etc. The repository layer is responsible for data access and persistence
Natty
Natty•8mo ago
This post on SO makes it seem like what I have service is more correct: https://stackoverflow.com/questions/1440096/difference-between-repository-and-service But idk ok yeah so what that post says Maybe i'm interpreting it wrong then.
Jake
Jake•8mo ago
What you are doing in ur files is communicating with database which is usually in the repository layer. Since ur accessing and manipulating data.
Natty
Natty•8mo ago
Ah ok thank you that is helpful.
Jake
Jake•8mo ago
Any kind of communication with the database read and write happens in Repository
Natty
Natty•8mo ago
Ok I'll go and rename it all to Repository.
Jake
Jake•8mo ago
I think he kinda worded it wrong... its kinda misleading. I think he means that the service the (api) calls the repository methods... its kinda wrong
Natty
Natty•8mo ago
Yeah i was quite confused lol. So in a web api project, let's say what I have is the repository layer, what would be an example of service?
Jake
Jake•8mo ago
Common web application architectures - .NET
Architect Modern Web Applications with ASP.NET Core and Azure | Explore the common web application architectures
Jake
Jake•8mo ago
Read up on this as well 😉
Natty
Natty•8mo ago
Will do, thank you!
Jake
Jake•8mo ago
RabbitMQ configuration,Any kind of messaging services MassTransit Those would be in a seperate project in a class library
Natty
Natty•8mo ago
Gotcha, ok. So like an actual "service".
Jake
Jake•8mo ago
Yes
Natty
Natty•8mo ago
Cool thanks i think this is good, ill read the link 🙂 Frost, additionally, since you already know my set up, I don't think my Unit tests make sense. For example I am doing:
[Fact]
public async Task GetCitiesAsync_ShouldReturnNull_WhenCityDoesNotExist()
{
// Arrange
var listOfFacilities = new List<Facility>
{
new() { City = "Houston", Name = "Your Safety", PhoneNumber = "360-555-1234", WebsiteUrl = "www.mycool.com"},
new() { City = "Atlanta", Name = "Big Measures", PhoneNumber = "320-555-1111", WebsiteUrl = "www.bigmeasure.com"},
new() { City = "NYC", Name = "Test1", PhoneNumber = "Test1", WebsiteUrl = "Test1" },
new() { City = "NYC", Name = "Test2", PhoneNumber = "Test2", WebsiteUrl = "Test2" }
};

_facilityRepository.GetCitiesAsync(Arg.Is<string>(x => x == "NotACity")).ReturnsForAnyArgs((List<Facility>?)null);

// Act
var result = await _facilityController.GetCitiesAsync("NotACity");

// Assert
Assert.IsType<NotFoundResult>(result);

var notFoundResult = (NotFoundResult)result;
Assert.Equal(404, notFoundResult.StatusCode);
}
[Fact]
public async Task GetCitiesAsync_ShouldReturnNull_WhenCityDoesNotExist()
{
// Arrange
var listOfFacilities = new List<Facility>
{
new() { City = "Houston", Name = "Your Safety", PhoneNumber = "360-555-1234", WebsiteUrl = "www.mycool.com"},
new() { City = "Atlanta", Name = "Big Measures", PhoneNumber = "320-555-1111", WebsiteUrl = "www.bigmeasure.com"},
new() { City = "NYC", Name = "Test1", PhoneNumber = "Test1", WebsiteUrl = "Test1" },
new() { City = "NYC", Name = "Test2", PhoneNumber = "Test2", WebsiteUrl = "Test2" }
};

_facilityRepository.GetCitiesAsync(Arg.Is<string>(x => x == "NotACity")).ReturnsForAnyArgs((List<Facility>?)null);

// Act
var result = await _facilityController.GetCitiesAsync("NotACity");

// Assert
Assert.IsType<NotFoundResult>(result);

var notFoundResult = (NotFoundResult)result;
Assert.Equal(404, notFoundResult.StatusCode);
}
but if i changed this line to: var result = await _facilityController.GetCitiesAsync("NYC"); it still passes, when I would think it shouldn't... I can do more reading on my own, but just if you're interested and still around. No worries.