C# IoC Project Structure Standards - c#

What is the recommended folder structure for a IoC C# project? For a MVVM project, the standard is to create folders named Views and ViewModels (and where do you put interfaces and unit testing classes?)
What about a DLL project, that has no views, but exposes many classes to be created via IoC, which folders should be in my project?
Also as I'm starting to refactor code into IoC, I'm running into issues with the SettingsFile class that contains data that is serialized into a file. It contains a few methods:
void SetDefaultValues()
SettingsFile Load()
void Save()
string Validate()
SettingsFile Copy()
The main issue is with Load, as deserializing the object creates a new hard instance of the class, bypassing the principles of IoC. What's the right way of handling the scenario?
I'm thinking of moving all code outside of that class so that this class is only responsible for being serialized/deserialized without any code, and then excluding it from IoC. Is this the right thing to do? It's a similar problem when using Entity Framework and using any auto-generated table classes.
Thanks

The answer is to separate data classes from behavior classes. SettingsFile, as well as any EntityFramework class, contain purely data. Dependency Injection via IoC applies only to behaviors classes.

Related

Where should I put common utility methods in an Asp.Net Core MVC-project?

I currently have all my common utility function methods in a base controller, which all of my controllers inherits from. These are methods for functionality like uploading files, resizing pictures, deleting files, sending e-mails, generating random passwords, hashing passwords, etc.
What is the recommended structure for these kinds of things?
In that case you shouldn't put all these utility functions inside your base controller. You will face a lot of problems if your project grows. Changes and testing of these methods can become difficult, all your inherited classes need to use the same utility methods, etc. Have a look at Composition over inheritance to see another approach.
Somethimes I tend to organize my projects in the following manner if that might help you:
Simple helper methods: Create a folder and a namespace (e.g. namespace [...].Common") inside your web project and put one or more public static classes inside it (e.g. class "FileHelper.cs", "StringHelper.cs", etc). If you need one of these methods in a controller action simply put a "using ...Common" statement at the top of your controller class and call e.g. FileHelper.MethodName.
If I can define a closed subject area with a group of methods I try to encapsulate these methods in a service class (maybe even outside the web project if I have a feeling that I might need this functionality in other projects too), define an interface for that class and plug that functionality into controller classes by using dependency injection. If you don't know about that concept you should definitely read Dependency injection in ASP.NET Core. Dependency injection is a vastly used major concept in ASP.NET Core projects that brings you a lot of advantages and - if used correctly - stears your work into well-organized projects.
More complex organizations are always possible depending on your needs. Have a look at multitier, hexagonal or onion architecture if your projects grow.

Register the DbContext in my repository instead of the WebApi

I have a question regarding the repository and service pattern in combination with ASP.NET Core and EF Core. I'm in the stage of learning all of this, so I might miss the clear picture fully in front of me right now.
My current project structure looks as follows:
Project.Repository.Contracts
Project.Repository.EF
Project.Repository.FakeData
Project.Service.Contracts
Project.Service
Project.WebAPI
WebApp
In my understanding of the repository pattern, only the Project.Repository.EF project does know about EntityFramework.
But all "Repository, Service, ASP, EF" examples register the DbContext in the ConfigureService method in the WebAPI. By calling services.AddDbContext.
Isn't this a break of the concept?
I want to avoid to have the EntityFramework dependency in my WebApi.
So my question is, how can i archieve this?
This is my code so far:
WebApp.Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
Project.WebApi.Module.ConfigureServices(services);
services.AddAutoMapper();
}
}
Project.WebAPI.Module.cs
public class Module
{
public static void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IProjectService, ProjectService>();
services.AddSingleton<IProjectRepository, ProjectRepositoryEF>();
}
}
The Service and Repository are just stubs at the moment.
So again, what I want to avoid is, that I have to call services.AddDbContext in my Project.WebAPI.Module.cs class.
What I want to, is to register the DbContext in my Project.Repository.EF Project without hardcoupling it with my WebAPI.
Is this even possible?
Ok so let me make it a bit clearer for you.
The Repository pattern is more than just a data access layer that does some CRUD operations but I will try to limit my answer just to your problem to help you understand it.
(Keep in mind that the answer below is only relevant if you have a need to use repositories)
First lets talk a bit the naming of your projects.
The project Project.Repository.Contracts should be renamed to Project.Repository.DTOs to make it clearer.
This project contains Data Transfer Objects which is what your DataContext will use to generate your db and handle all the operations.
Then the Project.Service.Contracts can be renamed to Project.Domain in which you will have all your business logic related models.
Automapper will be used to do the two way mapping from dtos to domain objects and vice versa.
Now we will have to split your Project.Repository.EF project to two different projects.
You see, the repositories only need to know about the data context. EF doesn't need to know about the repositories.
So from the Project.Repository.EF project you will create Project.Data and Project.Repository
Your migrations and data context itself is in the Data project while the repositories are in the Repository project which references the Data project.
Now the Data project can be refered in the API project in order to be used in the startup class and as long as the services only know about the repositories project (and the web project only about services), you should be fine.
I would also make an extension method in the Data project instead of a static call like this Project.WebApi.Module.ConfigureServices(services);. It's cleaner.
You can also have your Startup class in a shared project between the dependencies and reference this single project on the project from which you start the host as well. Keep in mind that both DbContext, Services and repositories need to be configured at the IoC somehow. My cuppa is to create assembly markers and use Scrutor to scan for these dependencies.
EDIT: As Camilo suggested however, there's absolutely no need for a repository pattern in Entity Framework Core. EF Core is based on interfaces so you can implement your own classes around them.
The main reason why you would need a repository on top of EF was mocking.
This is no longer needed because:
In memory database built-in into EF Core
Is based on interfaces so you can implement your own classes around them
This may not be the best answer or the one you're looking for, but I hope it helps.
Isn't this a break of the concept?
From an idealistic view, perhaps. The important portion that you're separating out into another project(s) is the implementation of your repository, the setup of your context (mappings, etc).
The value in that is two-fold (at least):
You can reuse these in other projects
You can switch them out with a different implementation (with a matching interface) within the same WebAPI project. For instance, if you were supporting a legacy database and a new database.
Is this even possible?
Possibly with extra work and complexity, but is it practical? IME, I haven't seen a situation where it would improve the readability and maintainability of the code.
The question I would ask is, Am I going to need to dynamically choose between EF and a completely different repository type (such as Dapper, NHibernate, etc)? If the answer is no, or even not in the near future, I wouldn't add to the complexity.
As my grandmother used to say, "Don't borrow trouble." If you do need to completely switch to a different repository framework / ORM down the road, switching out the lines in ConfigureServices will be trivial. It's only complicated if you need to support two or more at once.

