MVC 5 Custom ViewEngine to Load External Controllers and Views - c#

REQUIREMENT
I have a project and one of requirements is load external small websites like plugins.
This websites must accomplish few requirements of course (like mvc and net version and other more to make it compatible).
This plugins must be allocated in a new folder inside my MVC Website. And in it there are Views folder and compiled website dll result (controllers, models,...)
CURRENT DEVELOPMENT
I implementented a custom ViewEngine to load Views from this folder, and a ControllerFactory that makes the trick for controllers that are not located in my main website.
I based my code in http://christianjvella.com/wordpress/mef-mvc-defining-controllerfactory/ for ControllerFactory and Can I specify a custom location to "search for views" in ASP.NET MVC? for ViewEngines
PROBLEM
All seems to works well with a simple html view. But when I use some MVC helpers or objects like ViewBag, #Url.Content, #Html.DropDownList i have an error that the object is null or not exist.
Overriding CreateView method in ViewEngine, it returns an IView instance correctly and controllerContext have ViewBag and other necessary features.
It seems that, at the moment of view rendering, MVC doesn't attach controllerContext to view instance...
Is this a limitation of MVC that don't pass controllerContext to external loaded views or externals controllers? Any idea or workaround?

Your views have to be pre-compiled. You can use precompiled MVC views for doing so.
Precompiled views are created using a VS Addin called as RazorGenerator.
You can read more about here, below example puts Views in separate class library! ,some thing that you are looking for:
http://www.c-sharpcorner.com/UploadFile/97fc7a/article-precompiled-razor-view-using-razorgenerator-mvc-and/

Well, I forget to include web.config in plugins Views folder, with it works fine because it defines Razor and MVC dll references.
Thanks for all

You could also use a VirtualPathProvider to serve things from other assemblies, including static assets and views. This way you can use the standard ViewENgine
https://www.nuget.org/packages/EmbeddedResourceVirtualPathProvider/

Related

How to do ASP.NET Core controllers avaiable using Screaming Architecture Conventions?

I'm trying to understand how to do an Asp.Net Core application (3.0) looks like a Screaming Architecture folders and files conventions.
I read about it but and started with an empty project. The folders are:
Controllers
Views
Models
I want to make the web application working like
Customers/Controllers
Customers/Views
Customers/Models
Is it possible?
Thanks in advance.
Both controllers and models are referenced by namespace, so their physical file locations have no bearing on anything. Controllers are dynamically loaded regardless of where they are in the project or even if they're in the project at all (i.e. a controller from a referenced library will automatically be loaded). Models are entirely code-based, and you'd just add a using statement with the namespace of the model(s) to access them in any other piece of code.
Views, however, are very much based on the filesystem, and changing the main folder they're in from just Views or Pages directly in the project root will cause the convention-based view loading to fail completely. You can always add additional view search locations, such that it will look in /Foo/Views and /Bar/Views, etc. but that's really not recommended.
All that said, though, there is a concept of areas, and you can break down your controllers, models, and views that way. You'd simply have to have:
Areas/Customers/Controllers
Areas/Customers/Views
Areas/Customers/Models
In other words, the Areas prefix would be mandatory.

Clean Architecture - In ASP.NET MVC - Which layer I use to write the ViewModels?

The question is very simple,
I am using Clean Architecture for a project(web site) by using ASP.NET MVC. I download the Clean Architecture template sample code written by Ardalis from GitHub.
In that specific template, the writer didn't use the viewmodel.
Does anybody have any reference for a template using Clean Architecture and viewmodel for ASP.NET MVC etc or know where to put(layer) the view model.
I'm the author of the CleanArchitecture template in question
The latest version uses ViewModel classes with Views as one of several options (the others being Razor Pages, APIs with Controllers, and APIs with API Endpoints). Typically when using ViewModel classes the usual convention is to put them into a ViewModels folder in the root of the Web project.
This puts them near the Views folder so they are fairly easy to find (and for API Models used with API Controllers, frequently these are placed into an ApiModels folder that sorts near the API and/or Controllers folders typically used in these cases).
It's worth mentioning that this problem goes away if you use Razor Pages, because the model is linked to the "view" (the Page) in the approach.
Likewise for APIs, if you adopt the API Endpoints approach (another open-source package of which I am also the author), the Request and Response models used for each endpoint are typically linked to the Endpoint class there as well.

