I know it's a very basic questions but I'm just a newbie in C#. I know the default access modifier for class in C# is "internal" which means available in the same assembly. But let's say I have two public(more accessibility) class Employee and Departments in models, so they don't need to reference each other, fair enough. But I also a DepartmentController and EmployeeController in the controllers, and I need to reference class Employee and Departments, but aren't DepartmentController, EmployeeController Employee and Departments in the same assembly which is the project name?
This is the picture of the program:
You need to reference those classes because they aren't in the same namespace (MVCDemo. Controller!= MVCDemo. Models). If you import those classes to the scope of another project by importing their assembly, you are going to be able to see only the public classes, not the internals. I highly recommend that you try to move the models to a Class Library Project and play with their access modifiers to understand their scope implication better (Like trying to import an internal class withing another assembly).
Yes, your solution has a single project, and there's a single assembly for your project.
The reason why the you need public access modifiers on your controllers is explained here...
Why does the ASP.NET MVC Controller class need to be public?
Basically the MVC framework you're referencing needs access to the controllers in order for them to be used by the framework, if they're internal the MVC framework would not be able to access your controllers.
Whilst there's a single project in your solution, you're referencing many other assemblies. Anything within a project that needs to be accessed by another assembly, be it an assembly created from one of your projects or an assembly you're referencing, needs to have the Public access modifier.
Related
I am trying to create a new asp.net core web application using Razor pages. I want to add my db context in the startup.cs file, but I am using something called IDesign.
My DbContext entity is in a project that I am not allowed to reference. I need to somehow add my context either at the accessor layer or something else. I'm not super familiar with how services work for .net core.
I have a solution set up like this:
Clients Project
The project with the cshtml files, startupcs and all of that is here
Can only reference managers and utilities projects
Managers Project
Used for chaining calls to engines/accessors to accomplish tasks at a high level
Used to make calls to accessors
Can only reference accessors, engines, and utilities project
Engines Project
Used for business logic
Can only reference the accessors and utilities projects
Accessors Project
resource accessors. Hits dbs/services.
This is where my dbcontext class lives
can't reference anything except for utilities
Utilities Project
Used to store global classes and utility functions that apply to all projects
Can't reference anything
My problem is that if my DbContext lives in the accessors project, how do I pass that up from the managers so that I can use it in the clients? Has anyone had experience with this before?
Just to reiterate, I know that I could easily reference accessors project in the clients project and use the dbcontext from there. My problem is that I want to avoid being able to reference accessors so that other people who are working with this code aren't able to see any accessors classes.
You can add the DbContext related classes in a new project without the parts of the "Accessors" project. It will be similar to the "Utilities" project, which can be used/referenced by all projects. This way your "Clients" project knows what a DbContext object is and how to use it, but it doesn't know how to get one (unless it has a connection string and connects to the database directly using the DbContext class). This would be the responsible of the "Managers" or "Accessors" project.
The references chain will look like this:
I am working on a WPF project using MVVM pattern. In solution, I have viewmodels,models,views and properties.As per requirment, I need to access the same classes(view models, models, properties) from another class library in same project. I do not want to add the reference to the class library as it is an exe file and a heavy component which has got so many classes which i do not require. So, is there any solution for this. How can i access same classes(view model,model,propeties) in a solution from another class library in same project?
Thanks & Regards
You have two choices. First one, is to refactor your exe in order to extract the reusable classes to a separate dll. Then, just add a reference to this new dll.
The other is to use reflection to access the members of the exe, which is the worst option, even worse than simply adding a reference to the big old exe.
I suggest breaking down your solution further in more projects, For example separate projects for Model, View and ViewModel or perhaps breaking down even further and then add reference only to the library you need. That way you are not exposing everything.
The other option is reflection which may be cumbersome to use and make your code ugly.
In my .NET solution, I have two projects: one main project and a project for running tests against the main project. In my project, I have several methods that I'd like to keep "private", but would also like to run tests for. Is there an access method that could limit these functions to just inside of my solution?
You are looking for the InternalsVisibleTo attribute.
This attributes lets you specify other assemblies that should have access to types and methods that are internal to your assembly. So, in your main project AssemblyInfo.cs file (or any other source file), you can specify that your test project is a 'friend assembly' and should have access to the internals of your main project:
[assembly:InternalsVisibleTo("MainProject.Tests")]
On a side note, as pointed out by Alexei, if your MainProject is signed with a strong name key, any 'friend' assembly must also be signed. This is explained here
Although, as mentioned in another comment. Best practice is to test your assembly by using its public API.
You can use InternalsVisibleTo attribute to make internal types and methods visible to selected assemblies.
However, you should try to design your API so that it can be tested using only the public interface.
You should seriously think back about the architecture of your solution. This is a smell that often shows that your class does too much things at once.
A simple fix is to extract this responsibility (those private methods) to another class where they then become public and are testable out of the box...
No, there is no way to limit access to "just solution".
The reason is solution is simply group of projects. One project can be in any number of solutions. So even if you "limit" access to projects included in one solution you/someone else can create another solution that somehow will need to magically get access to methods.
Additionally built assembly does not include any information on what solution it was part of - so there is no information at run time to check access.
To you particular problem - InternalsVisibleTo (as shown in other answers) will give access to internal methods to projects you allow (requires strongly signed assemblies) or refactor your code to avoid need for testing private methods.
I have an idea I'd like to implement which basically involves separating the controllers in an MVC4 Project to 2 different projects. The reason being I'd like to be able to have different controllers for an internal admin section of my site and for the external client section. I'd like to make changes to each of them individually and add a new DLL to the website as I make changes...the changes to the internal admin section of the site thus not affecting the controllers DLL for the external client section for example.
Does anyone know if this is possible/advisable or of a better way to accomplish what I'm trying to achieve?
taken from an artical :
"The MVC framework provides a default controller factory (aptly named DefaultControllerFactory) that will search through all the assemblies in an appdomain looking for all types that implement IController and whose name ends with "Controller." Thus, if you tell the factory to look for a "Home" controller, the factory can return a newly instantiated instance of a HomeController class regardless of the namespace or assembly it lives in—as long as it implements IController...."
by adding a reference to another project in you'r solution you can achieve what you are looking for, in that referenced project add you'r controllers. like written above the MVC Routing will find all controllers that been referenced in that solution.
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.