CompanyDroneFromSector7G
CompanyDroneFromSector7G

Reputation: 4527

404 Errors after porting .Net Core application to MVC

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

Upvotes: 1

Views: 848

Answers (2)

Damith Asanka
Damith Asanka

Reputation: 964

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 }
        );
    }

Upvotes: 1

DavidG
DavidG

Reputation: 119166

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.

Upvotes: 1

Related Questions