MVC 5: Controller gets ignored - asp.net-mvc

I'm sure the question is as stupid as simple, but since nobody can give me a hint, I give it a try: I'm learning MVC Asp.Net by creating a small company-internal application, which has only 1 Page.
I worked trough the Tutorial: http://www.asp.net/mvc/tutorials/mvc-5/introduction/getting-started, which helps me a lot.
My problem itself: I went to the Controllers-Folder, added a Controller by selecting "MVC 5 Controller with read/write actions", then in the Views-Subfolder Views\NewItem\ I added a Index.cshtml by selecting "Empty Page".
But now when I debug the Program and select in the URL it keeps shooting a 404-error, meaning the Page is not found. I debugged the Controller, but it doesn't even goes to the Index-Method.
Is there anything I'm missing. I guess it's so stupid and clear I dont even find it on the Internet.
Nevertheless thanks in advance for all answers.

I think the easy way to add a View for your action method that is placed inside the controller you're working at, is to right click inside the body of your action method (that you want the users to access from the browser) and add the View you want, and the MVC automatically will add the View in the right place inside the View folder in Solution Explorer.

Please check you RouteConfig for rout configuration

Ensure that your controller is correctly named - e.g. NewItemController. If it doesn't have the Controller suffix, it won't be picked up.
It should also have an action method matching your view name, e.g. public ActionResult Index() in this case.

Related

How to sucessfully link to another cms page in Umbraco

I am growing increasingly frustrated with Umbraco. I've been working on an Umbraco project for a little while now and I have been unable to figure out how to solve my problem (one of many).
Scenario - I have a content managed page and on this page users can search for things (these things come from an entirely different database to Umbraco). This is fine, I've created a child action which loads the form for search and created the controller method which returns the results. However, each result I need to link to another content managed page (the same content managed page for each result) that takes an ID so I can inject some dynamic data into the content managed page.
Great, I've got a method for handling this request in my surface controller and I can create an Html.ActionLink for each result that when clicked hits my controller action with the id parameter.
Problem - When each link is clicked the url that gets hit is
http://localhost:5645/umbraco/surface/{controllername}/{actionname}/?id={id}
However this request is outside the Umbraco context, so when I try to return any page with the following controller code, I get the following error:
[ActionName("ShowDetials")]
public ActionResult GetProperty(int propertyId)
{
return View("~/Views/TestView.cshtml");
}
Cannot render a macro when UmbracoContext.PageId is null.
So my initial thoughts were to have a separate controller which inherits from Umbraco.Web.Mvc.RenderMvcController and try to handle the request in there, but then this raises other issues like being unable to use #Html.ActionLink to link to a RenderMvcController, I also don't want to have two controllers to handle content from the same section.
The other issues I have is passing custom models to the view.
If anyone can help me, I would be eternally grateful.
For any developer having this same issue the only way I have been able to solve it is by having two controllers. A surface controller to handle the initial rendering of the search form and page and to display the results of the search, then a separate rendermvccontroller to handle clicking on an individual result and displaying a 'details' page.
However, this in my opinion isn't great and I would still greatly appreciate it if anyone has another solution.

Finding my View in asp.net mvc

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.

ASP.Net MVC: same action name in different controllers

I have 2 controllers which are SearchController and SearchByStaffController respectively. They are very similar and both have an action with action name "Search". When I call View("Search") in their common super class, the confusion comes. Only the "Search" view with SearchController is rendered.
Does the MVC framework get only the first view that matches the name and ignore the rest?
I tried to pass the view path in View() and it worked. Would there be any side effect for doing so? I searched over the web and seems no one has done this before.
Thanks!
Does the MVC framework get only the first view that matches the name and ignore the rest?
Yes. The routing rules are aparsed (top to bottom) and when a rule is matched all end.
I tried to pass the view path in View() and it worked. Would there be any side effect for doing so? I searched over the web and seems no one has done this before.
You can but I don't like that because MVC is based on conventions. So, I see forcing the path of the view a way to broke a convention. Are you sure you can't simply create two routing rules for the two methods? So you can do something like this:
return RedirectToAction("Search", "Controller1");
and
return RedirectToAction("Search", "Controller2");
user932390,
mvc uses convention over configuration. this means that the 'search' view will have to be located in both the:
views/Search
and
views/SearchByStaff
folders respectively. the only way around this is to locate the search view under the views/shared folder, then the viewengine will find it there in both cases and use it (assuming they have the same model).

The view 'Index' or its master was not found.