Create a global method to call in MVC project

I am pretty new to MVC and I am currently working on an MVC 3 project in visual studio and I want to create a method or variable that is accessible globally. When I say globally I mean available in my web project, service layer project, and data layer project.
I guess when I say global I mean global to the entire solution.
I tried creating a class in the solution items folder and referencing in my web project but its not letting me add a reference to the class since it is not a DLL.
I am a little confused with how to do this. Any suggestion would be appreciated. Also keep in mind that though I am a programmer I am still somewhat new to MVC and programming.
Edit: I have also tried adding a method in the global.asax file but was unable to call it
You should create a shared assembly where you define the class. You can then add a reference to the shared assembly from all projects that need the feature.
The class that you want to be "global" sounds like some sort of service. I suppose this is the kind of thing you may want to do with a logging service for example.
Using a logging service as an example it is generally best practice for the interface to the logging service be defined in a lightweight contracts type assembly. Then any of your assemblies that require an implementation of ILoggingService should inject the necessary implementation using an IoC container such as Autofac or MEF.
This pattern is pretty common and allows you to share common services while keeping implementations loosely coupled. Also this pattern will lead to highly testable code as fake implementations can be injected with Moq

How to organize interfaces and implementations in WPF MVVM application

I'm working on WPF MVVM project which contains following projects,
Domain,
ViewModels,
Infrastructure,
Views
and for example I need IFileService that provide some operations with file and doesn't contains any business logic, I'm sure that the implementation of this interface FileService will be in Infrastructure project, but I have question where to put the IFileService interface
I need to use this interface in ViewModels project, if I will put it in this projects its mean that Infrastructure will have reference on ViewModels that is not good I think, if I will put it in Domain which contains business related classes the same.
Help me what is the best to organize structure and references between projects and where to put interfaces like IFileService?
Hmm, why not creating an additional project like DAL or DataLayer? It provides the model classes, which I'm also missing in your listing. You could also put the interface IFileService there although I would prefer working with DataProviders or Repositories (that's my prefered option), so that the VMs are not aware from where the data was loaded.
IMHO The project Infrastructure shouldn't not contain any sofisticated logic. I would put some useful methods and classes there and keep it as simple and clean as possible, so that it could be referenced everywhere. Probably, you won't even need it.
The unique rule I use for my MVVM project is, all projects have a reference to my Infrastructure project and my Infrastructure project has no reference to my other project.
So IMHO, IFileService, and interfaces in general, should be in the Infrastructure project. Then it is up to you decide where to put the implementation. The Infrastructure project usually has very basic logic implementation and final implementation goes to a dedicated project.
The only exception I sometimes add to this rule is when I base my development on an existing MVVM framework, then Infrastructure might reference it too but I try to avoid this approach.
You should put the IFileService interface to Infrastructure project. because this will make it available to every project as this is the core project right. and you might have diffrent implemantations e.g. syncronious file reader and asyncronius file reader. so the implemantation could go into your modules or ViewModels.

