I have been forking on a project for a while now and I ended up having a lot of view for different models. I was wandering whether it is possible to organise these views into sub folders. So just to be clear I want to do the following:
Controllers:
MyControllers(Folder)->
MyFirstController.cs
MYSubcontroller(Folder)->
MySubController.cs
Views:
MyFirst(Folder)->
Index.cshtml
MYSub(Folder)->
Index.cshtml
You are allowed to put views and controllers wherever you want. You can easily customize view paths on App_Start event. See tha answer in this topic: Can I specify a custom location to "search for views" in ASP.NET MVC?
I would though recommend using the standard project structure and paths. It would makes life easier for other developers that work with your code in the future eventually.
Most basic option would be for your controller routes to specify a view explicitly when returning:
return View("PATH-TO-YOUR-VIEW");
But I'm not a fan of this approach as you lose the nice built in MVC conventions.
By default, the Razor View Engine will use the following conventions when locating views:
~/Views/{1}/{0}.cshtml
~/Views/{1}/{0}.vbhtml
~/Views/Shared/{0}.cshtml
~/Views/Shared/{0}.vbhtml
The view name
The controller name
With this in mind, if you have a controller named MySubController with the default Index action, you would normally have a view file:
~/Views/MySub/Index.cshtml
Related
Here by modularity I do mean the feature based layout like this one:
(I've read about areas. And I'm not asking about areas)
For example, using NancyFx this thing is achieved easilly. As for ASP.NET MVC I've tried to extend the standard RazorViewEngine by replacing its view search paths. As the result views were found but the static content they referenced couldn't be loaded (404 error with message saying that there's no corresponding controller to match a request to /assets/css/dashboard.css)
I have seen many posts where people implemented custom view engines, redefined the CreateView, FindView, GetGeneralNameFrom methods and so on. But I don't get the whole thing on the ASP.NET MVC conventions.
What conventions should be changed in order to let controllers reside with its feature-related code (services, views, models) in the same feature-folder?
I'm asking about the internals I've got to change/replace/extend.
You must not place your view with your code files. In MVC you should have separate folders: Models, Controllers, Views. The MVC engine searches views in Views folder.
In your case in your Views folder you need to have subfolders Authentication and Dashboard. In each subfolder you place your index pages and other pages related only to this part of application. For example, if you have separate view edit for dashboard editing you place it in Views - Dashboard
The same is for controllers' classes. You have Controllers folder and subfolders Dashboard, Authentication. The same rule is for models' classes
For all .js files you should have Scripts folder, for all css rules - Content folder
And you do not need your custom ViewEngine for rendering pages. Its only needed if you have some non-generic templating or some business requirements
I am trying to learn asp.net MVC.
I have created a model called Property, I have then created a controller called PropertiesController. However when I run my code I get a 403 error when navigating to /Properties
If I rename my controller to Properties1Controller and navigate to /Properties1 it works.
I assume there is a conflict between the name of my controller and the Properties folder (mine contains AssemblyInfo.cs).
Is there a way around this or is it best to avoid controllers called Properties?
There is a conflict here. In your project you already have a Properties folder which holds the AssemblyInfo.cs file. I'd choose a different name for your controller.
It may be possible to get working with routing but in reality it's much simpler in the long run to stay away from anything non standard.
I am writing my own Payment method for NopCommerce (for Datacash to be precise, if somebody can point me towards a Datacash implementation of IPaymentMethod for NopCommerce that would also answer my question).
The documentation provided by NopCommerce for doing this is great, and that is what I am using as my reference, but I am very new to MVC, and the first step is to create a new controller.
I understand that, in regards to MVC, you have models, views and controllers. The model is to do with how the data for your website is modelled, the view is what you see (your HTML etc) and the controller is the programming logic behind what you see.
In any MVC Hello World Application I have done so far, you usually have a folder for your models, one for your views and one for your controllers, as shown below:
However, NopCommerce looks like this:
So my question is in which folder do I put the controller I am about to create (or does it even matter)?
Thanks
One observation: it looks like you didn't download the source version of nopCommerce, which does indeed have "Controllers" folders:
On the nopCommerce downloads page (http://www.nopcommerce.com/downloads.aspx), look for the version "with source code", if you're looking to do customization of any sort.
You don't have to but it is best/wise to.
The convention like you said is to have a View, Model and Controller.
So create a Controller folder, and you can either put your Controller class directly in the folder or do the better thing and create a NOPCommerceController folder so it looks like:
Controller/NOPCommerceController/SomeController.cs
Nice and clean.
You should create your controllers and models inside your plugin project:
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 an application that has a concept of discrete modules. These modules will live in Modules folder. Each module will have a folder under this Modules folder. These module folders will then have a Controllers and Views folder under them, very similar to how Areas work.
I would like to extend/change the search locations that are searched so that when my module controllers return a view the new locations will be searched.
I am thinking this will need to involve a custom ViewEngine, but I am uncertain of the specifics. Is there a specific viewengine I can extend, or do I need to write a new one from scratch.
Is writing a custom view engine the right way to go, or is there a better route?
I am thinking this will need to involve a custom ViewEngine
Correct thinking.
Instead of extending a specific view engine you can implement a view engine wrapper, that way your custom logic for locating views can work with multiple view engines. That's how MvcCodeRouting works, by temporarily replacing the controller value in controllerContext.RouteData.Values, so when a location format is used (such as ~/Views/{1}/{0}.aspx) you can inject into those placeholders your custom location.