ASP.NET Core Web API split controller based on aggregates - asp.net-core

In my API project I have currently 1 controller with the following syntax:
Abstract base controller
[Produces("application/json")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status406NotAcceptable)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public abstract class BaseApiController : ControllerBase
{
// ....
}
TestApiController
public class TestApiController : BaseApiController
{
// Parent action methods
[HttpGet]
[HttpPost]
...
// Child action methods
[HttpGet("{test:guid}/child")]
[HttpGet("{test:guid}/child/{id:guid}")]
...
}
This gives us the following urls:
http://localhost/api/v1.0/test
http://localhost/api/v1.0/test/1
http://localhost/api/v1.0/test/1/child
http://localhost/api/v1.0/test/1/child/1
Question
How can I split the controller into multiple files without braking the urls but to have a cleaner overview.
So a controller for all the test actions and another controller for all the child actions.

I'm not talking from an abundance of experience with controllers here (I have done some), but I think you'll find that the controller is the controller - in that there's no easy way to have a controller-route that isn't 1:1.
But, if you want to make controllers more manageable you could just keep them as lean as possible and put the bulk of code into classes that the controller calls.
Alternatively, rather than trying to split/decompose the controller and not the route, rework the overall API design/structure so that you have more controllers and routes. The Interface Segregation Principle comes to mind here (yes it's born out of OO but the principle is still applicable).
At the end of the day, you have calls coming into to API's defined by their routes, and off to the controllers - it doesn't really matter how that all looks (is structured) as long as the API is sufficiently sensible, intuitive and fit for purpose.

After some more searching on the internet I came across the following interesting Nuget package:
Nuget: Ardalis.ApiEndpoints.
Source code and examples about this can be found here:
Github: Ardalis.ApiEndpoints.
This allows us to separate controller into folders and for each action a separated class to give use exactly what we want.

Related

Controller and JsonResult asp.net core

Why do i need to inherit from Controller to return JsonResult?
What is the mechanism that makes the JsonResult type available?
I've tried thinking on it and I figure maybe Controller declares it as a type, but I don't know.
You will need to inherit from Controller in order to use the Controller.Json utility method. You will however not need to inherit from Controller just to create a JsonResult. You can always just new-up one. As long as you are within a controller (not necessarily one that inherits Controller), this will still work:
return new JsonResult(object);
As for why you will need to inherit from Controller and not just ControllerBase; many of the result utility methods actually live in Controller. The reason for this is that those are targeted to view-centric controllers while ControllerBase is typically used for API controllers.
Now one would think that returning JSON results would be especially useful for API controllers but that is actually not the case: For API controllers, you should rather return an ObjectResult and have the conventions take care of serializing that into the format that was requested by the client. That way, an API controller can easily support formats like JSON and XML at the same time.

How does ASP.Net MVC resolve controllers?

I'm trying to build an asp.net mvc 4 application.
I want the application to encompass both a HTML site and a restful api, e.g.
www.mysite.com/MyDetails/
www.mysiste.com/api/users/{userid}/Details/
In the above example I would use 2 controller classes.
MyDetailsController which inherits from System.Web.Mvc.Controller
DetailsController which inherits from System.Web.Http.ApiController
I've also added a simple 'Users Route' to the WebApiConfig:
routeTemplate: "api/users/{userid}/{controller}/{id}
In my early testing it appears as though the following scenarios are invalid:
www.mysite.com/api/users/12345/MyDetails/
www.mysite.com/Details/
Both of those return a 404.
This is definitely a good thing but what I'm trying to find out is why doesn't it work?
Can I rely on it not working or is it just coincidence in my simple test?
I've read about people struggling to develop a single MVC app/project that encompasses both HTML and REST apis but the most common complaint seems to be you can't duplicate controller names and it still seems like you can't simply use a namespace to differentiate them.
In this example I've deliberately designed the class names to avoid any conflict so what other gotchas are waiting to trip me up?
Thanks,
Chris A
Check your routes file, should be Global.asax under RegisterRoutes. The MapRoute call should tell you everything you need to know for MVC routing. Keep in mind, the order of the routes is important: top routes take priority over the bottom. Web API uses the WebApiConfig class and MapHttpRoute call to configure routes.
Please ensure you have put a (MVC) route on top of the action you wish to hit of your controller, default action being index.
[System.Web.Mvc.Route("Help")]
public ActionResult Index()
{
ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
}
Code above will hit this action method (provided your controller is registered and derived either from apiController or Controller) in the following way:
http://localhost:54541/help inside your IISExpress.
To register please do the following:
In "global.asax.cs", you’ll need to add:
AreaRegistration.RegisterAllAreas();

What is the best practices to handle multiple form operation under same action in ASP.NET MVC4?

I have the following scenario in my ASP.NET MVC4 project using Razor Engine:
I have a view with at least 4 different forms.
I would like to handle all form POST under same action mapping.
Actually, the 4 forms post to different Route Mapping, as follow:
POST: /User/FilterRolesInUse/15
POST: /User/RemoveRoles/15
POST: /User/FilterRolesNotInUse/15
POST: /User/AddRoles/15
I would like to know if is it possible to handle all 4 form under the same Route Mapping, something where all form post to /User/Roles/15 and then the controller can distinguish which form was submitted. The concept is something like:
class UserController : Controller {
//
// POST: /User/Roles/
public ActionResult Roles(int? id, object form) {
return DelegateToFormLogic(id, form);
}
}
I just want to know if is it possible because I really want to keep URL consistent.
Any advice or suggestion are welcome.
I do not see any advantage to having a single action that performs multiple functions. In fact it will be confusing to anyone that has to support the code. I would get away from submitting forms and use Ajax methods in your web client (using JQuery ajax) to get the data you need for this view and for update/insert/delete actions. This way you do not have to post back the whole page to perform actions that will probably take place on just portions of the view which will result in a better performing page and a better user experience. Change your controller to a ASP.NET Web API controller and make those methods a REST API that uses consistent URL naming convention and use HTTP verbs to indicate the type of action being performed. You will end up 3 methods that serve the 4 you have now and it could look something like this (they correspond to the same order listed in the question).
GET: /api/Role/15?InUse=True
DELETE: /api/Role/15
GET: /api/Role/15?InUse=False
POST: /api/Role
Your controller would look like this.
class RoleController : ApiController {
public List<Role> Get(int id, boolean InUse) { ... }
public void Delete(int id) { ... }
public void Post(List<Role> roles) { ... }
}
This maintains a clear separation of concerns while also keeping a consistent and understandable URL convention.

webapi aspnet 4 Architecture

I've project using Entity Framework 5 Code First, WebApi, ASPNET MVC 4, Repository and Unit of Work pattern, etc.
My architecture is as follows:
One project for the POCOS
One project with the context, Repository, Unit Of Work, etc
One project with the contracts (IRepository, IUnitOfWork, etc)
One WebApi project which holds ApiControllers for each entity of the model (GET, POST, PUT, DELETE).
Now, if I don't want to use SPA (as I don't have time right now to learn it) and I want to do something quick, What should I do? a new ASPNET MVC 4 project with Controllers inheriting from Controller rather than ApiController, and those controllers consuming the WebApi controllers?
Like this?
public ActionResult Index()
{
return View(WebApiProj.Uow.Houses.GetAll());
}
That doesn't seems to be quite good as it should be creating a Get pointing to the WebApi controller in the other project.
I'm thinking about this architecture, because mobile clients, web clients and any other clients would be calling the same services which sounds good.
Any advices on this architecture? Pros or cons?
I am not sure if what you show is possible? WebApiProj.Uow.Houses.GetAll() Is treating Houses as if it was a class with a static GetAll function on it. Houses is an instance class that needs to be instantiated per request and may/should have constructor injection concerns to handle too... GetAll would normally be an instance method.
Given you are in a situation where you are going to have multiple code clients i.e. the WebApi controllers and the MVC controllers you should consider adding a Service Layer to your project. http://martinfowler.com/eaaCatalog/serviceLayer.html.
Your Service Layer will probably take the form of a single class (if this is a small ish project but split it up if needed), it will have the Repositories and the Infrastructure code injected. You should end up with a series of CRUD and UseCase sounding method names that contain the orchestration logic between repositories, factories and unit of work classes.
public interface IMyServiceLayerClass
{
IEnumerable<House> GetAllHouses();
House SaveHouse(House house);
IEnumerable<Windows> GetAllHouseWindows(int houseId);
//etc
}
public class MyServiceLayerClass : IMyServiceLayerClass
{
private readonly IRepository<House> _houseRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly IRepositoryTypeB _repositoryTypeB;
Public MyServiceLayerClass(IUnitOfWork unitofwork, IRepository<House> houseRepository, IRepositoryTypeB repositoryTypeB)
{
//Populate the private readonly's
}
public IEnumerable<House> GetAllHouses()
{
return _houseRepository.GetAll();
}
Your two types of controller can then accept the Service class and have very thin logic just to forward on to the service layer.
public class HomeController : Controller
{
private readonly IMyServiceLayerClass _myServiceLayerClass;
public HomeController(IMyServiceLayerClass myServiceLayerClass)
{
_myServiceLayerClass= myServiceLayerClass;
}
public ViewResult Index()
{
return View(_myServiceLayerClass.GetAllHouses());
}
Same for the Api:
public class HouseController : ApiController
{
private readonly IMyServiceLayerClass _myServiceLayerClass;
public HouseController (IMyServiceLayerClass myServiceLayerClass)
{
_myServiceLayerClass= myServiceLayerClass;
}
public IEnumerable<House> Get()
{
return _myServiceLayerClass.GetAllHouses();
}
This will allow you to reuse the same business logic and orchestration across the controllers abstract the logic away from your WebApi and Mvc applications.
This code could easily live in your project that defines the contracts as it is only dependent upon interfaces. Or you could add its interface into contracts too and then create another project class Domain or Service which can hold the implementation of the service class.
I would strongly suggest you leave you Controllers to do what they do best and let them handle the delegation of the UI specific elements and re-factor non UI specific logic into a reusable service layer. This would allow Unit tests for controllers to focus on testing for the correct action result and status codes etc and allow your domain logic to be tested independently.
Take a look at my answer for another architecture question on MVC. The key for your question is to have an application or domain layer that both the MVC Controller and Web API Controllers can use to access the business model (The M in MVC). You do not want to call the Web API directly from the MVC Controller as it has overhead for serialization and de-serialization that is not required here. Instead call the application/domain layer directly.

asp.net mvc without entity framework

I am learning asp.net mvc and went through a great tutorial that demonstrated it. The tutorial also used Entity Framework.
We have our own data access class which I have to use.
I am a little bit confused as to what I need to do to bridge the gap between our class and MVC framework.
For example, in the tutorial, inside of MovieController.cs file, there is a Edit method, that looks like this:
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
If I don't use the Entity framework, what would it look like? Will I still need to use ModelState.IsValid and save the state like it's done
db.Entry(movie).State = EntityState.Modified;
Please advise. A clearly written example of using asp.net mvc without the use of Entity framework would be great.
What I need to know is what role does state play here and whether it is mandatory to use or is it just a part of how the Entity framework operates.
I would re-write this as:
[HttpPost]
public ActionResult Edit(Movie movie)
{
myDBObject.SaveChanges();
return RedirectToAction("Index");
}
Where myDBObject is my custom database access object.
The examples you see out there where controllers use directly some data access framework such as Entity Framework are bad examples. The whole internet is polluted with such stuff. I can hardly look at it without having my eyes hurt. I consider those as bad practices. Data access should be separated and abstracted in a repository. So for example:
public interface IMoviesRepository
{
Movie Get(int id);
void Save(Movie movie);
}
then you could have some implementation of this interface using plain ADO.NET, EF, NHibernate, a remote web service call, some custom ORM or really whatever:
public class MyCustomFrameworkMoviesRepository: IMoviesRepository
{
...
}
and the controller will take this repository interface as constructor argument:
public class MoviesController: Controller
{
private readonly IMoviesRepository _repository;
public MoviesController(IMoviesRepository repository)
{
_repository = repository;
}
public ActionResult Index(int id)
{
var movie = _repository.Get(id);
return View(movie);
}
[HttpPost]
public ActionResult Index(Movie movie)
{
if (!ModelState.IsValid)
{
return View(movie);
}
_repository.Save(movie);
return RedirectToAction("Success");
}
}
and the last part is to configure your dependency injection framework to pass the correct implementation of the repository into the controller. Now as you can see the way the data is fetched is completely decoupled from the controller logic. It is the way it should be. Always try to avoid the strong coupling between the different layers of your application.
And to answer your question about the State property : this is something completely specific to EF, seeing something like this in a controller is a really pity.
And to bring this even further and improve it you would introduce view models. View models are classes which are specifically designed to meet the requirements of a given view. So for example Movie is a domain model. Domain models should never be directly passed to views. Controller actions should never take domain models as action arguments. You should define view models which will contain only what is required by the given view and then perform the mapping between the view models and the domain models. Frameworks such as AutoMapper make this very simple.
hmm.
MVC and entity framework really have nothing to do with each other; they just work well together.
the if (ModelState.IsValid) validates your view model. If you are not using view objects with validators, it's a little pointless; if you are, then it's quite valuable.
inside the if (ModelState.IsValid) brackets, you would take the post data from your web page (usually a view model) and apply it to the object that will persist it to the database. EF is often used because once it's set up, it's fairly easy to maintain, and a lot less code to write.
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
are both EF-related. These would need to be replaced by your repository class methods and objects.
return RedirectToAction("Index");
is MVC. Upon successful persistence to your data store, return the control to the index page.
return View(movie);
is used to redirect back to the original view, because something failed validation.
You would still check ModelState.IsValid, but otherwise your code would look like what you have.
This assumes that your model has DataAnnotations attributes on it, though, which is what ModelState.IsValid is using to check. Those attributes can be used on any C# class' properties - not just Entity Framework.
You might end up creating specific view models for this purpose.
You need to make some connection between the Movie object (passed in on the http POST) and your database methods (myDBObject).
Maybe you want to say myDBObject.SaveChanges(movie) and assuming your db code knows how to handle the object Movie then you'll be fine.