WebApi routing for asp.net WebForms returns 404

I'm having problems setting up WebApi routes in asp.net WebForms application.

In the global.asax file, I have something like this:

 void Application_Start(object sender, EventArgs e) { GlobalConfiguration.Configure(WebApiConfig.Register); } 

I have another file with this code:

 using System.Web.Http; namespace WebConfig { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}", defaults: new { id = System.Web.Http.RouteParameter.Optional }); } } } 

Then, in the root, I have a folder called api, and in this folder I have a file that contains a class that looks something like this:

 public class MyController : ApiController { [Route("MyController")] [HttpPost] public HttpResponseMessage Post([FromBody]string value) {....} 

And finally, in my client code, I have this ajax call:

 $.ajax({ url: "/api/MyController", contentType: "application/json; charset=utf-8", type: "POST", dataType: "json", cache: "false", data: someData}); 

However, when I run this code, all I get is a 404 error. What do I need to change in the routing mechanism to make this work?

Thanks.

+6
source share
8 answers

Well, after more than two weeks of thinking about why something seems to just not work, I finally figured it out !!!!!

The problem with this sentence is:

Then, in the root, I have a folder called api and in this folder I have a file containing ... a web server API file

The solution turned out to be a 10 second fix:

Place the file MyWebAPIController.cs in the App_Code folder

What I had was a .cs file was in the root directory called /api because I mistakenly thought that if you want to call the web service from the /api/MyController client you need to create a directory that matches this path, and then put the controller in this directory. Instead, you should put the controller file in the App_Code directory.

LB2's answer helped me with attributes, use both [RoutePrefix] and [Route] :

 [RoutePrefix("api")] public class MyController : ApiController { [Route("MyController")] public HttpResponseMessage Post([FromBody]string value) 

and then you can call it like this:

 $.ajax({ url: "/api/MyController", type:POST, ...}); 

Thanks for watching this question!

+1
source

I think the others were very close. Try the following:

 [RoutePrefix("api")] // or maybe "api/", can't recall OTTOMH... public class MyController : ApiController { [Route("MyController")] [HttpPost] public HttpResponseMessage Post([FromBody]string value) 

and then request /api/MyController

If this does not work, use RouteDebugger to analyze your routes and why it rejects the match. Change your question with what you see in RouteDebugger so that I can track what doesn't match.

In addition, you may need to call MapHttpAttributeRoutes in your Register function, but not sure about it.


Edit

Now, when I look at him again, I think I see more problems with him.

First, start with the template:

Here is what you have (from your question):

 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}", defaults: new { id = System.Web.Http.RouteParameter.Optional }); 

The odd part here is that your template does not have a {id} segment, but is defined as optional. It looks like it is missing from the template and the route should be changed to:

 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = System.Web.Http.RouteParameter.Optional }); 

Note that you also removed the default action - I'm not sure that MVC automatically uses the method search convention method named Post , but I suppose it does.

The second problem is that your method signature (again from your question):

 public HttpResponseMessage Post([FromBody]string value) 

It defines a Post that takes a parameter named value , while your route defines a parameter called id . Therefore, there is another mismatch. You can rename a variable or decorate (see below). In addition, {id} optionally marked, but I believe (and I don’t remember OTTOMH exactly) you need to specify a default value for those cases when {id} not provided, and therefore are combined together:

 public HttpResponseMessage Post([FromBody(Name="id")]string value = null) 

This should fix it, although there may be more problems ... but let's start with them.

+2
source

Change url: "/api/MyController" to url: "/api/My"

+1
source

Did you think you were using route attributes instead? I find them easier than route configurations.

 public class MyController : ApiController { [Authorize] [Route("MyController")] [HttpPost] public HttpResponseMessage Post([FromBody]string value) {....} } 

perhaps you can also try customizing your routes inside the dedicated RouteConfig class, which also supports mvc4. My route configuration settings are as follows:

 /// <summary> /// The route config class /// </summary> public class RouteConfig { /// <summary> /// Registers the routes. /// </summary> /// <param name="routes">The routes.</param> 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 } ); } } 
+1
source

Your RouteAttribute parameter overrides the configuration settings, so you have two options:

1) remove RouteAttribute and use the URL: /api/my

2) hold RouteAttribute and use URL /MyController (in this case configuration parameters are ignored)

From the comments, I see that you want to go to: api/MyController . So the third option is not tested, but I think it can work:

3) [Route("api/MyController")]

+1
source

Use [RoutePrefix] in your controller class

 [RoutePrefix("api/My")] public class MyController : ApiController { [Route("MyController")] [HttpPost] public HttpResponseMessage Post([FromBody]string value) {....} } 

Then you can go to api / My / MyController

+1
source

Change [Route("MyController")] to [Route("api/MyController")] .

Then it will work as you expect.

+1
source

My problems were somewhat different. My setup is an asp.net webforms project and using VS2013. I wanted to introduce Web Api. The crooked ball was the implementation of my web forms on VB.net.

I wanted to write my APIs in C #, so I had to enable the codeSubDirectories parameter via web.config.

 <codeSubDirectories> <add directoryName="VBCode"/> <add directoryName="CSCode"/> </codeSubDirectories> 

I created two folders (VBCode and CSCode) in the App_Code folder, respectively.

Then I moved all my vb.net classes to a VBCode subdirectory.

Created UserController.cs under CSCode and wrote regular web api code.

 using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace WebAPIDemo { public class UserController : ApiController { static IUserRepository _repo = new UserRepository(); // GET api/<controller> public IEnumerable<Users> GetAllUsers() { return _repo.GetAllUsers(); } // GET api/<controller>/5 public IHttpActionResult GetUserById(int id) { return Json(_repo.GetUserById(id)); } 

Changed global.asax value

 <%@ Application Language="VB" %> <%@ Import Namespace="System.Web.Routing" %> <%@ Import Namespace="System.Web.Http" %> <script RunAt="server"> Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs) ' Code that runs on application startup RouteTable.Routes.MapHttpRoute( "defaultApi", "api/{controller}/{action}/{id}", defaults:=New With {.id = System.Web.Http.RouteParameter.Optional}) End Sub 

The api call worked with and without this decorator [RoutePrefix ("api")].

Took me a few hours to understand this implementation.

 Call 1: http://localhost:60203/api/user/getuserbyid/2 Result: {"Id":2,"FirstName":"Alan","LastName":"Wake","Company":"XYZ Corp","Email":" alan@xyz.com ","PhoneNo":"64649879"} Call 2: http://localhost:60203/api/user/getallusers Result: <ArrayOfUsers xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WebAPIDemo"> <Users> <Company>ABC</Company> <Email> madhur@abc.com </Email> <FirstName>Madhur</FirstName> <Id>1</Id> <LastName>Kapoor</LastName> <PhoneNo>65431546</PhoneNo> </Users> <Users> <Company>XYZ Corp</Company> <Email> alan@xyz.com </Email> <FirstName>Alan</FirstName> <Id>2</Id> <LastName>Wake</LastName> <PhoneNo>64649879</PhoneNo> </Users> </ArrayOfUsers> 
0
source

All Articles