Simple MVC route does not work - asp.net-mvc

I've created a new MVC project. I've created an empty controller called APIController:
public class APIController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Test()
{
return View();
}
}
I've created the corresponding views, which are empty apart from the word 'index' and 'test'.
When I go to myurl.com/Account it works
When I go to myurl.com/Account/Test I get an xml error saying:
No HTTP resource was found that matches the request URI [...]
No type was found that matches the controller named 'Account'.
This must be a noob error. Everything else in the project is default. The RegisterRoutes method is the default:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
What silly thing am I missing?
Bonus points if you can explain why the error is an XML error and not the standard yellow screen of death...

Problem solved.
Turns out if you call your controller APIController MVC treats it completely differently. Renaming it to ABCController worked great.
I'm not writing an API, I'm writing a website that manages an API!
Argh, thanks MVC!

Can you check if the controller you created is inheriting ApiController instead of the standard Controller?
This would also explain why the error message is being returned in XML.

Related

Can't access (404) ASPX from a View directory while HTML and (normal) ASPX are accessible

I can access Ping.HTML and Ping.ASPX but when I try to access the view from my MVC (4.0) project (deployed to the same server, the bogus one, by F5), I get 404.
It's a vanilla project created from the template for MVC 4 with a very default view and controller (no model).
Hints on how to resolved it? I'm out of ideas...
EDIT
My RouteConfig.cs is like this
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {
controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Controllers folder contains only one, single file called ÄDefault1Controller.cs*. It only does this:
public class Default1Controller : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Test()
{
return View();
}
}
EDIT
The exact URLs typed in (besides the server name alone, of course) are:
> http://localhost:49642/Index
> http://localhost:49642/Index.aspx
> http://localhost:49642/Home/Index
> http://localhost:49642/Home/Index.aspx
> http://localhost:49642/Default/Index
> http://localhost:49642/Default/Index.aspx
Based on the information you've given, it sounds like a routing problem. The URL you are requesting isn't firing a controller.
EDIT
MVC works by convention, so by naming your controller Default1Controller the matching URL would start with /Default1.
In the example you've given, you can only access the Test() method by navigating to http://localhost:49642/Default1/Test, which will return the view typically located at /Views/Default1/Test.aspx (or /Views/Default1/Test.cshtml for razor-based views).
Please check out the routing overview at ASP.NET for more information about how the route table maps to controllers and actions. I should point out that the link is for the older versions of MVC, but you should get the idea.
Let me know if I can help further.
Matt

ASP MVC controller not triggering

