45
votes

I'm relatively new to the MVC framework but I do have a functioning Web Project with an API controller that utilizes AttributeRouting (NuGet package) - however, I'm starting another project and it just does not want to follow the routes I put in place.

Controller:

public class BlazrController : ApiController
{
    private readonly BlazrDBContext dbContext = null;
    private readonly IAuthProvider authProvider = null;

    public const String HEADER_APIKEY = "apikey";
    public const String HEADER_USERNAME = "username";

    private Boolean CheckSession()
    {
        IEnumerable<String> tmp = null;
        List<String> apiKey = null;
        List<String> userName = null;

        if (!Request.Headers.TryGetValues(HEADER_APIKEY, out tmp)) return false;
        apiKey = tmp.ToList();

        if (!Request.Headers.TryGetValues(HEADER_USERNAME, out tmp)) return false;
        userName = tmp.ToList();

        for (int i = 0; i < Math.Min(apiKey.Count(), userName.Count()); i++)
            if (!authProvider.IsValidKey(userName[i], apiKey[i])) return false;

        return true;
    }

    public BlazrController(BlazrDBContext db, IAuthProvider auth)
    {
        dbContext = db;
        authProvider = auth;
    }

    [GET("/api/q/users")]
    public IEnumerable<string> Get()
    {

        return new string[] { "value1", "value2" };
    }

    [GET("api/q/usersauth")]
    public string GetAuth()
    {
        if (!CheckSession()) return "You are not authorized";

        return "You are authorized";
    }
}

AttributeRoutingConfig.cs

public static class AttributeRoutingConfig
{
    public static void RegisterRoutes(RouteCollection routes) 
    {    
        // See http://github.com/mccalltd/AttributeRouting/wiki for more options.
        // To debug routes locally using the built in ASP.NET development server, go to /routes.axd

        routes.MapAttributeRoutes();
    }

    public static void Start() 
    {
        RegisterRoutes(RouteTable.Routes);
    }
}

Global.asax.cs:

// Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

When I try to navigate to /api/q/users - I get a 404 not found error. If I change the routes to be "/api/blazr/users" - I get an error about multiple actions and not being able to determine which action to take.

Any help is appreciated - I really just need a small nudge to figure out where the issue is, no need to solve it completely for me (I need to learn!)

Thanks

EDIT

routes.axd:

api/{controller}/{id}
{resource}.axd/{*pathInfo}          
{controller}/{action}/{id}
5
When you use the 'route debugger' from AttributeRouting (should be available at ~/routes.axd) do you see the expected routes from the attributes, i.e. /api/q/users?David Tansey
Nope, just the api/{controller}/{id}, {resource}.axd/{*pathInfo} and {controller}/{action}/{id}. When I break the application on the MapAttributeRoutes() - the route collection comes back with 0 routes...Teagan42
I got the routes to show up in routes.axd by implementing IController in my controller - but it's still not quite right (returns empty page)Teagan42
Please, tell us how you fixed it.David Tansey
I updated the question. The issue was I had the MVC AttributeRouting NuGet but needed the web api nuget for AttributeRoutingTeagan42

5 Answers

118
votes

Not only do you have to have the call to routes.MapMvcAttributeRoutes() in your App_Start\RouteConfig.cs file, it must appear before defining your default route! I add it before that and after ignoring {resource}.axd{*pathInfo}. Just found that out trying to get attribute routing to work correctly with my MVC 5 website.

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

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

    }
38
votes

In your App_Start/RoutesConfig.cs

make sure you call the following line of code:

  routes.MapMvcAttributeRoutes();
8
votes

In nuGet package manager install to your project Web API Web Host package

add this class to folder app_start-> WebApiConfig.cs(if it doesn't exits - create):

  public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes(); // pay attention to this method
//here you can map any mvc route
            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new { id = RouteParameter.Optional }
            //);
            config.EnableSystemDiagnosticsTracing();
        }
    }

after Try change your Global.asax configuration to:

public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }
    }

P.S.

look through this article, very useful http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

cheers

4
votes

I came here looking for answers related to RoutePrefix. After some testing, I found that simply adding a

[RoutePrefix("MyPrefix")]

without using a subsequent Route attribute such as

[Route("MyRoute")]

means the RoutePrefix was ignored. Haack's routedebugger is very helpful in determining this: https://haacked.com/archive/2008/03/13/url-routing-debugger.aspx/

Simply add it via NuGet, which will add a line to your appsettings, and then all your routes are displayed at the bottom of your page. Highly recommend for any routing issues.

In the end, my final version looks like:

[RoutePrefix("Asset/AssetType")] [Route("{action=index}/{id?}")]

2
votes

Ensure you have NuGet package "WebApp API" installed for AttributeRouting.