MVC Controller not being reached in Web API Project - asp.net-mvc

I have a Web Api project which needs to return an MVC styled View. I have made my MVC Controller as such
public class MVCController: Controller
{
[HttpGet]
[Route("api/mvc/test")]
public ActionResult test()
{
return View();
}
}
However, When i try to access this controller from the web, i cant seem to reach the controller. I get the following error:
{"Message":"No HTTP resource was found that matches the request URI 'http://localhost/foo/api/mvc/test'.","MessageDetail":"No type was found that matches the controller named 'mvc'."}
After doing searches on google, people seem to be telling me to change routing properties in the webapiconfig to
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
But i still seem to be having no luck. IF HOWEVER i change my controller to an webapi controller as such
public class MVCController: ApiController
{
[HttpGet]
[Route("api/mvc/test")]
public IHttpActionResult test()
{
return Ok();
}
}
I can reach the controller.. If someone could give me some insight to as what is going on, it would be much appreciated.
UPDATE
After reading the response below, I have updated my controller to look like this:
public class MVCController: Controller
{
[HttpGet]
public ActionResult test()
{
return View();
}
}
However, localhost/MVCController/test still seems to give me a 404 error and the Controller is not being hit. Sorry for my newbieness by the way.

I bet you have a file called WebApiConfig.cs which has this code.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
This is where the routing pattern is defined for the web api controllers. So any request coming with api/something will be considered as a request for web api endpoint because you must have invoked the WebApiConfig.Register call before registering the routes for mvc controllers. The Order of registering routes really matters.
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register); // first one
RouteConfig.RegisterRoutes(RouteTable.Routes); //second one
}
Since the order of registration matters, when a request comes with api/something, it will be matched against the route registration for web apis and framework will try to look for matching web api controller.s
If you swap the order of calling the route registration method, your request will work. but that might affect other parts when you try to access web api controllers.
BTW, Are you sure you want to have api/ in the route pattern for your MVC controller ? Unless you really want some different url patten than the normal convention(*controllername/action*), just remove the Route attribute it self. With the default route definition, it will work for yourSite/mvc/test request.

Related

Difference between Web API (standalone) and Web API ASP.NET MVC

I've created both an ASP.NET MVC project which includes the Web API and I created an empty project where only Web API was selected and I'm trying to understand why they are behaving differently.
Both of them from what I can tell have the routing definition defined as follows:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
But I'd like to understand why the functions that are defined in the controller are behaving differently.
In my ASP.NET MVC Solution, I can create multiple functions under the one controller:
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
I don't have to add any attributes, well at least for gets and I can call individual function as:
http://localhost/api/test/GetProduct/1
http://localhost/api/test/GetProducts
In the Web API only solution, I had to define it as:
public IHttpActionResult HelloWorld()
{
return Ok("Hello World");
}
but the above will not work unless I add the [HttpGet] attribute to my HelloWorld function.
Also I don't seem to be able to define multiple functions within the one controller as it is done the in ASP.NET MVC Solution. Defining the same function as above just does not work or even if I define the functions below
[HttpGet]
public IHttpActionResult HelloWorld()
{
return Ok("Hello World");
}
[HttpGet]
public IHttpActionResult GetTime()
{
return Ok(DateTime.Now.ToString());
}
I get the following error:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Multiple actions were found that match the request: HelloWorld on type
MyProject.Controllers.TestController GetTime on type
MyProject.Controllers.TestController
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace>
at
System.Web.Http.Controllers.ApiControllerActionSelector.
ActionSelectorCacheItem.SelectAction(HttpControllerContext
controllerContext) at System.Web.Http.ApiController.
ExecuteAsync(HttpControllerContext controllerContext, CancellationToken
cancellationToken) at System.Web.Http.Dispatcher.
HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
</StackTrace>
When I define a single function, it works but contrarily to a Web API defined in my ASP.NET MVC solution, when I call the below
http://localhost/api/test/HelloWorld
It doesn't seem to care what the function name is called as it will work if I call any of the following:
http://localhost/api/test
http://localhost/api/test/GoodBye
and will only fail if I provide an invalid controller name i.e.
http://localhost/api/mytest
Can you explain the difference between the 2 and ideally what do I have to do to get a stand-alone Web API to behave the same way as it does when defined in Asp.net MVC
Thanks.
UPDATE-1
Below are 2 good examples where the behavior is clearly different but I can't see why as both are called "Web API with ASP.NET MVC".
Creating Simple Service with ASP.NET MVC Web API to be accessed by Windows Store and Windows Phone Application
Getting Started with ASP.NET Web API 2 (C#)
Edit:
I'm sry at first I misunderstood your enquiry and therefore gave you the wrong answer to your question.
In Web Api you can't define two functions that serve the exact same path. But you can overload them like you would with Functions.
public IEnumerable<Product> GetAllProducts() {}
public IHttpActionResult GetProduct(int id) {}
These two function differ in so far that they serve different paths:
localhost/api/products/
localhost/api/products/{id}/
The following functions on the other hand both serve localhost/api/test/
[HttpGet]
public IHttpActionResult HelloWorld()
{
return Ok("Hello World");
}
[HttpGet]
public IHttpActionResult GetTime()
{
return Ok(DateTime.Now.ToString());
}
Your second concern has been the naming and mostly why you can't define HelloWorld() without [HttpGet]. That is because Web Api automatically maps functions that have a keyword such as Get or Delete as part of their name to the corresponding Http Function.
Adding the Http-Attribute is only needed if the function name does not conform to these naming conventions or shall serve multiple Http-Methods. It's described here
I hope your questions are now answered.
Orig:
The Default Routing and subsequent decision on what Function is to be executed is different between MVC and Web API
Default Web Api:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Default Mvc:
config.Routes.MapHttpRoute(
name: "DefaultMvc",
routeTemplate: "/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
For Web Api the Routing is dependant on the controller name and further which Http-Method has been selected as well as the controller actually having a function the has been tagged with this method. Hence the and further Tags
Mvc on the other hand routes via the controller name and the action name to the desired functionality.
Web Api 2 adds further possibilies in letting you define AttributeRoutes. You may want to look further on this topic here and here

Creating Api controller in asp .net mvc

I have created controller called ApiConroller in MVC project. When I tried to run its Index() action method it returns the below error message:
This XML file does not appear to have any style information associated
with it. The document tree is shown below. No HTTP
resource was found that matches the request URI
'http://localhost:60000/api/index'.
Why it is returning xml file? How to make it return a view?
/api/ is part of the default mapping for the Web Api routing, as shown here:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
If you're not using Web Api, make sure you remove those route maps by removing the WebApiConfig file from your project and/or removing WebApiConfig.Register(GlobalConfiguration.Configuration) from the Global.asax file.
If you are using Web Api somewhere, you'll need to change the routing noted above.

Web API Attribute Routing in MVC area not working

I have an existing MVC project. I added a new area and this area will be web api. My web api routes are not being hit and since routing is still a frustrating thing for me I'm sure I'm doing something wrong.
In my route provider I thought this was all I had to do...
public void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
}
In my controller:
[RoutePrefix("api/nav")]
public partial class NavigationController : ApiController
{
[HttpGet]
[Route("MainDash")]
public DashboardModel GetDashItems()
{ ...}
}
My MVC area is defined as MyArea,
So in fiddler the following Get request return 404.
/MyArea/api/nav/MainDash
/api/nav/MainDash
Do I still have to define old fashioned conventional routes as well?
When I register my route I do set a default template...but the attribute routing should override...???
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new {controller="Home", action = "Index", area = "MyArea", id = "" },
new[] { "Testing.Nav.Controllers" }
);
}
I really don't think this has anything to do with it but I am at a loss for getting my routes figured out.
TIA
Update
Forgot this controller is also NOT in the controllers folder. It is in a folder called Api.
I tried /api/api/nav/GetDashIyems but still didn't work. But I wonder do I need to add the Api folder to the route table as an area to search...???

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