I know this is a common issue, but I have tried so many things and I just cannot figure this out. I am generating two links:
http://localhost:1757/ViewReport/DeleteFileFromServer?id=orderedList2.png&reportid=3f66320f-a092-4c5e-8321-3a0b6def68c2
http://localhost:1757/ViewReport/Downloading?id=orderedList7.png&reportid=3f66320f-a092-4c5e-8321-3a0b6def68c2
And am attempting to trigger the underlying controller from these 2 urls.
My routeconfig has one entry in it, which is the default one:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional}
);
And my two controller functions are:
[HttpGet]
public void Downloading(string id,string reportid){//code}
[HttpGet]
private void DeleteFileFromServer(string id, string reportid){//code}
Downloading gets called when using its url, but DeleteFileFromServer NEVER gets called, even though they have almost an identical url except for the controller name. There is NO special entry in route config, so I cannot figure this out. Any ideas? Thank you.
DeleteFileFromServer is marked private. Make it public.
Look at the scope of the methods, one is private and the other is public, both should be public
[HttpGet]
public void Downloading(string id,string reportid){//code}
[HttpGet]
public void DeleteFileFromServer(string id, string reportid){//code}

No type was found that matches the controller named 'User'

I'm trying to navigate to a page which its URL is in the following format:
localhost:xxxxx/User/{id}/VerifyEmail?secretKey=xxxxxxxxxxxxxxx
I've added a new route in the RouteConfig.cs file and so my RouteConfig.cs looks like this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "VerifyEmail",
url: "User/{id}/VerifyEmail",
defaults: new { controller = "User", action = "VerifyEmail" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index",
id = UrlParameter.Optional }
);
}
}
Unfortunately, when trying to navigate to that URL I get this page:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:52684/User/f2acc4d0-2e03-4d72-99b6-9b9b85bd661a/VerifyEmail?secretKey=e9bf3924-681c-4afc-a8b0-3fd58eba93fe'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'User'.
</MessageDetail>
</Error>
and here is my UserController:
public class UserController : Controller
{
// GET /User/{id}/VerifyEmail
[HttpGet]
public ActionResult VerifyEmail(string id, string secretKey)
{
try
{
User user = UsersBL.Instance.Verify(id, secretKey);
//logger.Debug(String.Format("User %s just signed-in in by email.",
user.DebugDescription()));
}
catch (Exception e)
{
throw new Exception("Failed", e);
}
return View();
}
}
Please tell me what am I doing wrong?
In my case, the controller was defined as:
public class DocumentAPI : ApiController
{
}
Changing it to the following worked!
public class DocumentAPIController : ApiController
{
}
The class name has to end with Controller!
Edit: As #Corey Alix has suggested, please make sure that the controller has a public access modifier; non-public controllers are ignored by the route handler!
In my case after spending almost 30 minutes trying to fix the problem, I found what was causing it:
My route defined in WebApiConfig.cs was like this:
config.Routes.MapHttpRoute(
name: "ControllersApi",
routeTemplate: "{controller}/{action}"
);
and it should be like this:
config.Routes.MapHttpRoute(
name: "ControllersApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
as you see it was interfering with the standard route defined in RouteConfig.cs.
In my case I was using Web API and I did not have the public defined for my controller class.
Things to check for Web API:
Controller Class is declares as public
Controller Class implements ApiController : ApiController
Controller Class name needs to end in Controller
Check that your url has the /api/ prefix. eg. 'host:port/api/{controller}/{actionMethod}'
Another solution could be to set the controllers class permission to public.
set this:
class DocumentAPIController : ApiController
{
}
to:
public class DocumentAPIController : ApiController
{
}
In my case I wanted to create a Web API controller, but, because of inattention, my controller was inherited from Controller instead of ApiController.
In my case, the routing was defined as:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{*catchall}",
defaults: new { controller = "WarehouseController" }
while Controller needs to be dropped in the config:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{*catchall}",
defaults: new { controller = "Warehouse" }
In my case I was seeing this because I had two controllers with the same name:
One for handling Customer orders called CustomersController and the other for getting events also called CustomersController
I had missed the duplication, I renamed the events one to CustomerEventsController and it worked perfectly
In my case it was a case of over-aggressive caching by the WebHostHttpControllerTypeResolver.
Fix:
Delete all files (or in my case just any files named "MS-ApiControllerTypeCache.xml") under this path:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root
Restart the app pool
credit: https://sitecore.stackexchange.com/questions/9897/webapi-controllers-not-being-found-in-sitecore-8-2
Faced the same problem. Checked all the answers here but my problem was in namespacing.
Routing attributes exists in System.Web.Mvc and in System.Web.Http. My usings included Mvc namespace and it was the reason. For webapi u need to use System.Net.Http.
Experienced this similar issue. We are dealing with multiple APIs and we were hitting the wrong port number and getting this error. Took us forever to realize. Make sure the port of the api you are hitting is the correct port.
I have also faced the same problem. I searched a lot and found that the class level permission is needed. by default, the class permission level is internal so I thought that it won't affect the program execution. But it got affected actually, you should give your class permission as public so that, you won't face any problem.
And one more. if it is webapi project, your webapirouteconfig file will overwrite the routeconfig.cs file settings. So update the webapi routeconfig file as well to work properly.
In my solution, I have a project called "P420" and into other project I had a P420Controller.
When .NET cut controller name to find route, conflict with other project, used as a library into.
Hope it helps.
In my case I was calling the APi like
http://locahost:56159/api/loginDataController/GetLoginData
while it should be like
http://locahost:56159/api/loginData/GetLoginData
removed Controller from URL and it started working ...
Peace!
In my solution, when I added the my new Controller to the project, the wizard asked me if I want to set the location of the controller into the App_Code folder.
The wizard warned me, if I do not locate it into the the App_Code folder, the controller type won't be found.
But I didn't read the whole warning, because I wanted to locate the file to elsewhere..
so that's why it didn't work for me.
After I added a new controller and let it to be in the App_Code by default, everything worked.
And one more answer to this for good measure...
In my case another project had been accidentally added as a reference by someone which brought in all of that project's controllers and causing route conflicts. Removing it and moving the code that was needed from it to a better place where it could be referenced without bringing in all of the controllers was the solution.
Go to the location
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root and find withe the file name "MS-ApiControllerTypeCache.xml"
and
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root
Delete all files named MS-ApiControllerTypeCache.xml from the root folder.
For my case, the issue ought to be addressed this way

ASP.Net MVC 4. Routing a controller in a separate assembly returns error 404

I am trying to perform what looks like a straightforward task - calling a controller from a separate assembly in my project.
However, when I requesting information from that controller I'm getting error 404. I have been fighting with it for last 5-6 hours and I suspect that I may be missing something small and obvious, that is why I hope for an advise.
I found on stakoverflow similar question about routing and error 404, but as I implemented another prototype project where I didn't get such error and use a similar code structure, I believe that the problem they describe is different from mine.
For a general picture - the overall goal of what I want to achieve is implementing an area inside an independent project like it is described here.
I did everything like it is explained in the link for a small prototype (and it works perfectly) and now trying to apply for the real project.
This is how I include an assembly and manage routes:
There is a main project with one of the Areas representing a hidden child project "CommunicationBus"
"CommunicationBus" project contains a class "CommunicationBusAreaRegistration". Registering a route works correctly, I can get here with debugger and also I can see this route when I use routedebugger (see screenshot below). I also played with namespace for this class, tried to add .Areas.CommunicationBus in the end, but it didn't make any difference I could notice.
namespace MBVD.MainProject.UI
{
public class CommunicationBusAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "CommunicationBus";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"CommunicationBus_default",
"CommunicationBus/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
new string[] { "CommunicationBus.Controllers" }
);
}
}
}
In the Global.asax of the main project I register routes the following way:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "MBVD.MainProject.UI.Controllers" }
);
}
If I reference here "CommunicationBus.Controllers", I can no longer open pages of the main application. However, I believe I need to register here only path to the controllers of the main application
Output path for CommunicationBus project is set to bin folder of the main project. Every time I build CommunicationBus I get a fresh .dll in the main project.
I added a simple controllers to the CommunicationBus project:
namespace CommunicationBus.Controllers
{
public class TestController : Controller
{
[HttpGet]
public string Index()
{
return "It works!";
}
}
}
I added a link to the main project
#Html.ActionLink("test","Index","Test", new {Area="CommunicationBus"}, null)
which is:
localhost:63254/CommunicationBus/Test
I use routedebugger and it doesn't show anything suspicious:
I use ASP.NET MVC 4 for both projects.
I would appreciate any ideas on what I can do to figure out why I'm getting this error.
I believe you are getting this error because of your routing order. Since /CommunicationBus/Test matches both /{controller}/{action}/{id} and /CommunicationBus/{controller}/{action}/{id} the first registered route (/{controller}/{action}/{id}) is taking precedence over the desired route, and MVC can't find a controller in the default namespace (MBVD.MainProject.UI.Controllers) called CommunicationBus.
Try registering your Area routes before your default route. Or, you can just skip that business all together and use Attribute Routing (http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx). If you go with Attribute Routing, you will need to ensure you are loading controllers from all namespaces before calling routes.MapMvcAttributeRoutes(); (if you are just including as a reference, this is no problem, it only becomes an issue if you are dynamically loading the reference).

