MVC4 Ideal controller coding - c#

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.

Related

Why inject the entire DbContext instead of just the necessary DbSets?

I've seen a lot of projects whether the entire DbContext is injected in a class:
public class MyClass
{
public MyClass(MyDbContext context)
{
...
}
public void DoStuff()
{
dbContext.MyTable.Select(x => x...)
}
}
Why not do this:
public class MyClass
{
public MyClass(DbSet<MyType> myTypes)
{
...
}
public void DoStuff()
{
myTypes.Select(x => x...)
}
}
I find #2 makes it more clear as to what data exactly the object needs to operate. It makes unit testing especially more clear as the dependencies are obvious from the constructor. Otherwise, you have to inspect the implementation of the method to find out what data it needs exactly so you can setup your test properly.
So why is #1 the norm?
(P.S. sorry for bad tags but it seems the tag system is broken atm)
Normally developers write unit tests to test business use cases and the data access layer should not contain any logic and that's why people use Repository Pattern to hide the implementation of the data access layer.
Otherwise, you have to inspect the implementation of the method to
find out what data it needs exactly so you can setup your test
properly.
MyDbContext and DbSet<MyType> are related to data access and when you try to implement unit tests for DoStuff method, you should not consider the implementation of query for writing test and the only thing you need is mocking MyDbContext or DbSet<MyType>. Also when use concrete class as a dependency, you violate Dependency Inversion Principle, and that is why you have to look at the implementation of DoStuff method to find out what data and where the data comes from.
Because the "Save" is on the dbcontext, not the child collections.
"SaveChangesAsync" as the most important one. But others listed below.
int saveChangesAsyncValue = await this.myDbContext.SaveChangesAsync(token);
Framework:
https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext.savechangesasync?view=entity-framework-6.2.0
Core:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.savechangesasync?view=efcore-5.0
Others (core):
https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.savechanges?view=efcore-5.0
You should really focus having unit tests on your BUSINESS LOGIC. And subtly, this also means.
Stop putting (any) business logic in your data layer. (and its kissing cousin, stop putting business logic in your presentation layer).
You should inject a (mock) of your datalayer into your business logic classes.
Having said that, EF InMemoryDatabase has blurred the lines a little bit.
But that does not avoid having to have the "myDbContext" available.

How should I instantiate multiple instances of a single class with .net core DI?

