1

For supportability reasons I'm porting an application from .Net Core with ReactJs to .Net MVC.

This also uses Redux for state handling.

This seemed to be going ok but for some reason the WebAPI calls all fail with 404 errors.

I'm pretty sure the routing is correct as per the failing calls but clearly something is getting lost somewhere.

The default MVC controller that was added as an entry point works fine, it's just the ported WebAPI controllers that seem to fail.

I'm not allowed to post the entire code for commercial reasons but this is what the controller and one of the actions in question looks like:

namespace Api.Controllers
{
    /// <summary>
    /// Account management.
    /// </summary>
    [Authorize]
    [System.Web.Http.RoutePrefix("api/account")]
    public class AccountController : ApiController
    {
        // <snip>

        /// <summary>
        /// Current logged in account.
        /// </summary>
        // GET api/Account/UserInfo
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [System.Web.Http.Route("userinfo")]
        public async Task<UserInfoViewModel> GetUserInfo()
        {
            ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
            var userName = User.Identity.GetUserName();
            var account = new AccountRepresentation(await _context
                .Accounts
                .SingleOrDefaultAsync(acc => acc.Email == userName));
            return new UserInfoViewModel
            {
                Account = account,
                UserName = User.Identity.GetUserName(),
                Email = User.Identity.GetUserName(),
                HasRegistered = externalLogin == null,
                LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null,
                Roles = await UserManager.GetRolesAsync(User.Identity.GetUserName())
            };
        }

        // </snip>
    }
}

(snip comments added by me)

Notice the routing attributes - it's a bit over the top as I'm trying everything, but as far as I can tell this should be ok. However in the browser console I'm seeing this:

Failed to load resource: the server responded with a status of 404 (not found) http://localhost:49690/api/account/userinfo

The port number is correct for the default controller so unless it's different for the other controllers for some reason, this should be ok as well.

I've been playing with the RouteConfig.cs file which currently looks as follows:

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

            routes.MapMvcAttributeRoutes();

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new[] { "Api.Controllers" }
            ).DataTokens.Add("area", "UI");

            routes.MapRoute(
                name: "api",
                url: "api/{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                namespaces: new[] { "Api.Controllers" }
            ).DataTokens.Add("area", "UI");

        }
    }
}

The WebApiConfig file looks as follows:

namespace Api
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            // Web API configuration and services
            // Web API routes
            // config.MapHttpAttributeRoutes();
            // Configure Web API to use only bearer token authentication.
            //         config.SuppressDefaultHostAuthentication();
            //         config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
            //config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

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

Application_Start() is like this:

namespace Api
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {

            AreaRegistration.RegisterAllAreas();
            //UnityConfig.RegisterComponents();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            log4net.Config.XmlConfigurator.Configure();
        }
    }
}

What else could be missing or wrong that is preventing the API actions being found?

(Let me know if any other code would be helpful)

Other details:

Visual Studio version: Enterprise 2015 update 3

.NET version: 4.6.1

1
  • Nothing has worked so far. Am now considering starting a new project from scratch and adding the code in one controller at a time. Commented Feb 1, 2017 at 14:47

2 Answers 2

1

In .Net Core, attribute routing is now enabled by default. However, in MVC5, you are need to set it up. In your route config, add this:

routes.MapHttpAttributeRoutes();

Note that for normal MVC (i.e. not WebAPI) you need this command instead:

routes.MapMvcAttributeRoutes();

Note: MapHttpAttributeRoutes is an extension method in System.Web.Http so you will need a using System.Web.Http; statement.

Sign up to request clarification or add additional context in comments.

11 Comments

Thanks. I have added routes.MapMvcAttributeRoutes() but this doesn't seem to help. However MapHttpAttributeRoutes doesn't seem to be a method of routes - am looking online for how to use this.
MapHttpAttributeRoutes is an extension method in System.Web.Http so you will need a using System.Web.Http; statement.
A combination of this answer and the other are what you need.
Actually I've just seen that MapHttpAttributeRoutes is already called in WebApiConfig file. Have added that to the question.
Please make sure webapiConfig register before Route register. If that is not working please commit web api route configuration and keep only config.MapHttpAttributeRoutes(); in WebapiConfig file. and see this one work
|
1

if you Porting .net Core application from .net mvc you have add WebApiConfig file and register in global file. and it should be like this. First use Route Attribute because you have use Attribute routing.

 public static void Register(HttpConfiguration config)
    {

        // Web API routes
        config.MapHttpAttributeRoutes();

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.