Why do you need a route defined for Html.Action?

I have created an otherwise empty ASP.NET MVC 3 application with 2 controllers, HomeController and OtherController.
HomeController.cs looks like this:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
Index.cshtml looks like this:
#Html.Action("Index", "Other")
And, of course, Othercontroller.cs:
public class OtherController : Controller
{
[ChildActionOnly]
public ActionResult Index()
{
return Content("OK!");
}
}
So far, so good. I run the app, and it tells me everything is OK!
Now, I take the default RegisterRoutes from Global.asax.cs:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
And I crumple it up, so that no routes match OtherController:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default", "", new { controller = "Home", action = "Index" });
}
Now, when I run the page, it crashes with this error message:
System.InvalidOperationException: No route in the route table matches the supplied values.
Source Error:
Line 1: #Html.Action("Index", "Other")
I specified the controller name and action name in the call to .Action. No URLs are being generated, and no requests are being made. Why does routing even need to get involved?
I think that this blog post will help you understand a little more:
http://blogs.charteris.com/blogs/gopalk/archive/2009/01/20/how-does-asp-net-mvc-work.aspx.
Essentially, routing is involved in determining which controller to 'fire up' to handle the request and appropriate action to invoke based on the parameters that you sent and the MVCRouteHandler uses those to make a decision. Just because you tell it which controller in your action does not make it magically ignore the routing table, go straight to that controller class and bypass all the other MVC goodness that happens in the back-end. Remember, these #HTML.Action methods can take a whole lot of overloads which could influence which route in the routing table to use (think URL structure for instance).
The MVC paths are not to static content and as such, have to be parsed through the URLRoutingModule which uses the routing table to decide on what to do. Since you have no matching route - you get an error.
EDIT
In my diatribe, I did not actually address your final statement. You're right, no URL was generated, but a request to the application was generated. HTML.Action still will use routing to determine what controller, action, area, parameters to use. I think it be fair to say in simple terms that it's like generating an ActionLink and clicking it for you.
Routing got involved by using Html.Action on a controller. When the engine couldn't find the "Other" HtmlHelper with an action of "Index" it defaulted to executing that path which means passing through routing. No route matched so it threw an error.
InvalidOperationException The required virtual path data cannot be found.
http://msdn.microsoft.com/en-us/library/ee721266.aspx
The solution for me was as follows:
I had the following line that was giving me an error:
#{Html.RenderAction("ActionName", "ControllerName");}
Adding a thrid parameter solved the error:
#{Html.RenderAction("ActionName", "ControllerName", new { area = string.Empty });}

Resources