I'm new to Dependency Injection, and so in trying to implement it in my .net core 3.0 projects, I've run into a scenario where I need multiple instances of a single service registered in my Service Provider. As a workaround, I've resorted to injecting the IServiceProvider itself and just calling GetRequiredService<T> (of transient-scoped services) multiple times. That works, but appears to be an anti-pattern, and I'm not sure how I'm supposed to do it properly.
Part of the problem in researching this further is the insistence in every answer that the need for multiple instances of a single class is itself code smell, but as an example, let's say I'm providing instructions to an oven to automate the baking process. A user will define the temperatures and times for each recipe in a view, then the view will return a List<string> that represents that list of steps to the controller. A sample list of steps might look like:
//Bake for 500 degrees Fahrenheit for 30 minutes, then 225F for another 90
["500F,30","225F,90"]
I will then need to convert that to a List<CookingStep> in the controller to add to my Recipe object. I've been doing something like this:
IOven Oven;
IRecipe newRecipe;
IServiceProvider sp;
//public OvenController... (constructor with dependencies injected here)
public async Task<IActionResult> BakeSomething(List<string> steps)
{
foreach(string s in steps)
{
IRecipeStep recipeStep = sp.GetRequiredService<IRecipeStep>();
recipeStep.ParseTimeAndTemperatureFromString(s);
newRecipe.Steps.Add(recipeStep);
}
await Oven.Bake(newRecipe);
return View("RecipeComplete",newRecipe);
}
But that isn't really inversion of control and it doesn't make the code any more testable, so in researching best practices, I could do a factory pattern, but I'm not sure how that helps do anything but bury the ultimate instantiation in a different class.
So I can make a factory, even a generic one, but is this (admittedly overly simplistic example) really better than the service locator pattern above?
IOven Oven;
IRecipe newRecipe;
IRecipeStepFactory rsFactory;
//public OvenController... (constructor with dependencies injected here)
public async Task<IActionResult> BakeSomething(List<string> steps)
{
foreach(string s in steps)
{
IRecipeStep recipeStep = rsFactory.NewStepFromString(s);
newRecipe.Steps.Add(recipeStep);
}
await Oven.Bake(newRecipe);
return View("RecipeComplete",newRecipe);
}
public class RecipeStepFactory : IRecipeStepFactory
{
public IRecipeStep NewStepFromString(string s)
{
RecipeStep recipeStep = new RecipeStep();
recipeStep.ParseTimeAndTemperatureFromString(s);
return recipeStep;
}
}
(I apologize in advance for any issues with the presentation or substance of my question, it's the first time I've had to ask a question of my own)
Yes, the factory is better. Another approach is defining a delegate like this:
public delegate IRecipeStep RecipeStepFactory(string steps);
and then registering it like so (Func<string, RecipeService> would also work, but a delegate is cleaner):
services.AddTransient<RecipeStepFactory>(sp =>
{
// resolve any services you need from the resolved IServiceProvider below
// since you don't need any in this case, I've commented it out
// IServiceProvider provider = sp.GetRequiredService<IServiceProvider>();
return s =>
{
RecipeStep step = new RecipeStep();
step.ParseTimeAndTemperatureFromString(s);
return step;
};
});
Then you can inject it:
private readonly RecipeStepFactory _recipeStepFactory;
public OvenController(RecipeStepFactory recipeStepFactory)
{
_recipeStepFactory = recipeStepFactory;
}
public async Task<IActionResult> BakeSomething(List<string> steps)
{
foreach(string s in steps)
{
IRecipeStep recipeStep = _recipeStepFactory(s);
newRecipe.Steps.Add(recipeStep);
}
await Oven.Bake(newRecipe);
return View("RecipeComplete",newRecipe);
}
I like this approach because it keeps everything in my composition root, but depending on the complexity of the factory, your current approach may be better. Personally, I'm using both approaches.
I actually use Autofac (a different DI container) for this, because I can just define the delegate in the service I'm declaring and Autofac automatically wires it up (see delegate factories) but obviously Autofac is probably more than what's needed for small projects, so unless you need it, you can use the pattern above.
IMHO, and with my experience, i would lean towards factory pattern (based on what i have understood and your above problem stmt/example only).
And that way, the controller doesnt know the actual implementation of the ReceipeFactory. In future if the receipe factory adds more different implementation or extensions, your controller wont be requiring a change. At all times, it would get the REceipeStep from the factory and send it to oven to bake.
you may want to learn and explore about Clean code architecture and that may be elaborate but would be wider to understand the different patterns and features for every problem statement.
One such that i'd love is available on youtube. and another (if you have Pluralsight account) at here.
These are my personal suggestions only. I hope based on this learning and knowledge, this may vary based on a realworld problem and solutions.

ASP.NET Core and ViewModelFactory

Hello, I'm trying to implement a ViewModelFactory "pattern" and I was wondering what's the best way to achieve it, considering the constraints of the current IoC container.
public class UserCreateViewModelFactory
{
private readonly DbContext db;
public UserCreateViewModelFactory(DbContext db){ this.db = db;}
public void Create(CreateUserViewModel viewModel)
{
//Creates the user
}
}
I have the above class easily injected into my controllers ctor. The head ache will come when I need more ViewModelBuilders, So I want to avoid two things:
Bloat ctor with injections
Bloat container with registrations
I want to be able to inject an IViewModelFactory on my controller and then using it like this:
[HttpGet]
public IActionResult GetUsers(int id)
{
return View(viewModelFactory.Build<GetUserViewModel>(id));
}
Notice that on calling Build(T) it has to call the correct IViewModelFactory implementation.
I know that StructureMap container support binding the concrete implementations to the corresponding interface but I'm trying to come up with a solution without having to add another dependecy to the project.
I think if you have builders for building viewmodels, then factory is extra layer of abstraction which simply can be dropped off.
Because you know the type of created viewmodel at compile time you can just inject a builder you need to the controller constructor.
If your controller create a lot of viewmodels and you end up with a lot of builders you need to inject - this can be considered as a sign of violation of Single Responsibility Principle. In that case you need to separate logic of controller to different controllers.
So I want to avoid two things:
Bloat ctor with injections
Separate class with bloated constructor to another classes with more specific responsibility which takes smaller amount of dependencies.
Or wrap dependencies with one or two, three classes based on their relation
Bloat container with registrations
This cannot be a problem, because dependency containers is usually designed to register whole "object graph" of your application
After sometime researching, I finally came up with a good solution for the this problem.
The solution is basically extending the default IoC capabilities through an IServiceCollection.ConnectImplementations() extension method.
During registration I'll search my concrete classes and connect them with its respective interfaces (like other containers). Then I use a Mediator/Proxy that has IServiceCollection injected and knows which concrete class should be building the view model.
The full solution is better explained by this gist I've created.

