Generic Web API controller - c#

I'm using Web API v2 and I have a handful of models that I need to do CRUD operations for. For example, I have an Allergy model and a Prescription model. In the application itself I have viewmodels which can turned into their appropriate models, but for simplicity's sake let's just say I take the model straight in the Web API controller.
So something like this:
public class PrescriptionsController
{
public HttpResponseMessage Put(Prescription model)
{
// saved to the DB
}
... (other CRUD operations)
}
I also have the same for the Allergy model:
public class AllergiesController
{
public HttpResponseMessage Put(Allergy model)
{
// saved to the DB
}
... (other CRUD operations)
}
Both models have different properties but are handled exactly the same way - in fact I have about 3 other models which are handled exactly the same way for each CRUD operation. I hate to do have 5 different endpoints that are basically copied and pasted code.
So my question is this:
Can I make a generic controller to handle all of these models? Something like MyCommonController<T>? (but with a better name of course!) Can the Web API handle the routing in that scenario? Is that even a good idea?

In the end I didn't try a generic controller. It seemed like it might be possible via jumping through some hoops with routing.
However, the fact that routing modifications to get this to work were so complicated it kind of negated the benefit I would get. I wanted to keep things simple. So I just created a generic base class instead:
class MyBaseController<TModel> : ApiController
{
public TModel Get(int id) { ... }
}
and had each type inherit from it:
class PrescriptionsController : MyBaseController<Prescription> { }
And that worked like charm, didn't have to mess with routing or anything. It makes it clear what's happening and is pretty maintainable.

Related

Mapping and querying the web api in service layer

I am making a web api and have created several classes, the class controller and the service as well as the dto and the model.
In the controller I have the methods for post and get and the business logic is in the service
My question is how can I make the queries from the model class and map the queries to the dto
Service Layer:
public class GermanyService : IGermanyService
{
public Task<IEnumerable<GermanyDto>> All()
{
throw new NotImplementedException();
}
public Task Create(GermanyDto germany)
{
throw new NotImplementedException();
}
}
Controller:
public class GermanyController
{
private readonly IGermanyService _germanyService;
public GermanyController(IGermanyService service)
{
_germanyService = service;
}
[HttpGet]
public async Task<IEnumerable<GermanyDto>> Get(int id)
{
return await _germanyService.All();
}
[HttpPost]
public async Task Post([FromBody]GermanyDto dto)
{
await _germanyService.Create(dto);
}
Okay :)
Use an interface implementation ->
seggregate your business logic's interfaces, so you have many of them, split into their single responsibilities and then join them in one:
Example
public interface IStreetName {
string StreetName{get;set;}
}
public interface IPostCode {
string PostCode {get;set;}
}
... other implementations for an Address DTO f.x.
then
public interface IAddress : IPostCode, IStreetName, ...
{
//should be empty
}
now you can Implement Iaddress on your DAL object, and not need an actual DTO -> because you ONLY reference the interface in your business logic.
etc.
Obviously, you would have to rename the intefaces for the properties on your "GermanyDTO", which I don't know what looks like.
EDIT:
Using mappers like "auto-mappers" or the like is usually a sign of 2 things.
1: You don't understand how to write effective mapping yourself.
2: Using a framework to accomplish something, doesn't absolve you from testing. And frameworks are notoriously difficult to test.
(Because, following proper procedure, you would have to test the interface between your code and the framework, and by extension the code between framework and 3rd part component, failing to do so, will setup you up for risks, between what you THINK the framwork does, and what it ACTUALLY does)
So Yes, using something like "Automapper" is at best a supression of a symptom rather than a cure.
Because the root cause is failing to understand how interfaces solve mappings.
And using a tool, to do something you can do cleaner yourself, and improve the structure of your entire system as a result? Is a no-brainer.
Just notice your own statement:
"Do you think it is effective? Automapper solves some of my issues"
You are seriously going to implement a direct dependency in your system, because of a framework?
You are admitting to writing bad code, because a framework can take away ... what? A little bit of boiler plate?