The view 'Index' or its master was not found. The following locations were searched:
~/Views/ControllerName/Index.aspx
~/Views/ControllerName/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
I got this error when using ASP.Net mvc area. The area controller action are invoked, but it seems to look for the view in the 'base' project views instead of in the area views folder.
What you need to do is set a token to your area name:
for instance:
context.MapRoute(
"SomeArea_default",
"SomeArea/{controller}/{action}/{id}",
new { controller = "SomeController", action = "Index", id = UrlParameter.Optional }
).DataTokens.Add("area", "YOURAREANAME");
This error was raised because your Controller method name is not same as the View's name.
If you right click on your controller method and select Go To View (Ctrl+M,Ctrl+G), it will either open a View (success) or complain that it couldn't find one (what you're seeing).
Corresponding Controllers and View folders name have the same names.
Corresponding Controller methods & Views pages should same have the same names.
If your method name is different than view name, return view("viewName") in the method.
Global.asax file contain the URL Route.
Default URL route like this.
"{controller}/{action}/{id}"
So,Try this.
1. Right click your controller method as below.
Example: let say we call Index() method.Right click on it.
2. Click Add View.. and give appropriate name.In this example name should be Index.
Then it will add correct View by creating with relevant folder structure.
Check the generated code at MyAreaAreaRegistration.cs and make sure that the controller parameter is set to your default controller, otherwise the controller will be called bot for some reason ASP.NET MVC won't search for the views at the area folder
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"SomeArea_default",
"SomeArea/{controller}/{action}/{id}",
new { controller = "SomeController", action = "Index", id = UrlParameter.Optional }
);
}
Where this error only occurs when deployed to a web server then the issue could be because the views are not being deployed correctly.
An example of how this can happen is if the build action for the views is set to None rather than Content.
A way to check that the views are deployed correctly is to navigate to the physical path for the site on the web server and confirm that the views are present.
The problem was that I used MvcRoute.MappUrl from MvcContrib to route the context.Routes.
It seems that MvcContrib routing mapper was uncomfortable with area routing.
You most likely did not create your own view engine.
The default view engine looks for the views in ~/Views/[Controller]/ and ~/Views/Shared/.
You need to create your own view engine to make sure the views are searched in area views folder.
Take a look this post by Phil Haack.
I had this problem today with a simple out of the box VS 2013 MVC 5 project deployed manually to my local instance of IIS on Windows 8. It turned out that the App Pool being used did not have the proper access to the application (folders, etc.). After resetting my App Pool identity, it worked fine.
right click in index() method from your controller
then click on goto view
if this action open index.cshtml?
Your problem is the IIS pool is not have permission to access the physical path of the view.
you can test it by giving permission. for example :- go to c:\inetpub\wwwroot\yourweb then right click on yourweb folder -> property ->security and add group name everyone and allow full control to your site . hope this fix your problem.
It´s still a problem on the Final release.. .when you create the Area from context menu/Add/Area, visual studio dont put the Controller inside de last argument of the MapRoute method. You need to take care of it, and in my case, I have to put it manually every time I create a new Area.
You can get this error even with all the correct MapRoutes in your area registration. Try adding this line to your controller action:
If Not ControllerContext.RouteData.DataTokens.ContainsKey("area") Then
ControllerContext.RouteData.DataTokens.Add("area", "MyAreaName")
End If
If You can get this error even with all the correct MapRoutes in your area registration and all other basic configurations are fine.
This is the situation:
I have used below mentioned code from Jquery file to post back data and then load a view from controller action method.
$.post("/Customers/ReturnRetailOnlySales", {petKey: '<%: Model.PetKey %>'});
Above jQuery code I didn't mentioned success callback function.
What was happened there is after finishing a post back scenario on action method, without routing to my expected view it came back to Jquery side and gave view not found error as above.
Then I gave a solution like below and its working without any problem.
$.post("/Customers/ReturnRetailOnlySales", {petKey: '<%: Model.PetKey %>'},
function (data) {
var url = Sys.Url.route('PetDetail', { action: "ReturnRetailOnlySalesItems", controller: "Customers",petKey: '<%: Model.PetKey %>'});
window.location = url;});
Note: I sent my request inside the success callback function to my expected views action method.Then view engine found a relevant area's view file and load correctly.
I have had this problem too; I noticed that I missed to include the view page inside the folder that's name is same with the controller.
Controller: adminController
View->Admin->view1.cshtml
(It was View->view1.cshtml)(there was no folder: Admin)
This error can also surface if your MSI installer failed to actually deploy the file.
In my case this happened because I converted the .aspx files to .cshtml files and visual studio thought these were brand new files and set the build action to none instead of content.
I got the same problem in here, and guess what.... looking at the csproj's xml' structure, I noticed the Content node (inside ItemGroup node) was as "none"... not sure why but that was the reason I was getting the same error, just edited that to "Content" as the others, and it's working.
Hope that helps
Add the following code in the Application_Start() method inside your project:
ViewEngines.Engines.Add(new RazorViewEngine());
I added viewlocationformat to RazorViewEngine and worked for me.
ViewLocationFormats = new[] {
"~/Views/{1}/{0}.cshtml",
"~/Views/Shared/{0}.cshtml",
"~/Areas/Admin/Views/{1}/{0}.cshtml",
"~/Areas/Admin/Views/Shared/{0}.cshtml"
};