Controller action "Index" not invoked with default setting

I have a ASP.NET web application project, I implemented a WebApi controller and now proceeding with a MVC controller.
I've added a new MVC controller (eg. "Test") and selected to add it with "empty read and write actions".
The controller is created with various CRUD methods, however the Index action is behaving unexpectedly.
By default the Index action does not take any arguments:
public ActionResult Index()
{
return View();
}
Now if I try to invoke this method using url "/Test/Index", the method is not being called.
But if I type url "/Test/Index/1" the Index action is run.
It looks to me that its related to routing so I checked the RouteConfig class which looks like:
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 }
);
}
Id is set to optional and my understanding is I should not be required to provide a parameter value in Index method?
I created another project and checked this behavior and it works fine.
So wondering what in this project making MVC controller behaving differently?
Is mixing WebApi controllers with MVC controllers having some side effect (making it a special case)?
Let me know if you need any information to answer this question.
Update:
I did modify the WebApiConfig for making API controller work as per my requirement, it looks like this:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}",
defaults: new { controller = "iclock", action = "cdata" }
);
}
I could not understand why it affect the MVC controller route? I got it now with answers provided.
Update 2:
The problem in this case is I can not (or can I?) prefix api in web api route as a third party device is sending GET and POST request using a fixed url, like following:
GET /iclock/cdata?SN=xxxxxx&options=all&pushver=2.0.2&language=XX
GET /iclock/cdata?SN=xxxxxx&type=time
POST /iclock/cdata?SN=123456&table=ATTLOG&Stamp=2011-04-05T17:40:20
I achieved above request handling functionality making changes into the WebApiConfig route. Now need a front end UI for which I am developing a MVC controller with CRUD operation.
What should be ideal approach in this case?
It could be when you navigate to Test/Index it doesn't know if it should use the web route where there is an optional "id" or the api route where there is no "id". If possible I would prefix your Web API routes, such as "api/{controller}/{action}" as described in the MVC Web API template.
For your second example, applications that access the API would simple prefix the URLs with "api/". If they are using the URLs you specified and cannot be changed, then I think you may be stuck because when the request comes in there is still the problem of not knowing which route to use.
If the URLs can be changed, as mentioned above, simple prefix with "api/".
EDIT: Updated my answer based on the extra information/code-snippet provided.
EDIT: Updated again
Did you look in WebApiConfig instead of RouteConfig in App_Start
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
You have a conflict in your routing table. Your Web API routing table is now the same as your standard MVC routing table. Your Web API routing table (the one that is initialized with MapHttpRoute should be declared as: routeTemplate: "api/{controller}/{id}". Also, you shouldn't have modified the Web API route. It is not cast in stone that it must be api/{controller}/{id}, but there is a certain convention that you should follow. Try reseting your routes to be like the following and then try again:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
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 }
);
}
}
So, first reset to normal routing configuration and test. After that make changes slowly and follow the result.

Resources