Generics or Inheritance for API request object

I know this might be an opinion-based question, but, I'd rather to ask as there might be some design principle for this.
I'm having a .net C# web API application to expose few APIs to retrieve some data from a database. I'm also using mediateR on this project. The APIs, they all get one request object but all of them have exact same properties. Imagine, we have a BaseProduct class from which ProductA, ProductB, and ProductChave been inherited in the domain project. Now, I need to expose APIs to return these three objects to the users. Here's an example of two of the request objects.
With Inheritance:
public abstract class BaseGetProductRequest { // the props here }
public class GetProductARequest : BaseGetProductRequest, IRequest<GetProductAResponse> { }
public class GetProductBRequest : BaseGetProductRequest, IRequest<GetProductBResponse> { }
public class GetProductAResponse { public ProductA[] Products {get; set;} }
Each of the above requests also has its own request handler class.
With using generics: (BaseProduct is a domain object class from which different product types are inherited)
public class GetProductRequest<TProductType> : IRequest<TProductType[]> where TProductType : BaseProductType { // all props in here }
Which will be used like this in an API:
public async Task<ProductA[]> Get([FromRoute] GetProductRequest<ProductA> request) { // API body }
So, the question is: Which one the following would be a better approach to take from a design point of view?
To take the Inheritance approach as above
Or to implement the requests and request handlers using generics so we'll end up with less files
Personally, I would prefer the first approach as I want to literally have separate request objects for each API, this way it looks cleaner to me besides that would be consistent with the rest of the code as well (as not all the request objects can be implemented generically). Besides, if by any chance in the future there is a need to add a type-specific property for a request object, then, our code will be more flexible with that change.
Is there like any specific design guidelines which recommends for example taking one over another? Thanks for your opinions in advance.
Sure the inheritance approach will give your project a higher performance, due to the re-usability of compiled requests

Best practice ASP.NET Controller for Common Actions

I have a quick question,
In so many examples I saw controller Actions which does not return any View or Partialview are also added in the same controller - Now in my situation i have multiple controllers which i need to run same ACTIONS such as
Controller A will Run Action A
Controller B will run Action A
Adding Action A in both Controller A and B does not look right.
As I am making [HttpPost] calls for Action A using AJAX, therefore, i want this to be in a Controller for easy POST access, although I don't want to add the same Action in both Controllers
I can add action A in Controller A and let Controller B access the same action requesting from Controller A instead but what I was thinking
**How about if I create a new Controller called
commonActionContoller
and put "ACTION A" in it and let everything use commonActionContoller when Action A is required?**
Cheers
EDIT: Example added as following
An example application which has Person and Countries, So Person model is the same for all Countries but we have different Controller for each country so If an Admin wants to update Person's model with field IsEmpoyed from true to false then they go to for example {USA}/Index controller and switch true to false. Now, this is same for {AUS}/Index and {China}/Index so Action which changes IsEmpyed to true/false is the same across all controllers. To make this work i don't want to add Action IsEmplyed to all country controllers - (Couldn't think of a better example) –
You should write Action A in both Controller. Otherwise it will violate Single responsibility principle. Best practice is to move the implementation codes from Controller to a Service layer. For example, if you want to load Product Category for Products and Sub-Categories, then code will be like this:
public interface ICategoryService
{
List<Category> LoadCategory();
}
public class CategoryService : ICategoryService
{
public List<Category> LoadCategory()
{
//code here
}
}
public class ProductController : Controller
{
private readonly ICategoryService _categoryService;
public ProductController()
{
_categoryService = <inject dependency here>;
}
public ActionResult GetCategory()
{
var category = _categoryService.LoadCategory();
}
}
public class SubCategoryController : Controller
{
private readonly ICategoryService _categoryService;
public SubCategoryController()
{
_categoryService = <inject dependency here>;
}
public ActionResult GetCategory()
{
var category = _categoryService.LoadCategory();
}
}
The guiding principle here should be Separation Of Concerns.
If ControllerA and ControllerB have specific business logic, and adding a CommonActions controller give shared data a good isolated home this is a good practice.
Without a better illustration of your needs though it's difficult to answer.
A slightly better example might be the order application:
InventoryController
EmployeeController
You probably don't want a CommomController with methods like:
GetStoreClosingHours(int storeNumber);
GetTotalSales(int employeeId);
GetEmployeeComps(int employeeId);
IoC and dependency injection might pay off as well depending on the actions. Where any controller could call methods like:
GetLastLogonTime(thisEmployee);
It's really a set of principles designing your application after all, and best practices aren't always super neatly packaged. I'd say most importantly choose something flexible, scalable and then stick with it.

MVC4 Ideal controller coding

I recieved an mvc4 application from my friend in which I will add some functions. but I found that he use controllers with more Than 6000 line of code.
I want to know what's the ideal way to develop MVC4 application.
means to have many controllers with little number of line code in each one. or to have little number of controllers with big number of line code.
I don't think there's a 'right' answer to this, especially without any concrete examples.
Just think about maintainability going forward. A monolithic controller with multiple thousands of lines of code is likely to be much more difficult to understand (and therefore maintain) than a smaller, more targeted controller.
Also I would look carefully at the kind code that goes into your controller. The controller is there to link your models to your views and is not the best place for business logic code; I would personally put any significant business logic into some kind of repository that the controller references.
There definitely isn't a generic solution to this problem, however you can reduce the number of “lines” within a controller by using repositories which will also enable you to make use of the dependency injection pattern.
Dependency injection will also help with unit testing. The repository separates the logic into a separate (replaceable) class.
Searching these terms will provide lots of information (unfortunately far too much to put all the information in a SO question) – but here is some code that will help you in the right direction:
Create an interface to define the repository
public interface IGenericControllerRepository
{
MyModel[] ComplexMethod();
}
Controller class:
public class GenericController : Controller
{
private IGenericControllerRepository repository;
public GenericController() : this(new GenericRepository()) { }
public GenericController(IGenericControllerRepository genericRepository)
{
this.repository = genericRepository;
}
// GET: /controller
public ActionResult Index()
{
MyModel[] m = repository.ComplexMethod();
return View("Index", m);
}
}
Repository Class
public class GenericRepository : IGenericControllerRepository
{
public MyModel[] ComplexMethod()
{
// do work here
}
}
It is hard to judge if you should split your controller into smaller ones as that really depends on the number of methods rather than the number of lines ( for example you could have a few methods with hundreds of lines ) in which case separating them into another controller won’t achieve a desired outcome. Your controllers should be split into “application logical” containers.
I think your friend maybe put the business logic into the controllers. You should put the business logic to other class, folder or projects.

What is the purpose of ASP.NET MVC Generic Controller

I am newbie in asp.net mvc. I heard the word ASP.NET MVC generic controller, can anyone easily explain what it is? I have worked with the default controller before but now I want to able to visualize the kind of purpose ASP.NET MVC generic controller does. It will be very helpful if some one can explain the situations when a developer has to think about using ASP.NET MVC generic controller. Concepts and code about how to implement it will be greatly appreciated. Thanks
You usually create a generic class to abstract away operations you can perform on a range of types, for example Entity Framework models containing an ID. In that case you can move all duplicate code into a base class.
For an MVC controller, a generic base controller may look like this:
public abstract class GenericController<T>
where T : class
{
public virtual ActionResult Details(int id)
{
var model = _repository.Set<T>().Find(id);
return View(model);
}
}
And an implementation like this:
public class FooController : GenericController<Foo>
{
}
Now when someone requests /Foo/Details/42, the entitiy is pulled from the _repository's Set<Foo>(), without having to write anything for that in the FooController.
This way you can create a basic "CRUD" controller that lets you easily extend your application with Create, Read, Update and Delete operations for new models.

Categories