ASP.Net MVC and RenderPartial w/ relative paths

I've been playing around with ASP.NET MVC and had a question. Or maybe its a concern that I am doing this wrong. Just working on a lame site to stretch my wings a bit. I am sorry this question is not at all concise.
Ok, here's the scenario. When the user visits home/index, the page should show a list of products and a list of articles. The file layout is such (DAL is my data access layer):
Controllers
Home
Index
Views
Home
Index inherits from ViewPage
Product
List inherits from ViewUserControl<IEnumerable<DAL.Product>>
Single inherits from ViewUserControl<DAL.Product>
Article
List inherits from ViewUserControl<IEnumerable<DAL.Article>>
Single inherits from ViewUserControl<DAL.Article>
Controllers.HomeController.Index produces a View whose ViewData contains two entries, a IEnumerable<DAL.Product> and a IEnumerable<DAL.Article>.
View.Home.Index will use those view entries to call:
Html.RenderPartial("~/Views/Product/List.ascx", ViewData["ProductList"])
and Html.RenderPartial("~/Views/Article/List.ascx", ViewData["ArticleList"])
View.Product.List will call
foreach(Product product in View.Model)
Html.RenderPartial("Single", product);
View.Article.List does something similar to View.Product.List
This approach fails however. The approach makes sense to me, but maybe someone with more experience with these MVC platforms will recognize a better way.
The above produces an error inside View.Product.List. The call to Html.RenderPartial("Single",...) complains that "Single" view was not found. The error indicates:
The partial view 'Single' could not be found. The following locations were searched:
~/Views/Home/Single.aspx
~/Views/Home/Single.ascx
~/Views/Shared/Single.aspx
~/Views/Shared/Single.ascx
Because I was calling RenderAction() from a view in Product, I expected the runtime to look for the "Single" view within Views\Product. It seems however the lookup is relative the controller which invoked the original view (/Controller/Home invoked /Views/Product) rather than the current view.
So I am able to fix this by changing Views\Product, such that:
View.Product.List will call
foreach(Product product in View.Model)
Html.RenderPartial("~/Views/Product/Single.ascx", product);
instead of
View.Product.List will call
foreach(Product product in View.Model)
Html.RenderPartial("Single", product);
This fix works but.. I do not understand why I needed to specify the full path of the view. It would make sense to me for the relative name to be interpreted relative to the current view's path rather than the original controller's view path. I cannot think of any useful case where interpreting the name relative to the controller's view instead of the current view is useful (except in the typical case where they are the same).
Around this time I should have a question mark? To emphasis this actually is a question.
Because I was calling RenderAction()
from a view in Product
...
I do not understand why I needed
to specify the full path of the view.
It would make sense to me for the
relative name to be interpreted
relative to the current view's path
rather than the original controller's
view path
The part I think you're misunderstanding is the "execution location" for lack of a better or official term. Paths are not relative to your view, not even your "controller's view" as you put it. They are relative to your request URL, which defines a controller context. I may not be saying it very well, but if you spent a little time in Reflector looking at how URLs and routes are resolved, I think this would all fall into place in your head.
[edit:
I was thinking, you have 2 cases:
the Home controller is the only one that ever references Product / Articles List user control
the user controls are shared by several controllers
In the first case, the view user controls really belong to the home controller and it makes sense to put them in the home controller folder. In the second case, it makes sense to place them in the shared folder since they will be shared by controllers.
In either case, maybe you can place them in a sub folder. Like Views/Home/Products and then try RendarPartial("Product/Single") and see what happens? I don't know if it would try to resolve it to: Home/Product/Single and then Shared/Product/Single or not. If sub folders work, it seems to allow the logical seperation of Product and Article, while showing that they are still members of either the Home controller or Shared by all controllers.
]
Check out this blog entry by Steve Sanderson:
http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/
What you are doing isn't wrong, but it does seem to sort of go against the convention of View/Controller folder names. That said, it makes sense to want to define controller-agnostic view user controls and nesting them seems valid. So I dunno!
Anyways, the link just describes a method of instead of using RenderPartial to render a use control, it defines a method of RenderPartialRequest that renders the return value (in your case a user control) of a controller action. So you could add a Product and Articles controller with an Action List that returns your user control, and then call those two actions from the Home/Index view. This seems more intuitive to me, but just an opinion.
He also mentions subcontrollers from MVC Contrib, and I'm pretty sure there is desire for something like this to be a part of ASP.NET MVC release.
From looking at the MVCStoreFront sample this is how they have everything structured for calling RenderPartial
Views
Shared
ProductSingle
ProductList
ArticleSingle
ArticleList
Then render them via:
<% Html.RenderPartial("ProductSingle", ViewData["ProductList"]); %>
<% Html.RenderPartial("ProductList", product); %>
<% Html.RenderPartial("ArticleSingle", article); %>
<% Html.RenderPartial("ArticleList", ViewData["ArticleList"]); %>

Resources