I made a project where I have a basic DemoController:
<Export(GetType(IController))> _
<ExportMetadata("controllerName", "Demo")> _
<PartCreationPolicy(CreationPolicy.NonShared)> _
Public Class DemoController Inherits Controller
Public Function Index() As ActionResult
Return View("~/Views/Demo/Index.aspx")
End Function
End Class
In my "plugin" project that has this controller, it has the path /View/Demo/Index.aspx. When I run my main web app, I can get to the return View line but then it says the file cannot be found.
Why would this be?
I hope this all makes sense and sorry for the poor formatting.
I should probably mention that my .aspx file is in another project than the web app. I build everything into a dll then put that into a folder in my web app project. The error I am getting is "The view '~/Views/Demo/Index.aspx' or its master was not found or no view engine supports the searched locations. The following locations were searched: ~/Views/Demo/Index.aspx"
You said that you have all the views embedded in a separate project. Using the built-in view engine won't work. Either you have to specify the view locations in the built-in view engine as specified in this thread or create a custom view engine.
you must register the views for your plugins
the flow with asp.net mvc
so if you're developing plugins with DI you must keep in mind a few things
-custom View Engine
-custom Controller Factory
the default ControllerFactory can't resolve the controllers of your plug-ins, it's the same with the viewEngine, you must tell to the viewEngine where is that view
here is a example http://blog.maartenballiauw.be/post/2008/05/20/Creating-a-custom-ViewEngine-for-the-ASPNET-MVC-framework.aspx
~/Demo/Index
Should be right route
Also, please fix the return like that
Return View()
or
Return View("Index")
Related
I started learning Asp.NET MVC and got stuck pretty immediately. According to all materials I have, after I add controller in MVC project (Template - empty MVC controller), corresponding view should be created, too (folder under Views).
However, when I do this, nothing happens. Does anybody know what could be the problem?
And will this cause me a problems in a long run? I guess I could create those files manually, but still would prefer if they were generated...
My system:
Visual Studio Professional 2013, Update 5
Project: new MVC Web Application, template "Internet Application"
Thank you
Other possible way is to add complete path of the view in your controller method which is returning a view.
public ActionResult Index()
{
return View("~/Views/Home/Index.cshtml");
}
this method is useful when you have a hierarchy of folders for view files.
Normally views aren't created when a new controller is added. Views can be generated with the following methods:
Simply right click the method name within any controller and select "Add View"
Right click on the controllers folder and select "Scaffold..." which will created a new controller, views and/or DataContext for a specified model.
I added a default MvcApplication (MVC 4) (its name is MvcApplication3 matching the name of my solution's) width Home views (About, Index, Contact) and that will be my startup (bold in VS solution explorer's interface) project. Then I added another project (MvcApplication, but this time an empty one) called MvcApplication2 to the solution. Then I added the latter project as a reference to the first. I also added a controller called TestController (green line) to the referenced project and generated a view for its Index (red arrow) method. However, when I go to a link /Test or /Test/Index, the view I am expecting (red arrow) is not shown. Then I added the same folder Test with Index.cshtml (blue arrow) to the main project and now I am seeing its contents rather than the project's where my controller sits in.
Is it possible to make the application look for the views in the other project rather than the startup one?
I am adding the image of the structure to make it easier to follow.
P.S.: probably related: the breakpoint IS being hit in the Index method of TestController.
tldr; blue view is used instead of a red one
I think your problema is that you have set MvcApplication3 as startup Project and is causing you to open the view off that Project.
Is it possible to make the application look for the views in the other
project rather than the startup one?
Yes its posible, you can redirect your application the url. Think this your application have a url http://localhost:(someport) you can set redirect to the port of the second application.
I put a link to for better understanding a routing system of MVC: Documentation of routing system
As far as I know, you can't link to projects together like that. Each project becomes its own website with its own address. The reason you might put multiple projects together in one solution is to share things like classes, services, etc. I think what you're needing is areas:
http://www.codeproject.com/Articles/714356/Areas-in-ASP-NET-MVC
With some ideas from me and a friend of mine and a link about overriding RazorViewEngine I finally got what I wanted working exactly how I was expecting it to:
I created a folder named ViewsBase in the main project.
I rewrote RazorViewEngine this way: I only changed the place that was needed for me, leaving everything else like I found in the constructor of RazorViewEngine:
public class MyCustomViewEngine : RazorViewEngine
{
public MyCustomViewEngine()
{
...
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml",
"~/ViewsBase/{1}/{0}.cshtml",
"~/ViewsBase/{1}/{0}.vbhtml"
};
...
(I find it rather disturbing how I am unable to format the code properly. Can someone give me a hand please?)
and in Global.asax of the main project I added:
ViewEngines.Engines.Clear();
var ourViewEngine = new
ViewEngines.Engines.Add(ourViewEngine);
AreaRegistration.RegisterAllAreas();
...
I added a post-build event command:
xcopy /s "$(ProjectDir)Views\*.*" /Y "$(SolutionDir)$(SolutionName)\ViewsBase\"
It started looking for the views in the expected order
I added a ViewStart file to the base project to make it render the Layout too.
My Views folder has gotten crazy big! I would like to reorganize it so that the Views folder contains a list of Modules, and then each Module folder contains its share of the View (Controller) folders that currently appear under Views folder.
But of course this means going into each of my controllers and editing every view-returning method the explicit location of its view.
So instead of Controller Orders.Index method just having this:
return View();
I have to edit it to return this:
return View("~/Views/Orders/Index.cshtml");
You can imagine the suck level that this exercise attains over 50 or so controllers.
Is there some way that I can setup a routing or something per controller that will tell that controller's methods to go find their views in a defined subfolder of the Views folder?
It can be done with the help of CustomViewEngine
Follow this post and i hope you can provide your own locations to locate the view template.
MVC provide way where we can easily provide list of path to be searched
Locate view
Once you add CustomViewEngine, register it in Application_Start() event and then you are done :)
Happy coding
You could fix that by implementing a custom RazorViewEngine, where you can specify the search path for the views per request, per controller and so on.
I just implemented MVCContrib's Portable Area feature and it works fine. I can open it using:
http://localhost/projectname/portableAreaName, but this portable area is not working if i render it using the HtmlHelper extension method like this:
public static void RenderHtmlWidget(this HtmlHelper Html)
{
Html.RenderAction("Index", "HtmlWidget", new {area = "HtmlWidget"});
}
And calling the helper method in the view as such:
#using Project.Widgets.HtmlWidget;
#{Html.RenderHtmlWidget();}
I'm getting an error: The view 'Index' or its master was not found or no view engine supports the searched locations. In the possible location list there are no ~/areas/... defined.
But I can render my HtmlWidget successfully with this the same line of code in the view:
#{Html.RenderAction("Index", "HtmlWidget", new { area = "HtmlWidget" });}
What am I doing wrong and how should I use the HtmlHelper extensions correctly with the MVCContrib portable areas feature?
There are a few things that may be causing this.
In the calling/parent project where you use the helper method to invoke your portable area, do you have a Web.config file in the /Areas/ folder? If not, you must copy the Web.config found in the /Views/ folder of the same project, and simply place the new copy in the /Areas/ folder as well.
In the Registration class file in your portable area project, after you call MapRoute in the "RegisterArea" method, are you calling "RegisterAreaEmbeddedResources();"?
Is each view in your portable area project made to be an embedded resource as opposed to content? Select a View in the Solution Explorer and hit F4, "Build Action" should be set to "Embedded Resource", but it defaults to "Content"
You also need to make sure that both the Portable project and the consuming project reference the same version of MvcContrib, but that they also utilize the same version of ASP.NET MVC. If your area is referenced in multiple projects, each based off of a different version of MVC (not likely, but possible depending on the situation), your area must use whatever version of MVC the consuming project uses.
I'd also suggest using Phil Haack's .NET Routing Debugger - its a single DLL file that you reference in the consuming application and add a single line to your ApplicationStart() in your Global.asax.cs. This becomes incredibly helpful in determining if your portable area is being correctly registered with the base project - and helps you cut to the chase.
I'm using VS2008 and .net 3.5. I have created a class library(Myproject.Controllers) in my solution. Under this class, I have added a Controllers folder. And in the folder I have added a MyController which is declared as
public class MyController : Controller
My views are still in the default Views folder. Now, when I run this in VS, I get a message in the Default.aspx.cs:
{"The controller for path '/' could not be found or it does not implement IController."}
If I put a copy of my MyController in the default Controllers folder then it works fine. Does anyone know how I can set/configure the Controllers path? I've searched the web and didn't find anything for this. Thank you.
By creating your own Controller factory, you can specify exactly how controllers are used. Here's how
step 1 - create a class and derive it from IControllerFactory
http://msdn.microsoft.com/en-us/library/system.web.mvc.icontrollerfactory_members.aspx
step 2 - Consume your new Controller Factory in application start
ControllerBuilder.Current.SetControllerFactory(typeof(MyControllerFactory));
IControllerFacotry implements 2 methods
IController IControllerFactory.CreateController(System.Web.Routing.RequestContext requestContext, string controllerName);
void IControllerFactory.ReleaseController(IController controller);
And that's all there is to it.
I did this not too long ago, and the only tricky part was to make sure that the namespace where the controller resides is the same as it would be if it was in the default folder. The main pitfall is the root namespace of the class library project - you can change it by right-clicking the project node in Solution Explorer, selecting Properties and changing the value in the Root Namespace textbox. The easiest way is to name it the same as the MVC application itself.
From my understanding, this should just work. Did you add your Controllers library as a reference to your web site?
From MVC source
// ControllerTypeCache.cs:
private static List<Type> GetAllControllerTypes(IBuildManager buildManager) {
// Go through all assemblies referenced by the application and search for
// controllers and controller factories.
// DefaultControllerFactory.cs
// if all else fails, search every namespace
return GetControllerTypeWithinNamespaces(controllerName, null /* namespaces */);
I had a similar issue using dotnet 4.0 utilizing MVC 2.0 on IIS7.0. After checking all the normal stuff, having the right MVC assembly version and so on, i finally moved the code from a random location on the web server to /inetpub/www and recreated my site on the webserver. That seemed to have done the trick. Aparently, DotNet MVC likes to have the source under /inetpub/www to be able to resolve the MVC paths.