Resolving Circular References (C#)

I'm having a couple of problems with circular reference/dependency that I've been sitting on all day. Something must be wrong with my thought process, I just don't get it.
Here are my projects:
Flip.Main (ASP.NET MVC)
Flip.Domain (C# DLL)
Flip.Services (C# DLL)
Flip.Utility (C# DLL)
Current References/Dependencies:
Flip.Main -> Flip.Domain, Flip.Services, Flip.Utility
Flip.Services -> Flip.Domain, Flip.Utility
Flip.Domain -> Flip.Utility
I wanted to structure my project in a way that my services project has all services, my domain project the model, repository and 'fluent' extensions to query the model, and the main and utility project are pretty much self explanatory.
Problems encountered:
1) I have an EmailService in my Flip.Services project, which needs to send out localized emails. All localization is done in Flip.Main's App_GlobalResources. No idea how to get the strongly typed emails and other localized resources now to my service layer as Flip.Main already depends on the service layer and therefore I can have it depend back to the Main project.
2) I have business classes, e.g. CustomerSearchFilter which represents a strongly typed search query. I want those business classes outside of the Flip.Domain project because they are not part of the domain model. However, in my CustomerSearchFilter class I have domain class instances (e.g. CustomerGroup) so it needs to know about domain classes. At the same time my Fluent interface in my Flip.Domain project needs to know what CustomerSearchFilter is so I can apply it to my IQueryable interface. Circular reference again.
3) I have a custom [AuthorizeSessionState] attribute which I use to decorate specific controller actions in my ASP.NET MVC Flip.Main project. This is an ActionFilterAttribute which needs to instantiate my SessionService who resides in my Flip.Services project. I can't put this into my Utility class though (because Flip.Services already references Flip.Utility). I don't think they should be in Flip.Main either - do I have to make another project for this!?
(20 more)
I feel like I'm making a mistake somewhere down the line, especially when I read that others usually don't encounter circular reference problems. Help?
Use interfaces for all non-trivial classes. Place interfaces in a different assembly from implementation.
The question comes down to what you separate by namespace and what you separate by DLL. If you have a good reason to keep EVERYTHING modular, you have to work really hard. But if each of these dlls only have a class or two in them, perhaps you could merge them together?
Take a few minutes and sort out the procedures ... create an identifier for each project (FM, FS, FD, FU). List each publicly accessible procedure on a page and then add an identifier for a project, if that project uses the procedure ...
Then you can see which procedure needs to be in (or accessible to) which project.
Hope that helps!
You can put your localized email strings in Flip.Services. The downside is that you have two places to maintain localized resources. You can also have a separate dll for all your resources to minimize the place to edit resources.
You have to move the fluent interface to an other dll or make CustomerSearchFilter part of the domain.
You will need to add more projects or rearrange your structure and use namespaces to create the separation.
It sounds like your building on concrete implementations instead of interfaces/contracts. As Ima suggests define interfaces that describe what a certain class should be able to do. Use this interface when you declare properties, parameters and the like. Keep the interfaces separate from the implementaion and both the implementation and the projects that uses the interface can reference the interface project.
You then get the nice option of using dependency injection making your code easier to test as an a side
In the "tiers" of a domain, repositories and services live at the same logical level, above the domain in an infrastructure role. I would suggest moving your repository implementations (queries, etc.) outside of the domain itself. That solves #2 at least.

Categories

Resources