asp.net MVC correct place for controllers for shared partial views

Where is the best place in the project directory for the controllers for Shared partial views?
I have found similar question to: ASP.NET MVC: Correct place for Partial Views?
I can't decide if it is better to do something like /Controller/Shared/CONTROLLER_FOR_PARTIAL_VIEW or just create its separate folder like /Controller/CONTROLLER_FOR_PARTIAL_VIEW
The partial view is specifically for dropdownlistfor, and the model wont be used for anything other than to populate the dropdown. So if a site has many dropdown lists or just partial views in general, a shared folder seems to be the best option. If the preferred way it the Shared folder, do you use one controller for each partial view, or one controller for all partials? I appreciate any thoughts or feedback, thanks!
EDIT: To be clear, I m specifically asking about the directory for the CONTROLLERS not the VIEWS. Thanks!
In one sense, it doesn't matter. There is no true standard or convention for this, so you have the freedom to do it however it makes the most sense to you and your application.
Having it under something like Controllers/Shared could make sense, if there's enough of these that that is worthwhile and it adds value to keep them separate from regular controllers. However, in terms of a project, everything is essentially shared, so there's no true distinction here. Personally, simply having it named something distinctive is probably the best route. For example, I have a number of child actions in one of my projects that are used in various parts of my layout. As a result, I created a LayoutController to house these.
The one thing to keep in mind is that, if you're using standard routing, any controller will be available to the routing infrastructure, regardless of where it's located in your project tree. You'd have to pretty much just know how to get to it, but if you named your shared controller something like SharedController, then with standard routing, its actions would be available via /shared/action. For things like child actions, this is easily solved by using [ChildActionOnly]. By adding that attribute to your child action, it will be divorced from the routing infrastructure for URL requests. Internally, MVC will still be able to get to it for the purposes of rendering it for a view, though.
Projects I've been on it was at /Area/Controllers/SharedPartialController.cs and with that naming the view was at /Area/Views/SharedPartial/_MenuDropdown.cshtml
Hopefully you're using "areas" in your MVC project, in which case I would suggest doing one shared controller per Area.
I.e. /Order/Controllers/TabsPartialController.cs for one that relates to Order area, and then /User/Controllers/NavTabsPartialController.cs etc.

Folders in Controllers directory in ASP.NET MVC 4

I'm kind of new to ASP.Net MVC 4. I'm working on an app that will have a lot of routes. With that in mind, I'm running into naming conflicts in my Controller. Because of this, I've decided that I want to split up my Controller into multiple controllers. In an attempt to keep things clean, I feel I have a need to put Controller classes in subdirectories within the Controllers directory. My questions are:
Is this even an option? I can't seem to find any examples with
this approach
How do I register the Controllers that are in the
subdirectories such that when I add routes in the RouteConfig.cs
file, they leverage the controller that is in a subdirectory?
Thank you!
Is this an option? Definitely. You can place the controllers wherever you want. MVC would automatically scan the assembly for controllers and it doesn't matter if they are placed only under Controllers.
If things get more complex, and you want better organization, you can leverage the concept of Areas in ASP.NET MVC - http://msdn.microsoft.com/en-us/library/ee671793(v=vs.100).aspx

Using MVC3 with folder structure like regular ASP.NET

