VansFannel
VansFannel

Reputation: 45931

Api controllers work but web razor controllers don't with owin

I'm getting crazy with this.

I'm developing an ASP.NET Web Api 2.2 project with Visual Studio 2012 Premium, .NET Framework 4.5.1 and C#.

I have created an empty ASP.NET MVC 5 project. I have deleted Global.asax and create this Startup.cs class:

using Microsoft.Owin;
using Ninject;
using Ninject.Web.Common.OwinHost;
using Ninject.Web.WebApi.OwinHost;
using Owin;
using System.Reflection;
using System.Web.Http;
using System.Web.Routing;
using MyProject.Web.API.App_Start;

[assembly: OwinStartup(typeof(MyProject.Web.API.Startup))]
namespace MyProject.Web.API
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            var webApiConfiguration = new HttpConfiguration();
            webApiConfiguration.Routes.MapHttpRoute(
                name: "Default",
                routeTemplate: "{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });

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

            webApiConfiguration.Routes.MapHttpRoute(
                name: "ProductionOrderActionApi",
                routeTemplate: "api/MyProductionOrders/{orderNumber}/{action}",
                defaults: new { controller = "MyProductionOrders" });

            app.UseNinjectMiddleware(CreateKernel);
            app.UseNinjectWebApi(webApiConfiguration);
        }

        private static StandardKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());

            RegisterServices(kernel);

            return kernel;
        }

        private static void RegisterServices(IKernel kernel)
        {
            var containerConfigurator = new NinjectConfigurator();
            containerConfigurator.Configure(kernel);
        }
    }
}

The project works fine with ApiController classes, but when I try to access to a Controller I get HTTP 404 Status code: not found.

What do I have to do to allow Web pages? I think the problem is with Routes but I have tried to add RouteConfig to the project, but I don't know how.

I have searched a lot on Google but I haven't found anything related to my question (or maybe I haven't put the correct search term).

If you need NinjectConfigurator class, please tell me and I add it.

Upvotes: 1

Views: 2119

Answers (2)

rism
rism

Reputation: 12142

You need to use MapRoute for Controllers.

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

MapRoute is an extension method and within that the MvcRouteHandler is setup as the route handler for the request. If you haven't mapped a given route to be handled by MvcRouteHandler then you're not engaging the Mvc request processing pipeline that leads to a controller being instantiated.

MapRoute uses an MvcRouteHandler

   public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
    {
      if (routes == null)
        throw new ArgumentNullException("routes");
      if (url == null)
        throw new ArgumentNullException("url");
      Route route = new Route(url, (IRouteHandler) new MvcRouteHandler())
      {
        Defaults = RouteCollectionExtensions.CreateRouteValueDictionaryUncached(defaults),
        Constraints = RouteCollectionExtensions.CreateRouteValueDictionaryUncached(constraints),
        DataTokens = new RouteValueDictionary()
      };
      ConstraintValidation.Validate(route);
      if (namespaces != null && namespaces.Length > 0)
        route.DataTokens["Namespaces"] = (object) namespaces;
      routes.Add(name, (RouteBase) route);
      return route;
    }

MapHttpRoute uses an HttpMessageHandler:

public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler)
{
  if (routes == null)
    throw Error.ArgumentNull("routes");
  HttpRouteValueDictionary routeValueDictionary1 = new HttpRouteValueDictionary(defaults);
  HttpRouteValueDictionary routeValueDictionary2 = new HttpRouteValueDictionary(constraints);
  IHttpRoute route = routes.CreateRoute(routeTemplate, (IDictionary<string, object>) routeValueDictionary1, (IDictionary<string, object>) routeValueDictionary2, (IDictionary<string, object>) null, handler);
  routes.Add(name, route);
  return route;
}

Upvotes: 3

Chino
Chino

Reputation: 821

To me it indeed looks like the routing setup has not been set as you only defined the routes for webapi. The routing configuration for mvc and webapi is a little bit different so you can't setup the routing for both in the way you did there. A quote from book i am reading:

The key to avoiding conflict between the frameworks is a careful route setup; to facilitate that, by default ASP.NET Web API will occupy URI space under /api, while all of the other root-level URLs will be handled by MVC. Typically Web API routes are defined in the WebApiConfig static class against the HttpConfiguration object and its Route property, while MVC routes are defined in the static RouteConfig class, directly against the System.Web.RouteCollection.

 //Web API routing configuration
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Web API routes
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
            );
        }
    }
    //MVC routing configuration
    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: 0

Related Questions