Lenny
Lenny

Reputation: 195

WebApi Controller Get Action Doesn't Work

I'm having trouble with one of my WebApi2 controllers. While writing tests I've discovered the Get() is never hit instead it returns a 301 followed by 403. Oddly if I hit Get(id) the second action speaks up and does its job, but I can never hit the Get() action. If I rename the controller it works properly, but sadly, I cannot rename ModelsController to ModelController as I would like since there is an existing user base expecting that name. This is a rewrite of an existing Api that was done in MVC2 I think. All the other controllers work great, just not this one.

Any thoughts as to how to debug this? Or what I may have missed?

Other notes: The routing configuration is default. There is no other ModelsController to be found

Below is a simplified version of my code, and the problem remains...

using System.Collections.Generic;
using System.Web.Http;
using TW.Api.Business.Services.Models;

namespace TW.Api.Business.Services.Controllers
{
    public class ModelsController : ApiController
    {
        public string Get()
        {
            return null;
        }

        public string Get(string id)
        {
            return null;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Routing;

namespace tw.api.business
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // config.MapHttpAttributeRoutes();


            config.Routes.MapHttpRoute(
                name: "Api_GetWithChild",
                routeTemplate: "{controller}/{id}/{action}/{childId}",
                defaults: new { id = RouteParameter.Optional, action = "Get", childId = RouteParameter.Optional },
                constraints: new { httpMethod = new HttpMethodConstraint("GET") });

            config.Routes.MapHttpRoute(
              name: "Api_Post",
              routeTemplate: "{controller}/{id}/{action}/{childId}",
              defaults: new { id = RouteParameter.Optional, action = "Post", childId = RouteParameter.Optional },
              constraints: new { httpMethod = new HttpMethodConstraint("POST") });

            config.Routes.MapHttpRoute(
            name: "Api_Put",
            routeTemplate: "{controller}/{id}/{action}/{childId}",
            defaults: new { id = RouteParameter.Optional, action = "Put", childId = RouteParameter.Optional },
            constraints: new { httpMethod = new HttpMethodConstraint("PUT") });

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

            // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
            // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
            // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
            //config.EnableQuerySupport();

            // To disable tracing in your application, please comment out or remove the following line of code
            // For more information, refer to: http://www.asp.net/web-api
            //config.EnableSystemDiagnosticsTracing();
        }
    }
}




using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace tw.api.business
{
    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 }
            );
        }
    }
}

Upvotes: 2

Views: 2823

Answers (2)

Traze
Traze

Reputation: 180

When creating methods for web-API end-points, you must follow some naming conventions for automatically mapping of method-to-api. Or you can override that using HTTP action and Route attributes

Follow either of the following arrangements (note the 'Model' and 'Models' in method names):

public class ModelsController : ApiController
{
    public string GetModels()
    {
        return null;
    }

    public string GetModel(int id)
    {
        return null;
    }
}

Or, use the route attributes:

public class ModelsController : ApiController
{
    [HttpGet]
    [Route("api/Models")]
    public string GetModels()
    {
        return null;
    }

    [HttpGet]
    [Route("api/Models/{id}")]
    public string GetModel(string id)
    {
        return null;
    }
}

Ref: Routing and Action Selection

Upvotes: 1

Yishai Galatzer
Yishai Galatzer

Reputation: 8862

Looking at your route config, there are a few issues

  1. The constrained routes are not really necessary
  2. The id being optional in a middle of a route pattern doesn't really work, your optional items should come at the end.

Upvotes: 1

Related Questions