Accessing views with absolute paths on ASP.NET MVC - asp.net-mvc

I'm trying to access a view in this way:
return View(#"~\Items\Details.aspx");
and I get this error:
The view '~\Items\Details.aspx' or its master could not be found. The following locations were searched:
~\Items\Details.aspx
On the ItemsController, in the Details action, returning View() works just fine. Why can't I access that view from another controller?

Prefix it with '/Views' should help.
return View("~/Views/Items/Details.aspx");

You can make the Items view a shared one (you put it in the Views/Shared folder), then you can just call View("Items") and it will work.

Related

MVC3 View Routing and partial view not found

I know what my problem is but not sure how to fix it so I was hoping the geniuses here could help. I have a controller that I want to grab a piece of info from the url then redirect to the site. My controller does it's thing and returns the view but the view has a partial in it and the view engine can't find it?
So here is the setup.
The controller is mapped route as:
//marketing/tracking
routes.MapRoute("CampaignTracking",
"{save}/{campaignid}",
new { controller = "CampaignTracking", action = "Index" });
This works great. So next my controller:
public ActionResult Index(Int32 campaignID)
{
var model = new ...snip...
return View("../Customer/Login", model);
}
Now I originally got the error couldn't find view as it was looking in a CampaignTracking folder and I had :
return View("Customer/Login", model);
So I changed it as seen above with the ../ to get to the correct location. Now it finds the Login.cshtml but in login.cshtml it renders a partial and again it is looking to find the partial in the Campaigntracking.
I could abolish the CampaignTracking controller and move the action result into the CustomerController but would prefer to keep it in its own controller as this will likely grow and doesn't really group under customer.
As per nicu Janga
I changed in my controller:
return View(#"~/Views/Customer/Login.cshtml", model);
and in my login.cshtml the partials:
#Html.Partial(#"~/Views/Customer/...etc.cshtml")
but I am wondering why. I can understand how the view engine gets confused coming out of the controller but once corrected with return View(#"~/Views/Customer/Login.cshtml", model); shouldn't the proper path propagate as well to the login.cshtml???
Obviously not but what don't I understand??
You can try this one:
return View(#"~/Views/Customer/Login.cshtml",model);
it works?
Let me see if I can fill in some details for you. First up, let's say we've just added the following controller to an empty project:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
Now, let's also assume that we didn't bother to add the Index.cshtml view, so when we run this, it will tell us the view is missing. Take a look at the message that accompanies that exception:
The view 'Index' or its master was not found or no view engine supports
the searched locations. The following locations were searched:
~/Views/home/Index.aspx
~/Views/home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/home/Index.cshtml
~/Views/home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml
These are the exact locations that are searched when MVC is trying to locate a view. For the most part, if you're using C# with MVC, the only two you need to care about are:
~/Views/home/Index.cshtml
~/Views/Shared/Index.cshtml
That means if you don't provide a path when specifying the name of your view, it will always check both of these locations. So if we did this from our HomeController:
return View("Test");
MVC will look for this view at ~/Views/Home/Test.cshtml and then ~/Views/Shared/Test.cshtml. The great thing about this is it's consistent. It always looks for the views in the same way.
Now, let's use a more complicated example (again, assuming we're in our HomeController):
return View("../SomeDirectory/Test.cshtml");
This is going to be looked for in the following ways:
~/Views/Home/../SomeDirectory/Index.cshtml
~/Views/Shared/../SomeDirectory/Index.cshtml
Taking a look at ~/Views/Home/../SomeDirectory/Index.cshtml first , this would actually mean it's searching for the view here: ~/Views/SomeDirectory/Index.cshtml. Obviously, this isn't where your view is, and the same applies to where ~/Views/Shared/../SomeDirectory/Index.cshtml ends up.
The important thing to remember here is ~ means the relative root of your site. It will always work from the root of your site, which means you can always be sure exactly what's going on. By doing this
return View("~/Views/Home/Index.cshtml");
you are telling MVC exactly where to find your view, rather than letting MVC's rules of convention decide for you. That means whenever you specify a location for MVC to find your view, it will only search that location. So return View("~/Views/Home/Index.cshtml") will only search for the view at ~/Views/Home/Index.cshtml. If it cannot find the view there, you'll get the same exception as before, but it will give you a slightly different message:
The view '~/Views/Home/Index.cshtml' or its master was not found or no view
engine supports the searched locations. The following locations were searched:
~/Views/Home/Index.cshtml
Notice how it hasn't searched for the view in the other locations.

Failed to return partial view from area

Basically I've just created an Area in my ASP.NET MVC4 application.
It all works great etc, however when I want to return a PartialView as shown below:
return PartialView("_ImportSessionsTable", viewModel);
(not that the above call is called from the area(admin) view)
I get the following error:
The partial view '_ImportSessionsTable' was not found or no view
engine supports the searched locations. The following locations were
searched: ~/Views/ImportSessions/_ImportSessionsTable.aspx
~/Views/ImportSessions/_ImportSessionsTable.ascx
~/Views/Shared/_ImportSessionsTable.aspx
~/Views/Shared/_ImportSessionsTable.ascx
~/Views/ImportSessions/_ImportSessionsTable.cshtml
~/Views/ImportSessions/_ImportSessionsTable.vbhtml
~/Views/Shared/_ImportSessionsTable.cshtml
~/Views/Shared/_ImportSessionsTable.vbhtml
The thing is: as far as I can see it isn't looking for the view in the area folder (admin) which is where I have the view stored. How can I get it to look there? Whenever I call return View(); it works fine so it's only when I specify the view as a string.
How can I get it to look there?
You could specify the full location of the partial to be rendered:
return PartialView("~/Areas/Admin/Views/ImportSessions/_ImportSessionsTable.cshtml", viewModel);
You could also consider overriding where the viewengine searches for views, but that might be a little extreme for what you're looking for. See here: Link

Problems returning PartialViews from controller

I am using MVC 4 and I have some areas in my project and some Views and Partial Views within each area:
Areas
AdminArea => one area and so on
Views
Customer
Customer.cshtml => my View
_CustomerDetails.cshtml => my partial View
In my controller, CustomerController I have the following code that fails:
return PartialView("_CustomerDetails", model) => fails to find my partial view.
However, if I call
return PartialView("~/Areas/AdminArea/Views/Customer/_CustomerDetails.cshtml", model)
the code executes successfully.
My Views (not partial views) all work ok. I even have some some partial views (also in the same area) that render ok without specifying the full path, but for some reason, for the most of them the above code fails in constructor saying that:
The partial view '_CustomerDetails' was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Customer/_CustomerDetails.cshtml a.s.o. ... => and is searching in global not in Admin area.
Is there any way to fix this problem without having to specify the full path to my PartialViews in code? (like passing area="Admin" like I do in the .cshtml file).
I am not using any custom ViewEngine and I have called AreaRegistration.RegisterAllAreas() in Global.asax.cs.
Thanks,
Tamash
I am really sorry for even posting this question:
The call from the controller worked fine, but the problem was that I was calling from javascript to get the PartialView through an action and I didn't specify the full name for that action. That's why the partial view wasn't returned since the method responsible for returning it wasn't being called at all.
Sorry about that: the code is a bit complex and I got lost in details around Ajax calls.
seems weird, try adding a view from controller action method i.e right click action method in controller, add view, make a view a partial view and see where it adds it.. check if it is the same location as you are putting, if not there is some structure prob/bug.

Why is Asp.Net MVC not searching for a view in my Shared directory?

In my /Views/Shared/ folder I created an EntityNotFound.cshtml razor view. In one of my controller actions I have the following call:
return View(MVC.Shared.Views.EntityNotFound, "Company");
This causes the following exception:
System.InvalidOperationException: The view '~/Views/Shared/EntityNotFound.cshtml' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Company/Company.cshtml
~/Views/Company/Company.vbhtml
~/Views/Shared/Company.cshtml
~/Views/Shared/Company.vbhtml
I am confused, because it does not even seem to be attempting to search ~/Views/Shared/EntityNotFound.cshtml. Even if I replace MVC.Shared.Views.EntityNotFound with "EntityNotFound" I get the same error.
Why is Asp.Net MVC not even attempting to find my shared view?
Have a look at the list of overloads for View();
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.view.aspx
Specifically, when you pass View(string,string); it sees the second string as the name of the master view.
Whats probably happening, is that it can't find the "Company" master view, you'll not the exception messages says
... or its master was not found...
Which means that it is probably finding the NotFoundException.cshtml, but can't correctly find the Company.cshtml that it's looking for as the master.
The correct syntax should be this (don't pass path, MVC is a language by conventions)
return View("EntityNotFound");
Assuming "Company" is a param you wnat to pass to the view, try like this:
ViewBag.ErrorEntity = "Company";
return View("EntityNotFound");
And from the View
<p>Entity not found: #ViewBag.ErrorEntity</p>

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).

Resources