Converting web forms site to MVC - asp.net

This seems like a common question, but I cannot find an answer anywhere.
First some background. I have an ASP.NET website with ASPX web forms. When a browser requests http://www.mysite.com/somefolder/ then IIS serves the contents of /somefolder/default.aspx. Requests for http://www.mysite.com/somefolder/default.aspx also receive /somefolder/default.aspx.
Now for the question. I want to gradually convert the site to MVC and Razor. What needs to be done so that requests for http://www.mysite.com/somefolder/ are handled by MVC and requests for http://www.mysite.com/somefolder/default.aspx get a 301 redirect to http://www.mysite.com/somefolder/?
EDIT
Here's some additional information that may clarify my question above.
In the past, whenever I "retired" an ASPX page I would place a Response.RedirectPermanent in its code-behind to redirect to the replacement page. Should that practice be continued in this scenario when default.aspx is replaced by MVC/Razor or should something different occur (such as deleting default.aspx and using routing to handle requests for http://www.mysite.com/somefolder/default.aspx)?

EDIT : There's an easy solution for this. In the Route.Config, add routes.IgnoreRoute("{resource}.aspx/{*pathInfo}"); :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
And in the Global.asax.cs add this:
protected void Application_BeginRequest(object sender, EventArgs e)
{
var requestUrl = Request.Url.ToString().ToLower();
//Default.aspx is converted to "Home/Index"
if (requestUrl.Contains("/default.aspx"))
{
Context.Response.StatusCode = 301;
Context.Response.Redirect("/Home/Index");
}
}
You may need to parse requestUrl in case parameters are passed to the page.
I would suggest to read this: ASP.NET MVC - Legacy Url Routing which would help to build a better solution.

Related

The controller path for '/null' was not found or does not implement IController

I have existing asp.net web forms applications that I have added RouteConfig.RegisterRoutes(RouteTable.Routes); to their global.asax files. I'm attempting to use some MVC alongside the forms - like friendly urls. The code is pretty standard and includes this:
public static void RegisterRoutes(RouteCollection routes)
{
var settings = new FriendlyUrlSettings { AutoRedirectMode = RedirectMode.Permanent };
routes.EnableFriendlyUrls(settings, new MyFriendlyUrlResolver());
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
}
It's all pretty much boilerplate code, aside from the custom friendly url resolver, so I'm not understanding why I am getting a lot of "The controller path for '/null' was not found or does not implement IController" errors now.
Am I getting a bunch of traffic to www.mysite.com/null now or does this have something to do with routing? Is there a special way to set up routing for a forms-heavy site? I have created new apps with forms + MVC and this is pretty much the code that the project comes with.
First of all be sure of your routing like if your route is
localhost/Home/Index
Also make sure that in your code behind file aspx.cs inherit the controller class like
Public class Customer : Controller and then put a break point on your action method
here it will be
localhost/Customer/Add
Then Check your aspx (design) page whether you are routing to the correct URL
generally in MVC
#Html.Action("Add", "Customer ", Model).
Check your global.asax file Application_onstart event nad make sure these two lines are present in this order
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);

Getting error 404 not found with ASP.NET MVC Area routing