Autofac, dynamic dependency Injection for MVC controllers

I have a project setup with UnitOfWork Interfaces and Managers. All this works well while I just had to use an accountMananger for the base of my controller.
protected BaseController(IAccountManager acctManager)
{
_accountManager = acctManager;
}
and my controllers are created like this, and works.
public class AccountController : BaseController
{
public AccountController(IAccountManager accountManager)
: base(accountManager)
{
}
Now I am creating other business managers and I realise that by the end of the project my BaseController constructor is going to be huge or I am going to have a load of various signatures based on the controller I am on. And if I forgot something and needed another manager and changes one constructor, all the other controllers need to also change.
I mean, I actually ALWAYS want accountManager to be injected/resolved in the base. Can I do that? Since I am 99% checking for authorisation.
I have read about ControllerFactories but also somebody mentioned to implement IDependancyResolver , but no example, which is his preferred way to do it.
I can see this becoming a big burden to create constructors based on the controllers I need, which I dont have yet.
Can any body give me an example of how to easily access my managers in the base, as I need them. I mean, they all created and ready to be resolved anyway.. so why the heck do I need to pass them in such a strange way anyway?
Sorry. Just learning about DI and this is from a good tutorial but as you can see lacking some further explanation.
What you have with your account manager is called a Cross-Cutting Concern. There are a few different ways to skin this cat, but you should avoid injecting the same dependency into every controller.
In general, it is also better to avoid inheritance because that will cause tight coupling between your classes. The tight coupling is obvious here - what if you needed a controller that didn't have IAccountManager as a dependency later?
In this particular case, there is already a built-in loosely coupled authorization framework in MVC that you can utilize - the AuthorizeAttribute, which is the normal way of handling access to your controller action methods.
[Authorize]
public class AccountController : Controller
{
public AccountController () { . . . }
[AllowAnonymous]
public ActionResult Register() { . . . }
public ActionResult Manage() { . . . }
public ActionResult LogOff() { . . . }
}
There are also several other options for implementing cross-cutting concerns - implementing IActionFilter - see this for a DI friendly example, interception (which some DI containers support), using the Decorator Pattern, and putting the dependencies in ambient context (such as HttpContext.Items).
I can see this becoming a big burden to create constructors based on the controllers I need, which I dont have yet.
This is why you should inherit DefaultControllerFactory and provide it with the one instance of your DI container at application startup (in the composition root). It is typically the container's responsibility to provide the dependencies to your controllers, especially if your application is large.
public class AutofacControllerFactory
: DefaultControllerFactory
{
private readonly IContainer container;
public InjectableControllerFactory(IContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
this.container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (requestContext.HttpContext.Request.Url.ToString().EndsWith("favicon.ico"))
return null;
return controllerType == null ?
base.GetControllerInstance(requestContext, controllerType) :
this.container.Resolve(controllerType) as IController;
}
}
I strongly recommend you read the book Dependency Injection in .NET. DI is one of the most misunderstood concepts in software development, and it is well worth the investment of studying the topic in detail on its own without having to sift through the misinformation on the Internet. There are many benefits to be gained by proper use of DI, but improper usage is often worse than not using DI at all.

Generic Web API controller

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.

Categories