When I'm inside Admin area and map my routes using attribute routing it cannot find view because it doesn't look inside actual area view folders but instead only global view folders.
Only if I pass full path to view it then can display it, otherwise it throws me error.
Error
The view 'Authorize' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Authorize.aspx
~/Views/Home/Authorize.ascx
~/Views/Shared/Authorize.aspx
~/Views/Shared/Authorize.ascx
~/Views/Home/Authorize.cshtml
~/Views/Home/Authorize.vbhtml
~/Views/Shared/Authorize.cshtml
~/Views/Shared/Authorize.vbhtml
Code
[RoutePrefix("admin")]
public class HomeController : Controller
{
[Route]
public ActionResult Index()
{
return View("Authorize"); // Error
return View("~/Areas/Admin/Views/Home/Authorize.cshtml"); // Working
}
}
Note that if I disable attribute routing and switch back to good old routes it will work. Any way of fixing this or it's working as intended and I should apply full path in all my areas?
You need to add the [RouteArea("")] attribute to your controller:
[RouteArea("Admin")]
public class HomeController : Controller
You can find the documentation here.
Related
URLs work correctly
Actions work correctly
the only problem is that the razor engine is just searching for view files in ~/Views and not in ~/Areas/Admin and I don't know why is that because it used to work fine
It works when I fill the return view type of the action by the exact path of its view but the absolute path for views is not working
Here is one action for example but none of the actions in the admin area can call their views
Even _Logout which is a partial view ib Shared cannot be called by _Layout unless using the full path
Action in Controller:
// GET: Admin/Login
[Route("Admin/Login")]
public ActionResult Login()
{
return View();
}
Error:
The view 'Login' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Default/Login.aspx
~/Views/Default/Login.ascx
~/Views/Shared/Login.aspx
~/Views/Shared/Login.ascx
~/Views/Default/Login.cshtml
~/Views/Default/Login.vbhtml
~/Views/Shared/Login.cshtml
~/Views/Shared/Login.vbhtml
Solved!
[RouteArea("Admin", AreaPrefix = "")]
Was missing from top of my controller
I have created a .Net Core Web API program. I want to add a single view to it. Under the same project I add a "Views" folder. In the HomeController, where I am routing all my API requests, I created the following:
[HttpGet("view")]
public IActionResult Index()
{
return View();
}
In my Views folder I created a folder "Home" and added "Index.cshtml" to it.
When I launch the API, and navigate to "../view" I get to the return View(); line, but then it returns a 500 Internal Server Error.
This is what I don't like about the "automagical" approach of MVC convention. I have no idea where to link a view to a controller if the convention didn't work.
Update, this probably should have been my first course of action.
I added a new class to Controllers folder, and used the MVC Controller template in VS2015. I then added a view to match, and it still doesn't work automagically.
So for clarity, my project is: ASP.NET Core Web Application(.NET Core) with a Web API template. I have a "Jobs" controller class that was added at the start as 'Values' and I renamed. Then I added an MVC Controller Class named "HomeController" with the only method being "Index". I added a folder named "Views" and a subfolder named "Home", and added an MVC View Page named "Index.cshtml".
I tried to use "return View();" in the Index method, didn't work. I then tried to add [Route("Home/Index")] above the Index method. Either way, the URL will get me to my break point at "return View();" but it will never return the view.
Note : It's a little strange that you want to return a view in a Web API project, a Web API project is supposed to return some data structure, like json using return new JsonResult(your_json_here) for example.
Note 2 : you need the Microsoft.AspNetCore.Mvc framework (which is installed with the Web API template)
Anyway, you have different ways to configure routing in a asp.net core application :
Creating and extending default routes
Example of routing configuration in the Configure method :
app.UseMvc(routes =>
{
// You can add all the routes you need here
// And the default route :
routes.MapRoute(
name: "default_route",
template: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" }
);
});
Using attributes
If you configure routing with attributes, don't forget the controller's one :
Example for the route /index :
[Route("")]
public class HomeController : Controller
{
[HttpGet]
[Route("[action]")]
public IActionResult Index()
{
return View();
}
}
Example for the route /home/index :
[Route("[controller]")]
public class HomeController : Controller
{
[HttpGet]
[Route("[action]")]
public IActionResult Index()
{
return View();
}
}
Example for the route /iputwhatiwant/actionnameiwant :
[Route("iputwhatiwant")]
public class HomeController : Controller
{
[HttpGet]
[Route("actionnameiwant")]
public IActionResult Index()
{
return View();
}
}
My screen of a .NET Core Web API project returning a view :
For more information, the official documentation is well-documented : https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing
How are you running this webapp, from the Windows commandline?... can you give us the detailed HTTP500 error. It will probably reveal something different than routing errors because that usually gives 404.
[Route("[controller]")]
public class HomeController : Controller
Note the automagical "[controller]" in the Route definition, I think its necessary now
It took me a frustratingly long while to learn the routing convention as it was being developed, but it seems to have normalized out for a few versions. Check out this tutorial documentation on the subject in MVC: Attribute Routing in ASP.NET MVC 5, which is MVC not WebCoreAPI where it is likely based from. If you have a better documentation specific to Web Core API, use that.
This ASP.NET Web Core Build a web API tutorial documentation has some good points about what you seem to be trying to do. Specifically, the section title "Getting to-do items" has this code:
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(long id)
{
var item = _todoRepository.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
Looking at that with benefit of some measure of MVC routing experience, it looks particularly different from your approach in that the HTTP verb annotation member property value used is a query parameter.
Seeing I am guessing using known inexpertise, still, I think you need to get the attribute routing fixed, and maybe return an ObjectResult instead of a view, as NightOwl888 suggests. The server error might also have much more useful information along with the exception message.
EDIT: Sorry, I may have misunderstood your question. If you are trying to build an app that serves dynamic web pages instead of a WebAPI that serves data object results, this Build an MVC Web App tutorial, similar to the "Build a web API" tutorial I mentioned before might have your app structure problem answer. If you are trying to do both, you should probably start with the MVC Web App structure or use two separate projects.
The (only) way I have got this working is to declare the path as an attribute on the action - in the same way you have done but with the format as below (Controller/Action):
[HttpGet("Home/Index")]
public IActionResult Index()
{
return View();
}
I was missing:
"preserveCompilationContext": true
in the build options of my project.json
I'm new to ASP MVC programming and wanna ask about how the route is configured.
For example I have the Home Controller
public ActionResult Home(){
return View("Index")
}
This will find the Index.cshtml under /Views/Home/
However if I rename the Home Folder to Homees for example, the view is not found and also I try to return View with View("~/Views/Homees/Index.cshtml") this is not change that the controller not found the view.
Is this the default of the asp mvc? and it's possible to change this one?
There are few points.
ASP.net MVC is convention based. It is also specified by #Petar Minev. When it comes to search for view it use following method. It take controller name as directory name and view name file name with different extention ( like cshtml, vbhtml , aspx ) based on view engine. ( As you are using cshtml it seems that you are using both Razor and Webform view engine).
For search it will first go to directory with controller name and search for specified view. If it is not available there then it goes to shared folder.
Above is default behavior of ASP.net MVC.
Now you change folder name then first solution you have tried that must work as it works for me. ( Please check that your folder name is correct. Make sure you did not rename for area directory).
public ActionResult Home(){
return View("~/Views/Homees/Index.cshtml")
}
Another solution is to rename controller with HomeesController ( So it will automatically locate correct directory)
If you continue with this convention for other folder like the way you add "es" in "Home" it is better to add this convention in default search for view.
( You can do this by either inherit from default RazorViewEngine or change RazorViewEngine parameter)
For example
protected void Application_Start()
{
RazorViewEngine engine = (RazorViewEngine)ViewEngines.Engines[1];
List<string> currentFormats = engine.ViewLocationFormats.ToList();
currentFormats.Insert(0,"~/Views/{1}es/{0}.cshtml");
engine.ViewLocationFormats = currentFormats.ToArray();
... Other application start code
}
Razor View engine is default view engine for ASP.Net MVC. This Razor view engine is configured to locate path at specified path i.e. "~/Views/{1}/{0}.cshtml".
Here {1} placeholder specifies controller name and {0} represents view name.
Say, for Example any request for Index action in Home controller will look for view at "~/Views/Home/Index.cshtml".
Now if you want to change this default path then you have to define custom view engine. Here a sample example how can you define a custom view engine and change the default path.
public class MyCustomViewEngine : RazorViewEngine
{
public MyCustomViewEngine()
{
ViewLocationFormats = new string[] {
"~/MyViews/{1}/{0}.cshtml",
"~/MyViews/Shared/{0}.cshtml" };
MasterLocationFormats = new string[] {
"~/MyViews/{1}/{0}.cshtml",
"~/MyViews/Shared/{0}.cshtml"};
PartialViewLocationFormats = new string[] {
"~/MyViews/{1}/{0}.cshtml",
"~/MyViews/Shared/{0}.cshtml"};
FileExtensions = new string[] { "cshtml" };
}
}
You also need to register custom view engine with ASP.Net run time at Application _Start() event.
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MyCustomViewEngine());
Your controller code is seems wrong, if your controller name is Home then code will be like this with index action
public class HomeController : Controller
{
public ActionResult Index()
{
return View("~/Views/Homees/index.cshtml");
}
public ActionResult Contact()
{
return View();
}
}
you just used the controller name as action name, by default in view folder there is a separate folder for each controller like for Home controller there will be a folder named Home, and inside that there will be separate cshtml file for each action result, like for my code there is a two action result name Index and Contact so under Home folder there will be two separate cshtml for both as index.cshtml and contact.cshtml. So when we request index action it will go for index.cshtml and for Contact action contact.cshtml by default, but we can spacify our own view for any action like my index view, and it works fine, your approach was correct but only problem was the Controller name and action name I think, try this way it may help
by default Microsoft's ASP.NET MVC is created over one Folder Convention which means that all files that will be Controllers should be under Controller folder, each file which will be View should be under View folder,
also if you create Mvc Route for example MyProfile, in the MVC you'll get contorller with this name and folder under the view's.
All this is controlled by the default routing which is knowing where to find, Views and controllers, so if you want to make some changes or modifications you should go to ASP.NET web site and look some tutorials for MVC Routing
Hope i helped :)
Simple just go to App_Start and Open RouteConfig.cs File and change route controller "Home" to "Homees" by default it set as "Home". If you rename your HomeController to "HomeesController" you should change to rountconfig by default route. check below image
After that open "HomeesController" from Controller folder here you can add action for view
public ActionResult Index()
{
return View();
}
and Add Action to View "Homees" Folder
I recently converted our intranet Umbraco site from v4 to v7.2 and also converted all the webform masterpages to mvc.
I am trying to convert a usercontrol that should be a child action to a SurfaceController but I am getting the dreaded "No route in the route table matches the supplied values" error when trying to call the action:
#Html.Action("ServiceStatusInfo", "ServiceStatusSurface")
This is just a get action that doesn't require a view or a model. It just calls the action on the server and the server updates a file on the server that then get's read by some javascript.
I have done a lot of searching and I created a sample solution using Umbraco 7 and created a controllers folder, then a "MySurfaceController" and I was able to call the action from the masterpage of the sample solution with no issues but in the recently converted project it seems like there is some weird routing issue going on. I compared the web.config's for both the current project and the sample one and they pretty much have the same entries (I thought maybe I missed something). It seems that my converted project is not recognizing the routing. Any help will be appreciated.
Here is the SurfaceController
using Umbraco.Web.Mvc;
using System.Web.Mvc;
namespace MyUmbracoApp.Controllers
{
public class ServiceStatusSurfaceController : SurfaceController
{
// can't reach this either:
public ActionResult Index()
{
return Content("hello world");
}
// this is what I am trying to reach
[ChildActionOnly]
public ActionResult ServiceStatusInfo()
{
// do some stuff to get the status
return CurrentUmbracoPage();
}
}
}
I have also tried using the "PluginController" option even though this is not a plugin with the "area" attribute but same problem.
Maybe there is a workaround that I am not aware of ?
Change StatusInfo to ServiceStatusInfo in your action call. This should match the name of the action.
#Html.Action("ServiceStatusInfo", "ServiceStatusSurface")
I have created a new control VidController
public class VidController : Controller
{
public ActionResult GetVids()
{
return View();
}
}
Right clicked inside the method and created View with default name GetVids. Now when i try to open ~/Vid/GetVids there is no page opening...
What i have to set in Global file?
Instead of opening ~/VidController/GetVids in your browser you could try /Vid/GetVids. In ASP.NET MVC the standard convention is that the Controller suffix is used for the class name but removed when resolving the route.
When you call VidController/GetVids, the routing engine is trying to find a controller named VidControllerController which obviously doesn't exist.