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.
Related
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
Just a quick question, when you create a new controller for a new MVC ASP.Net app how does it know which controller to use. More specifically, given you create a new controller and you call it SockController in order to use said controller I would navigate to http://mywebapp/sock. How did the web app know that /Sock/ is linked to SockController? Is there a mapping somewhere ? Or if not what happens when if you call omit controller from the name when creating it, ie call it SockCont.
Note: I am not a Web Dev im just curious so please don't post links to page with tons of text, im looking for a short simple answer.
ASP.NET Routing extracts the name of the controller from the URL by getting the Route Value and then appending "Controller" to the end. So "/home/" returns "HomeController".
ASP.NET then uses reflection to go through every class in the project's assembly (or referenced assemblies) to find a class that inherits from System.Web.Mvc.Controller and is called "HomeController". It then uses the default, parameterless constructor to create an instance of it.
It then matches the Route action to a method of the controller.
This process is called "Dispatch" and similar patterns are seen in PHP, Ruby-on-Rails, etc, except that dynamic languages like those have different ways of resolving class names to actual objects (CakePHP uses Class auto-loading bindings to locate the class definition, for example).
I am new to ASP.NET. I have a general idea with ASP.NET on how to create a web application? But Here, I am asking the question because I want to apply best practice for my coding. So, I want to separate conceptual layers, for example, I want to create function which check session on page_load, if its empty than redirect to default page. I can do this by copy-paste to each new page.but I would like to call function rather than doing Copy/Paste.
I am thinking of creating library for Data Access as well as to connect and do data manipulations. Is it possible?
I just found this article from googling : Application Archi...
Can I use this concept?
Correct. For the Data Access Layer, you can create a ClassLibrary Project and add the compiled dll as a reference to your WebApplication project.
Here is a MSDN Link with the steps on how to do this.
NOTE:
But ideally you can have another ClassLibrary Project for Business Logic Layer, where you can reference your Data Access Layer dll; and then you can add the Business Logic Layer dll to your Web Application (it's all about achieving loosely coupled architecture and building scalable software; again this will depend on business needs)
To start with, here is a good read on "Microsoft Application Architecture Guide"
Absolutely. Just create a new Class Library project in Visual Studio and reference it in your ASP.Net project.
Read about
Base Page
Inherit all your pages from this base page. this will help you in having a OOP approach and also save you the trouble of
Copy-Paste
Add Class Library to your solution as shown below. And then you can move your data access & data manipulation code in classes in the class library.
Add a reference of this class library project to your web application. Now you will be able to call the functions that you have defined in your classes in Class Library in your web project.
VS 2010 Adding Class Library ..
Create a base class say 'MyAppPage' and override OnInit event. In the on init event check for the session. If null then redirect to your login page else continue. Make all your pages derived from your base class instead of System.Web.UI.Page. It will be good if you follow this for user controls also. Its always good to have your base class.
I found this Post (How to extend where MVC looks for views) about changing the location of the View.
I was wondering if there's something similar for changing the location of the controller.
I just want to change the location of the class inside project and don't want to affect the url.
For example Instead of placing the Controller into
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
I want to achieve something like
MyMvcProject\MyGroup1\
MyController1.cs
MyController2.cs
MyMvcProject\MyGroup2\
MyController3.cs
and also support Areas:
MyMvcProject\Areas\MyGroup3\
MyController4.cs
Is it possible to achieve this? And if yes, where can I find documentation about it?
You can do what you want, and it doesn't require any special configuration, because ASP.NET MVC does not care about where you put your controllers. First, controllers are located using reflection, so the name of the folder where you put your controllers is irrelevant. Controllers are searched by type name and optionally by namespace (for disambiguation). You can even have controllers in separate projects/assemblies. As long as the controller ends up in an assembly in the bin folder then it's searchable by the framework.
As mentioned above, you'll need to create a controller factory to support your custom resolution. Here's an example:
http://develoq.net/2010/custom-controller-factory-in-asp-net-mvc/
As others have already stated you need to do one of the following:
Derive from IControllerFactory interface and provide an implementation of the CreateController and ReleaseController methods.
Derive from DefaultControllerFactory and override the default behaviours.
Here are some links to get you started:
Custom controller factory in ASP.Net
Inside the ASP.NET MVC Controller factory
Dive deep into MVC - IControllerFactory
Also, if you're willing to spend a bit of money I would also recommend the book Pro ASP.NET MVC 3 Framework as this explains almost every aspect of how the MVC framework can be customised (including an example on how to create a custom controller factory - the source code for which can be freely downloaded from the publishers website).
I think it is impossible to do this. ASP.NET MVC have defined the convention that we have to follow.
Controllers are in Controllers folder, views are in Views{ControllerName}\
I believe you cannot change the convention unless you create your own ControllerFactory.
If you really want to do that, just implement IControllerFactory interface (or try to derive from DefaultControllerFactory).
Then your Application_Start register your controller factory using ControllerBuilder.Current.SetControllerFactory method.
Look at the ControllerFactory documentation and to the MVC source code for details.
What you're asking and what your example shows are two different things; depending on which one you want to achieve, you may or may not need to do any work.
There are two requirements for a class to be a controller in the MVC Framework:
It has to have a class name of Name + "Controller"
It has to have a parameterless public constructor.
Your sample "normal" MVC layout is actually not valid:
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
Those classes wouldn't be found by MVC because they don't have the correct name, regardless of which folder they are in.
If all you want to do is change the namespace/folder names, that "just works", assuming you name them the same as the appropriate route segment(s):
MyMvcProject\MyGroup1\
Page1Controller.cs
Page2Controller.cs
MyMvcProject\MyGroup2\
Page3Controller.cs
MyMvcProject\Areas\Area1\
Area1Page1Controller.cs
This walkthrough (written for MVC 2 but works just as well in MVC3) shows you how to support Areas with the default controller behavior.
If you actually want to name them SomethingController1 or SomethingElseController5, or otherwise change the route -> classname mappings, then you do need to implement a custom ControllerFactory, and inject it into the MVC pipeline.
There are plenty of examples on the web on how to do this, including the one posted earlier.
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.