So I am reading about building MVC3 projects and there is one thing that seriously bugs me. The folder structure of the project in no way corresponds to the path of the HTTP request. There is a bunch of things I like and would want to use, but having a flat folder structure is not one of them.
Why is this a problem? Well, I see it becoming a problem when building a site with a heavy mix of content pages and various forms/dynamic pages (most of our sites are like that), which would typically be done by different people. It seem it would be too complicated for client-side developers to follow routing rules of dynamic pages and/or creating new ones.
What I would like to understand is if there is way to configure MVC3 application in such a way that:
it follows directory structure for finding controllers without explicit route map for each one
views live in the same folder as corresponding controller
routing magic still works for actions and parameters
For instance I'd like to have a request /fus/ro/dah/ to try to find DahController in the \webroot\fus\ro\dah\ folder and execute its Index action. If not found it would look for RoController with Dah action in the \webroot\fus\ro\ folder, etc.
It is entirely possible that MVC was not meant to be working this way at all and I am just trying to force a square peg into a round hole.
UPDATE:
Looks like I can drop a view file into the desired folder structure, and it will be executed. However layout would not work apparently because it is expecting a controller. Does this mean I have to create a controller for pure content pages? That is a pretty crappy design...
UPDATE 2:
Main issue right now is that creating "fus" folder means that MVC will not even attempt to look for FusController... not under "fus" folder, nor anywhere else. Is it possible to get around that?
For instance I'd like to have a request /fus/ro/dah/ to try to find
DahController in the \webroot\fus\ro\dah\ folder and execute its Index
action. If not found it would look for RoController with Dah action in
the \webroot\fus\ro\ folder, etc.
MVC is not designed for a particular need like this, it is a general framework for building applications using model-view-controller pattern.
If you can't bend the application for the framework you can bend the framework for the application and honestly MVC is very customizable. [As a proof, in the current project (migration from ASP to MVC) that I'm working we have models as xml and no classes also we are using XSLTs for rendering. With a little work we have created custom components like custom view engine, custom validation provider, custom model binder... to make the framework best fit for the application and it does]
MVC is not designed and not forces to use it as it is and you can customize/extend as much you want. In your case you may have to create a
custom controller factory (because you want to customize the way in which the controller is seleced),
custom view engine (because you want to customize where the view is placed)
and may be others.
For custom controller factory you have to extend the DefaultControllerFactory class. There are lot of articles you can find through Google that explains about how to create custom controller factories.
Depending upon the view engine you are using you have to extend the respective one. For ex. if you are using web forms then you have to extend the WebFormsViewEngine and it razor then RazorViewEngine.
For more info. check this link
http://codeclimber.net.nz/archive/2009/04/08/13-asp.net-mvc-extensibility-points-you-have-to-know.aspx
you can mixup Asp.net and Asp.net MVC. as LukLed said, MVC is convention over configuration pattern. if you follow the convention. you dont need to configure. you can check this link for mixing up the asp.net content with MVC3
Mixing Asp.net and Razor
I believe ASP.NET MVC is not meant to be used that way. While you can configure MVC to do it, it is better to keep standard /controller/action/parameters URL format. If you have complex website with many different functionalities, areas may be helpful http://msdn.microsoft.com/en-us/library/ee671793.aspx. Every area get its own set of controllers, models and views, so teams working on different parts of website won't disturb each other.
While it may sound convenient, that framework first searches for DahController and executes Index action, then searches for another one, I find it bad idea. URLs should be clearly defined and Fus controller with Ro action shouldn't just stop working, because someone created RoController with Index action.
Look into using Areas as well. I think that helped me get over my folder structure issues with MVC honestly. So i could use the base folder as my Home details, then i could have a 'Admin' area which was a separate folder, things like that.
How "regular ASP.net" do you want it to be? If you want to do "legacy" ASP.Net Web Forms mixed in with MVC, you certainly can - re: mixing MVC with "file based aspx" - aka "hybrid". At the end of the day, it's all ASP.Net.
This is a standard MVC Application generated by Visual Studio. I've added a folder somedirectory where I want to use the legacy folder/file.ext paradigm and have a default.aspx Web Forms file:
Can I navigate to it via http://foo.com/somedirectory? Yes.
Can I use "pretty urls" too? Yes
Vanilla Global.asax generated by VS, just added MapPageRoute:
....
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//using "pretty urls" - ordering your routes matter.
routes.MapPageRoute("theWebForm", "legacy", "~/somedirectory/default.aspx");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
so now I can navigate to it via http://foo.com/legacy
Just check the order of your routes, and perhaps plan on your naming conventions so you don't have "collisions"...
Hth....

Categories