62

I have an asp.net web forms application running under v4.0 integrated mode.

I tried to add an apicontroller in the App_Code folder.

In the Global.asax, I added the following code

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

When I tried to navigate to the controller at http://localhost/api/Value, I get the 404 error.

The extensionless url is configured in the handler section. I have forms and anonymous authentication enabled for the website.

ExtensionLess url is configured for '*.'

When I hit the url for controller, the request is handled by StaticHandler instead of ExtensionlessUrlHandler-Integrated-4.0.

I have no clue now why the system will throw the error as shown in the image below. Error

Suneel Dixit
  • 889
  • 2
  • 10
  • 17
  • 1
    Are you sure that you don't need to use port in URL? Like `http://localhost:23243/api/ValueController` – Valin Dec 16 '13 at 22:03
  • 2
    Is there a Get method? It should likely be `/api/Value` as well, if I remember right. – Darren Kopp Dec 16 '13 at 22:06
  • I don't need port because the website is configured on port 80. – Suneel Dixit Dec 16 '13 at 22:14
  • There is a Get defined – Suneel Dixit Dec 16 '13 at 22:15
  • 2
    Do you have the MVC4 and WebApi NuGet packages (or DLLs) installed? I have never tried to use a WebApi controller in a Web Forms project. – Jesse Webb Dec 27 '13 at 16:05
  • Have you tried moving the Controller to the "Controllers" folder, or somewhere else other than the "App_Code" directory? – Jesse Webb Dec 27 '13 at 16:07
  • Can you confirm that .NET 4.5 is installed on the web server? Web API requires .NET 4.5. – jebar8 Dec 31 '13 at 21:18
  • Lot's of useful information at [ASP.Net - Api Routing](http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection) – crunchy Jan 03 '14 at 13:54
  • I just spent [too many] hours tracking this down. It worked on dev but not locally. My IIS was configured for an older version of the website. I had a application under the site with the virtual path of api/. So when I tried getting to myawesomesite.com/api/mycontroller it was looking in the application, not my website. I removed the application from the website in IIS and it worked. –  May 10 '16 at 16:59
  • @SuneelDixit u omit {action} – AminM Jul 20 '18 at 08:08

20 Answers20

116

I was experiencing this problem.

I tried editing my WebApiConfig.cs to meet a number of recommendations here and code samples elsewhere. Some worked, but it didn't explain to why the route was not working when WebApiConfig.cs was coded exactly as per the MS template WebApi project.

My actual problem was that in manually adding WebApi to my project, I had not followed the stock order of configuration calls from Global.asax

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        // This is where it "should" be
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        // The WebApi routes cannot be initialized here.
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }

I could make guesses about why this is, but I didn't investigate further. It wasn't intuitive to say the least.

shannon
  • 8,664
  • 5
  • 44
  • 74
  • 10
    Apparently the order that the routes are registered is important. First register HTTP routes, then MVC. – FishesCycle Dec 05 '14 at 16:50
  • thanks! I kept getting what I thought were CORS problems but it was in fact 404s because adding an API controller to an existing MVC project meant that the GlobalConfiguration line was missing from global.asax – zanther Apr 11 '17 at 09:38
32

The problem is in your routing configuration. Mvc routing is different from WebApi routing.

Add reference to System.Web.Http.dll, System.Web.Http.Webhost.dll and System.Net.Http.dll and then configure your API routing as follows:

   GlobalConfiguration.Configuration.Routes.MapHttpRoute(
     name: "DefaultApi",
     routeTemplate: "api/{controller}/{id}",
     defaults: new { id = System.Web.Http.RouteParameter.Optional }
   );
Leonel Sanches da Silva
  • 6,972
  • 9
  • 46
  • 66
Alborz
  • 6,843
  • 3
  • 22
  • 37
  • 2
    Also be sure to not have conflicting routes in Http Routing and in MVC routing as it causes major issues. Delete the old route and make the entire /api path ONLY for Http routing. – SlaterCodes Jan 02 '14 at 22:34
17

Ensure the following things

1.) Ensure that your IIS is configured with .NET 4.5 or 4.0 if your web api is 4.5 install 4.5 in IIS

run this command in command prompt with administrator privilege

C:\Windows\Microsoft.NET\Framework\v4.0.30319>aspnet_regiis.exe -i

2.) Change your routing to

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

and make request with Demo/Get (where demo is your controller name)

if the 1,2 are not working try 3

3.) Add following configuration in web.config file

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />

</system.webServer>
Binson Eldhose
  • 749
  • 1
  • 6
  • 14
11

Also, make sure your controller ends in the name "Controller" as in "PizzaPieController".

Eric W.
  • 7,148
  • 3
  • 20
  • 27
7

I tried all of the above and had the same problem. It turned out that the App pool created in IIS defaulted to .net 2.0. When I changed it to 4.0 then it worked again

Alan
  • 183
  • 1
  • 2
  • 5
4

Thanks Shannon, works great =>

My order in my Global.asax was :

GlobalConfiguration.Configure(WebApiConfig.Register);  
RouteConfig.RegisterRoutes(RouteTable.Routes);

instead of the good one :

RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register); 
ceinpap
  • 41
  • 2
  • Hate to point this out but this goes against the answer that the majority approve. So for all others - please scroll down to the answer that helped me and (at this point) 96 others. – Richard Housham Apr 27 '18 at 12:37
  • Somehow I changed just the opposite way. An old old application quit working after some minor changes, and really throw off for a loop. Thanks everyone. – Whoever Feb 20 '20 at 12:43
3

Also try to delete your entire api bin folder's content. Mine was containing old dlls (due to a big namespace renaming) exposing conflicting controllers. Those dll weren't deleted by Visual Studio's Clean functionality.

