Here's the error:
The incoming request does not match any route.
Basically I upgraded from Preview 1 to Preview 2 and got rid of a load of redundant stuff in relation to areas (as described by Phil Haack). It didn't work so I created a brand new project to check out how its dealt with in Preview 2. The file Default.aspx no longer exists which contains the following:
public void Page_Load(object sender, System.EventArgs e)
{
// Change the current path so that the Routing handler can correctly interpret
// the request, then restore the original path so that the OutputCache module
// can correctly process the response (if caching is enabled).
string originalPath = Request.Path;
HttpContext.Current.RewritePath(Request.ApplicationPath, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(HttpContext.Current);
HttpContext.Current.RewritePath(originalPath, false);
}
The error I received points to the line httpHandler.ProcessRequest(HttpContext.Current); yet in newer projects none of this even exists. To test it, I quickly deleted Default.aspx but then absolutely nothing worked, I didn't even receive any errors. Here's some code extracts:
Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace Intranet
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
AreaRegistration.RegisterAllAreas();
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
protected void App_Start()
{
RegisterRoutes(RouteTable.Routes);
}
}
}
Notice the area registration as that's what I'm using.
Routes.cs
using System.Web.Mvc;
namespace Intranet.Areas.Accounts
{
public class Routes : AreaRegistration
{
public override string AreaName
{
get { return "Accounts"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute("Accounts_Default", "Accounts/{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" });
}
}
}
Check the latest docs for more info on this part. It's to register the area. The Routes.cs files are located in the root folder of each area.
Cheers
As per comment "Sorry, I was working by the example, you're meant to use Application_Start not App_Start. I have no idea why"
Related
I've been searching for answers for this everywhere, but I can't seem to find any. I basically have an MVC application setup and I am using the built in AttributeRouting for my routes.
The folder structure looks like this;
Models
Views
Controllers
Areas
Member
MemberAreaRegistration.cs
Controllers
HomeController.cs
Views
Home
Account.cshtml
And then I wire up my routes in the global.asax like this;
public class Application : System.Web.HttpApplication {
protected void Application_Start(){
AreaRegistration.RegisterAllAreas();
// other web optimization stuff
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
So then, MemberAreaRegistration.cs is simple.
namespace App.Web.Areas.Member {
public class MemberAreaRegistration: AreaRegistration {
public override string AreaName { get { return "Member"; } }
}
public override void RegisterArea( AreaRegistrationContext context){ }
}
And I try to wire it using the attributes...
/areas/member/controllers/homecontroller.cs
// ...
[Route("member/account")]
public ActionResult Account() { return View(); }
// ...
The problem is that this finds the route, but it cannot find the view. I get the following error;
The view 'Account' or its master was not found or no view engine
supports the searched locations. The following locations were
searched:
~/Views/Home/Account.aspx
~/Views/Home/Account.ascx
~/Views/Shared/Account.aspx
~/Views/Shared/Account.ascx
~/Views/Home/Account.cshtml
~/Views/Home/Account.vbhtml
~/Views/Shared/Account.cshtml
~/Views/Shared/Account.vbhtml
By all accounts, this should work fine - and if not, I expect the ~/area to at least be in the path it is trying to search. Do I have to wire something additional up to make this function?
I am using ASP.NET MVC 5.0
If I hardcode the absolute path of the view, it works. Obviously this is not a good situation though. I'd prefer it to find the view out of convention. But if I type return View("~/areas/member/views/home/account.cshtml"); I do get the view back - so I know it can access to file and that it is correct.
Here is my RouteConfig.cs per request
RouteConfig.cs
public class RouteConfig {
public static void RegisterRoutes(RouteCollection routes) {
// mvc attribute routing allows us to supersede normal routing mechanisms and
// declare our routes a bit more verbosely
routes.MapMvcAttributeRoutes();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "App.Web.Controllers" }
);
}
}
That's because, once you are defining your route as an action's attribute, ASP.NET MVC doesn't know which area it is in, hence it doesn't know where to look for Views.
In the Controller the Account action is in, try to explicitly specify a RouteArea attribute.
I'm writing this off the top of my head, but it should look like:
[RouteArea("Member")]
[RoutePrefix("member")]
public class HomeController: Controller {
[Route("account")]
public ActionResult Account() { return View(); }
}
or, alternatively:
[RouteArea("Member")]
public class HomeController: Controller {
[Route("member/account")]
public ActionResult Account() { return View(); }
}
I'm using MVC4 without WebAPI, just plain on MVC. I have an admin area (called "Admin", as usual) which is properly registered:
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName { get { return "Admin"; } }
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute("EditGroupRoute", "admin/groups/{action}/{id}", new { controller = "EditGroup", action = "Index", id = UrlParameter.Optional });
//...
//No default handler at the end, all routes are predetermined
}
Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//...
}
}
My regular, non-area RouteConfig.RegisterRoutes works as it should and contains normal routes with no default catch-all handler at the end.
Whenever I try some admin area route I get a 404 error. I'm using Haack's RouteDebugger and it shows a full match (and only one match) below the 404 error text, with the correct area, controller and action.
I've checked similar questions on SO, but no joy. Any ideas what could be wrong?
Area controllers were in the wrong namespace. Originally they were in /Controllers when I moved them to area controllers I didn't update the namespaces.
I have a small MVC 3 app - bit of a demo ground.
I have one area and thats been working fine.
I have just added another area expecting to just spin up the app and it work - but no, 404 - The resource cannot be found.
The map route in the AreaRegistration is the default (as is the first area i created).
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Postcard_default",
"Postcard/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
I have tried adding in a specific controller into this, but nothing.
So I downloaded Phil Haack's RouteDebugger and my route is found when typing in http://server/Postcard/Create (which is where I am trying to get too)
Structure of the Area
My controller
public class CreateController : Controller
{
private ILogger Logger { get; set; }
private ICardSender Emailer { get; set; }
private IOCCardRepository CardRepository { get; set; }
public CreateController(ILogger logger, ICardSender cardSender, IOCCardRepository repository)
{
this.Logger = logger;
this.Emailer = cardSender;
this.CardRepository = repository;
}
//
// GET: /Postcard/Create/
public ActionResult Index()
{
var model = new OCPostcardModel().Create();
return View(model);
}
NOW: I have since deleted the entire area, tried again it didn't work. So I added in the specific controller in the route (Inside AreaRegistration file)
context.MapRoute(
"Postcard_default",
"Postcard/{controller}/{action}/{id}",
new { controller = "Create", action = "Index", id = UrlParameter.Optional }
);
And its working...I don't know why it didn't work when I did this before, but it is now.
Still curious though as I've not seen anyone add in this controller into route in any of the demo's i've looked at - and I haven't got it in my other area?
I ran into this when I moved a controller into an Area but forgot to update the namespace. The controller name is scoped to the Area's namespace. So "Some" in "Area" will map to App.Areas.Area.Controllers.SomeController, which didn't exist.
You were missing the controller part in your maproute
Try to add a class PostCardAreaRegistration under PostCard Area
using System.Web.Mvc;
namespace Areas.PostCard
{
public class PostCardAreaRegistration: AreaRegistration
{
public override string AreaName
{
get
{
return "PostCard";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"PostCard_default",
"PostCard/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
}
Did something change in MVC 3? I have tried all the examples on the Internet for setting up Unity as my IoC Container, but I keep getting an error saying that Unity cannot resolve my UserController. Here is my constructor on my UserController:
public UserController(IUserService userService)
{
_userService = userService;
}
I have the IUserService registered, that is not the problem. I keep getting errors, no matter what example I try. Does anyone have a good tutorial, or code, that works with Asp.Net MVC 3?
For reference, I have tried this, this, this, and this ... and tons of others.
Error:
The type UserController cannot be constructed. You must configure the container to supply this value.
ErrorLine:
controller = MvcUnityContainer.Container.Resolve(controllerType) as IController;
Configuration:
MvcUnityContainer.Container = new UnityContainer().RegisterType<IUserService, UserService>();
ControllerBuilder.Current.SetControllerFactory(typeof(UnityControllerFactory));
This worked for me for MVC3 RC. Notice IControllerFactory now has GetControllerSessionBehavior in MVC3 RC.
UnityMvcControllerFactory.cs:
using System;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using System.Web.SessionState;
public class UnityMvcControllerFactory : IControllerFactory
{
private IUnityContainer _container;
private IControllerFactory _innerFactory;
public UnityMvcControllerFactory(IUnityContainer container)
: this(container, new DefaultControllerFactory())
{
}
protected UnityMvcControllerFactory(IUnityContainer container,
IControllerFactory innerFactory)
{
_container = container;
_innerFactory = innerFactory;
}
public IController CreateController(RequestContext requestContext, string controllerName)
{
try
{
return _container.Resolve<IController>(controllerName.ToLowerInvariant());
}
catch (Exception)
{
return _innerFactory.CreateController(requestContext, controllerName);
}
}
public void ReleaseController(IController controller)
{
_container.Teardown(controller);
}
public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
return SessionStateBehavior.Default;
}
}
Global.asax.cs:
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
// Register Types and Set Controller Factory
ConfigureUnityContainer();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
private static void ConfigureUnityContainer()
{
IUnityContainer container = new UnityContainer();
// Set Controller Factory as UnityMvcControllerFactory
ControllerBuilder.Current.SetControllerFactory(
new UnityMvcControllerFactory(container)
);
}
}
To answer your question "What has changed in MVC3": MVC3 now has native support for dependency injection. Along with that change has come a redesign of the way controller objects are activated. Check out Brad Wilson's post (and the whole series about MVC 3.0) for more information:
http://bradwilson.typepad.com/blog/2010/10/service-location-pt10-controller-activator.html
Developers who previously implemented IControllerFactory by deriving from DefaultControllerFactory just to override the GetControllerInstance method for dependency injection purposes should now implement IControllerActivator instead.
In short, the unity controller factory (as well as the Ninject controller factory) are probably going to be broken until they release a new compatible version. A quick google did find this, however I have no idea if it works.
I have a new MVC 2 project using ninject 2 for IOC. I have the following global.asax which sets up both NHibernate and Ninject. The code runs fine, ninject pulls out the controllers from the assembly (it does convert them to lowe case strings when it does this - inside the Ninject source).
All my controller URL's are now case sensitive so, /Home won't resolve but /home will.
When I use an uppercase first letter (the defualt in MVC) I get the error "The IControllerFactory 'Ninject.Web.Mvc.NinjectControllerFactory' did not return a controller for the name 'Home'."
Surly this isn't normal? Any Ideas?
public class MvcApplication : NinjectHttpApplication
{
public static ISessionFactory SessionFactory = CreateSessionFactory();
public MvcApplication()
{
this.BeginRequest += new EventHandler(MvcApplication_BeginRequest);
this.EndRequest += new EventHandler(MvcApplication_EndRequest);
}
void MvcApplication_BeginRequest(object sender, EventArgs e)
{
CurrentSessionContext.Bind(SessionFactory.OpenSession());
}
void MvcApplication_EndRequest(object sender, EventArgs e)
{
CurrentSessionContext.Unbind(SessionFactory).Dispose();
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
private static ISessionFactory CreateSessionFactory()
{
var cfg = new Configuration().Configure(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nhibernate.config"));
cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionString, #"Data Source=.\;Initial Catalog=xxxxxx;Integrated Security=true;");
//cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionString, System.Environment.MachineName);
NHibernateProfiler.Initialize();
return cfg.BuildSessionFactory();
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
RegisterAllControllersIn(Assembly.GetExecutingAssembly());
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new INinjectModule[] {
new ServiceModule(),
});
}
}
I'm wondering what the RegisterAllControllersIn(Assembly.GetExecutingAssembly()); line does? I'm not seeing that in the Ninject code. You shouldn't need to call any specific controller registrationg, since Ninject will find them and construct them on its own.
RegisterAllControllersIn isn't used anymore in the latest version of the extension combined with Ninject 2.1. Therefore, I succest to uptate to the latest version of Ninject and the MVC extension.
http://teamcity.codebetter.com/project.html?projectId=project3&tab=projectOverview
There is also a sample project on GitHub based on the VS2010 Sample project:
http://github.com/ninject/ninject.web.mvc/tree/master/mvc2/src/SampleApplication/