I am having a problem with an Area route in MVC 5. When I browse to /Evernote/EvernoteAuth I get a 404 resource cannot be found error.
My area looks like this:
Areas
Evernote
Controllers
EvernoteAuthController
Views
EvernoteAuth
Index.cshtml
The EvernoteAreaRegistration.cs (UPDATE: RegisterArea() wasn't being called so I did a Clean and Rebuild. Now it is called but same result.) contains this route map:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Evernote_default",
"Evernote/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
The EvernoteAuthController's Index() method simply returns View().
My application's RouteConfig.cs currently has no route maps defined, but I tried manually "forcing" it here by implementing this:
routes.MapRoute(
name: "EvernoteAuthorization",
url: "Evernote/{controller}/{action}",
defaults: new { controller = "EvernoteAuth", action = "Index", id = UrlParameter.Optional },
namespaces: new string[] { "AysncOAuth.Evernote.Simple.SampleMVC.Controllers" }
);
but I get the same results whether this route map exists or is commented out.
Using Phil Haack's asp.net mvc routing debugger I saw that my routes matched fine and the area name, controller name and Action method names matched. I put breakpoints in the controller action methods and those methods were never entered. UPDATE: Those methods were never entered when browsing to /Evernote/EvernoteAuth however when I browsed to just the area name, /Evernote, an EvernoteAuthController was instantiated and the Index() method was called. (Why is that controller being instantiated by /Evernote by not by /Evernote/EvernoteAuth?) Then I received the error:
The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/EvernoteAuth/Index.aspx
~/Views/EvernoteAuth/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/EvernoteAuth/Index.cshtml
~/Views/Shared/Index.cshtml
and so on...
In this case I believe ~ = / (application root). So the area Areas\Evernote\Views is not being searched.
How do I troubleshoot this?
It is important tha you add the correct namespace to your controller
namespace YourDefaultNamespace.Areas.Evernote.Controllers
{
public class EvernoteAuthController : Controller
{
...
...
}
}
So the routing can find your controller.
Now you have to register the area in the Global.asax.cs with the method
AreaRegistration.RegisterAllAreas();
Be careful with AreaRegistration.RegisterAllAreas(); inside Application_Start method.
If you put AreaRegistration.RegisterAllAreas() to be last inside Application_Start that will not work.
Put AreaRegistration.RegisterAllAreas() to be first and routing will be successfully executed..
Example:
protected void Application_Start(object sender, EventArgs e)
{
AreaRegistration.RegisterAllAreas(); //<--- Here work
FilterConfig.Configure(GlobalFilters.Filters);
RouteConfig.Configure(RouteTable.Routes);
AreaRegistration.RegisterAllAreas(); //<--- Here not work
}
Like you found in my post at http://legacy.piranhacms.org/the-magic-of-mvc-routing-with-multiple-areas you probably figured out the all controllers are mapped to the default route (i.e the one you added manually in your route config). If it has been added to the default route, then it will search the location for the default route for its views, i.e ~/Views/...
So the error really seems to be that the Area isn't configured properly. Make sure that you have the following line in your Global.asax.xs:
AreaRegistration.RegisterAllAreas();
This is the line that actually sets up the areas and makes sure that when a controller within a area is hit, the view directory of that area is searched, in your case ~/Areas/Evernote/Views. The thing covered in my blog post was how to eliminate that controllers from your Evernote area are being mapped in the default route.
Hope this help!
Regards
Håkan
In my case the order of the configuration in Application_Start of global.asax.cs was
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
Changing the order made it work.
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();

Url Rewrite: Should www re-writing be in the app or the web server?

I have to redirect non-www urls to use www. I have a choice of doing this in IIS 7 or code this logic in my ASP.Net application.
In terms of portability I would've thought writing this in the application itself might be better.
Is there a preferred method for achieving this or is it just preference?
When you do this in IIS7, all it does is modify your Web.Config files for you. I would have said that that was the conventional way of doing things.
http://www.iis.net/learn/extensions/url-rewrite-module/creating-rewrite-rules-for-the-url-rewrite-module
I think, it is more rational to do this in the application. For example we have it defined like that:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"User", // Route name
"u/{user}/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Hence we have plenty of flexibility and can have specific tokens in our links, etc. Yet if there was no need for that - we would use IIS base. So, I guess - whatever tickles your pickle here :)

A route named "x" is already in the route collection. Route names must be unique. Exception with ASP.NET MVC 3

I'm doing an ASP.NET MVC 3 web service and I keep getting this exception intermittently.
Stack trace:
Server Error in '/' Application.
A route named 'ListTables' is already in the route collection. Route names must be unique.
Parameter name: name
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: A route named 'ListTables' is already in the route collection. Route names must be unique.
Parameter name: name
Source Error:
Line 24: // }
Line 25: // );
Line 26: context.MapRoute(
Line 27: "ListTables",
Line 28: // example:
Source File: C:\inetpub\wwwroot\SchemaBrowserService\Website\Areas\Api\ApiAreaRegistration.cs Line: 26
Stack Trace:
[ArgumentException: A route named 'ListTables' is already in the route collection. Route names must be unique.
Parameter name: name]
System.Web.Routing.RouteCollection.Add(String name, RouteBase item) +2329682
System.Web.Mvc.RouteCollectionExtensions.MapRoute(RouteCollection routes, String name, String url, Object defaults, Object constraints, String[] namespaces) +236
System.Web.Mvc.AreaRegistrationContext.MapRoute(String name, String url, Object defaults, Object constraints, String[] namespaces) +59
System.Web.Mvc.AreaRegistrationContext.MapRoute(String name, String url, Object defaults) +17
SchemaBrowserService.Areas.Api.ApiAreaRegistration.RegisterArea(AreaRegistrationContext context) in C:\inetpub\wwwroot\SchemaBrowserService\Website\Areas\Api\ApiAreaRegistration.cs:26
System.Web.Mvc.AreaRegistration.CreateContextAndRegister(RouteCollection routes, Object state) +105
System.Web.Mvc.AreaRegistration.RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, Object state) +199
System.Web.Mvc.AreaRegistration.RegisterAllAreas(Object state) +45
System.Web.Mvc.AreaRegistration.RegisterAllAreas() +6
Website.MvcApplication.Application_Start() in C:\Users\djackson\Downloads\RestApiMvc3\Website\Website\Global.asax.cs:35
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272
It's probably related to the fact that Route Debugger shows that I have some old routes that I've modified or deleted and won't go away (even after rebooting my machine). The stack trace also refers to a source file that has long since been deleted and my app has been moved to a new location, cleaned and rebuilt since then. What am I missing?
Here is all of my route registration code:
// in Global.asax.cs:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default2", // Route name
"Api/{controller}/{action}/{id}", // URL with parameters
new { controller = "DataSource", action = "Index", area = "Api", id = UrlParameter.Optional } // Parameter defaults
);
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()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
// in ApiAreaRegistration.cs:
public class ApiAreaRegistration : AreaRegistration
{
public override string AreaName { get { return "Api"; } }
public override void RegisterArea(AreaRegistrationContext context)
{
// DataSources
// Tables
context.MapRoute(
"ListTables",
// example:
// /api/DataSources/DataSource/1/schemata/schema/dbo/tables
"Api/DataSources/DataSource/{dataSourceId}/schemata/{schemaName}/tables",
new
{
controller = "Tables",
action = "TableList",
schemaName = "dbo",
dataSourceId = "DefaultId"
}
);
// Schemata
context.MapRoute(
"Schema",
// example:
// /api/DataSources/DataSource/1/schemata/schema/dbo
"Api/DataSources/DataSource/{dataSourceId}/schemata/{schemaName}",
new
{
controller = "Schema",
action = "Schema",
dataSourceId = "DefaultId",
schemaName = UrlParameter.Optional
}
);
// // DataSources
context.MapRoute(
"SingleDataSource",
"Api/DataSources/DataSource/{dataSourceId}",
new
{
controller = "DataSource",
action = "DataSource",
dataSourceId = UrlParameter.Optional
}
);
context.MapRoute(
"ListDataSources",
"Api/DataSources",
new
{
controller = "DataSource",
action = "DataSourceList",
dataSourceId = "DefaultId"
}
);
context.MapRoute(
"Api_default",
"Api/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
}
To fix this problem I had to go into the bin folder on my project, delete all DLL files and then rebuild and this fixed the problem.
This error can occur due to multiple causes, I had the same error and solved it by modifying the Global.asax class.
The Application_Start method at Global.asax.cs was like:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
RouteConfig.RegisterRoutes(RouteTable.Routes);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
The following line occurs twice in this method:
RouteConfig.RegisterRoutes(RouteTable.Routes);
This ensured that the route was twice added to the route list and at the same time causing the error.
I changed the Application_Start method as follows and the error disappeared:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
This may not be the answer for your problem, but can perhaps help others in the future. I didn't see this answer between the others, so I decided to add this.
I found out that Global.asax was referring to an old version of the site's DLL file before I renamed it. The DLL was not being cleaned up when I did Build > Clean up because the VS project/solution didn't refer to it any more. It seems that sometimes only the newer version of the DLL was being used, allowing the site to work correctly, but eventually both of them would be loaded causing the route conflicts.
The routes get loaded from all assemblies within AppDomain.CurrentDomain, so if your old assemblies are still part of that, you might be still getting old/duplicate routes.
In my case, I faced with this issue, when I added reference to another project from solution, which also was MVC and use the same names in area (I didn't want to added this project, I don't know how it happened). When I removed this DLL, project started to work.
Deleting the DLLs alone didn't work for me (in VS2013), but deleting the entire 'bin' and 'obj' folders and then building the solution worked perfectly! Makes me wish I hadn't spent so long trying to fix it...
None of the suggestions worked for me. Went ahead and restarted the web server (IIS in this case) and that cleared the error after I had fixed the code. DLL must have been cached in IIS.
try this code, only change name
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapHttpRoute(
name: "API",
routeTemplate: "api/{controller}/{action}",
defaults: new { action = "GetAgentId" }
);
I am getting same error. But finally I have got solution.
Scenario: I am adding different(mvc4 application) dll in my web api mvc4 application.
When try to run. I am getting same error.
Root Cause- When my web api application run .Application register all area from self and start loading to current application domain dll references. When application load dll(MVC4 application) that time getting error because current maproute already add key for "HelpPage_Default".
Solution.
1.Change key for RegisterArea in maproute either current application or existing application(Refer dll).
2.Move code dll(mvc4 application) code to different liberary and refer to new dll.
I was manually calling AttributeRoutingHttpConfig.Start() in my Global.asax. Did not notice this auto-generated line at the top of the file which automatically calls it.
[assembly: WebActivator.PreApplicationStartMethod(typeof(Mev.Events.Web.AttributeRoutingHttpConfig), "Start")]
I had an application that was a Forms app migrated to MVC with a third party component used for authentication which redirected to another site.
The component would start a session twice if the user wasn't already logged in (once for initial connection to site and once for return).
So I solved this with the following code:
if (routes.Count < 3)
{
routes.IgnoreRoute("login.aspx");
routes.IgnoreRoute("default.aspx");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {action = "Index", id = UrlParameter.Optional}
);
}
Deleting the dlls in the bin folder did work 100%, I still had dlls my project needed to rebuild.
Rather make a copy of the bin folder. then delete the original.rebuild the project. if it fails, place the missing dlls into the bin folder.
I was running an old MVC2 website and I got this issue because the IIS 'Managed Pipeline Mode' was set on 'Integrated' by default (press F4 on the project). Changing it to 'Classic' fixed the issue
When publishing to an Azure App Service I had to check the Publish Dialog's "Settings"->"File Publish Options"->"Remove additional files at destination" to get the old project DLL and symbol files removed. Then the site would load.
This is essentially the current answers (Fleas's) solution at the core. Delete the offending DLL.
What caused this old DLL to be retained was I was loading an older version of the website (MVC 3~5 templates but different web project with colliding namespaces, since the newer version was a copy of this project made some point in the recent past.) The newer project's DLLs just needed to be deleted. There are various ways to achieve this. I found using a dialog to be the easiest atm. Logging into the file system and axing the files by hand certainly works too.
If you are versioning, and you use two APIs with the same name, you will get this error. If you need the same Get, try changing the Name attribute of the route:
TestsController.cs:
[MapToApiVersion("1.0")]
[Route("{moniker}", Name = "GetTest")]
public async Task<IHttpActionResult> Get(string moniker, bool param1 = false)
[MapToApiVersion("1.1")]
[Route("{moniker}", Name = "GetTest11")] // Change name here for a different version
public async Task<IHttpActionResult> Get(string moniker)
And pass in the version in the URL:
http://localhost:6600/api/tests/2020?api-version=1.1
faced this issue. the problem was occurred after adding an area to my project. there was a call for MapMvcAttributeRoutes() in RegisterArea() method. therefore, you should not look for a duplicate route names, just look for duplicate MapMvcAttributeRoutes() calls.

ASP.NET routing ignoreRoute does not work

I can't exclude non-existing files from the routing system. I am dealing with this code in a Web Forms scenario:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.gif/{*pathInfo}");
routes.IgnoreRoute("{resource}.jpg/{*pathInfo}");
Route r = new Route("{*url}", new MyRouteHandler());
routes.Add(r);
}
When I debug
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string path;
IHttpHandler page;
try
{
path = requestContext.RouteData.GetRequiredString("url");
LogFile(requestContext, path);
}
path still contains non existing gif files, jpg etc
I want to exclude all files that have an extension if that’s possible
Is something wrong with the code above? Is the order correct, i.e. add routes.IgnoreRoute entry prior to adding a route to RouteCollections?
In Web Forms, you can use the StopRoutingHandler. In the following example, routing will be ignored for files in the /images folder like http://yoursite.com/images/xyz.jpg
routes.Add(new Route("images/{resource}", new StopRoutingHandler()));
IgnoreRoute is an extension method of ASP.NET MVC (System.Web.Mvc) - does not work in Web Forms.
Do this:
routes.Add(new Route("{resource}.gif/{*pathInfo}", new MyIgnoreHandler()));
Map your other routes to your regular handler.
You should remove the "mvc" tag from this question.

Resources