(However, I find asp.net web api seriously lacks routing and debugging information at the debugging level).

Sbu
  • 910
  • 11
  • 22
2

If you create the controller in App_Code how does the routing table know where it is? You have specified the route as "api/{controller/..." but that's not where the controller is located. Try moving it into the correct folder.

crunchy
  • 705
  • 1
  • 13
  • 35
2

After hours of spending time on this , i found the solution to this in my case.

It was the order of registering the Routes in RouteConfig .

We should be registering the HttpRoute in the Route table before the Default controller route . It should be as follows. Route Config Route table configuration

  public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.MapHttpRoute(
             name: "DefaultApi",
             routeTemplate: "api/{controller}/{action}/{id}",
             defaults: new { id = RouteParameter.Optional }
         );
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

    }
}
Shri Guru
  • 41
  • 5
2

Thanks to Shannon, ceinpap, and Shri Guru, the following modification works for me:

  1. WebApiConfig.cs:

    public static void Register(HttpConfiguration config)
    {
        ...
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
    
  2. Global.asax.cs:

    protected void Application_Start()
    {
        ...
        GlobalConfiguration.Configure(WebApiConfig.Register);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        ...
    }
    
zx485
  • 28,498
  • 28
  • 50
  • 59
Martin L.
  • 61
  • 4
1

For the URL you've trying (http://localhost/api/Value) make sure there's a public type named ValueController which derives from ApiController and has a public method with some of these characteristics:

  • Method name starts with Get (e.g. GetValues or simply Get).
  • There's an HttpGet attribute applied to the method.

In case you're trying the code from the default Web API project template, the name of the controller is ValuesController, not ValueController so the URL will be http://localhost/api/values.

If non of the above helps, you may want to enable tracing which can give you a useful insight on where in the pipeline the error occurs (as well as why).

Hope this helps.

volpav
  • 5,090
  • 19
  • 27
  • +1 for "'Values' in the name 'ValuesController' must match the name of the model. What a waste of time! – MTAdmin Aug 28 '14 at 20:29
1

None of solutions above solved my problem... My error was that I copied the bin files directly to production server, and then, I don't work. The 404 was gone when I publish the project to disk and copied the "published" folder to server. It's a little obvious, but, can help some one.

Tiago Gouvêa
  • 15,036
  • 4
  • 75
  • 81
1

I copied a RouteAttribute based controller dll into the bin folder, but it wasn't getting recognized as a valid controller and I was getting the 404 error on the client.

After much debugging, I found my problem. It was because the version of System.Web.Http.dll that the controller was referencing was different from the version of System.Web.Http.dll that the main project (the one containing global.asax.cs) was referencing.

Asp.Net finds the controller by reflection using code like this

internal static bool IsControllerType(Type t)
{
    return
        t != null &&
        t.IsClass &&
        t.IsVisible &&
        !t.IsAbstract &&
        typeof(IHttpController).IsAssignableFrom(t) &&
        HasValidControllerName(t);
}

Since IHttpController is different for each version of System.Web.Http.dll, the controller and the main project have to have the same reference.

tcb
  • 4,408
  • 5
  • 34
  • 51
1

We had this as well, changing .NET version from 4.5 to 4.5.1 or newer solved the issue

Eric Herlitz
  • 25,354
  • 27
  • 113
  • 157
  • 1
    Yes, I had a MVC and a Web API on 4.5, both were fine. Problems occurred when I manually move Web Web API to the MVC project, the MVC project then return 404 for Web API controller. changed to 4.5.2 resolved the problem. – ZZZ Oct 30 '16 at 10:38
1

The sequence of registering the route, was the issue in my Application_Start(). the sequence which worked for me was

AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);

earlier it was

AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register);
chaitanyasingu
  • 121
  • 1
  • 13
0

Try just using the Value part of the controller name, like this:

http://localhost/api/Value

Note: By convention, the routing engine will take a value passed as a controller name and append the word Controller to it. By putting ValueController in the URI, you were having the routing engine look for a class named ValueControllerController, which it did not find.

Karl Anderson
  • 34,606
  • 12
  • 65
  • 80
  • My mistake. In post I added Controller, but actually I am trying to navigate to http://localhost/api/Value – Suneel Dixit Dec 16 '13 at 22:14
  • In the posted screenshot, it says you are trying to get to local host/api/CustomerRegistration, do have a controller class named CustomerRegistrationController? – Karl Anderson Dec 16 '13 at 23:46
  • Yes..I do have the CustomerRegistrationController. I attached the screen shot of what I seeing when I try to navigate to any webapi controller. – Suneel Dixit Dec 17 '13 at 00:01
0

Your route configuration looks good. Double check the handlers section in web.config, for integrated mode this is the proper way to use ExtensionLessUrlHandler:

<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

More on this topic: http://blogs.msdn.com/b/tmarq/archive/2010/05/26/how-extensionless-urls-are-handled-by-asp-net-v4.aspx

dbalogh
  • 216
  • 1
  • 5
0

Time for me to add my silly oversight to the list here: I mistyped my webapi default route path.

Original:

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

Fixed: (observe the curly braces around "id")

config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional}
        );
Mansfield
  • 14,445
  • 18
  • 76
  • 112
0

I appreciate this is a very old question but I thought I would add another answer for future users.

I found this to happen just now in a project I was working on only after it was deployed to CI/Staging. The solution was to toggle the compilation debug="true" value back and forth while deploying each version to each environment once, and it would fix itself for me.

Lari Tuomisto
  • 198
  • 1
  • 1
  • 11
0

In my case I forgot to make it derive from ApiController.

So it would look like

public class ValuesController : ApiController
aoakeson
  • 602
  • 1
  • 8
  • 20