I'm at a loss for why this routing issue is occurring.
Route in Global.asax.cs file:
routes.MapRoute(
"Archives", //Route name
"{controller}/{action}/{month}", // URL with parameters
new { controller = "Articles", action = "Archives" },
new { month = #"^\d+" } // Parameter.defaults
);
Controller:
public ActionResult Archives(int month)
{
ViewData["month"] = month;
return View(article);
}
Which keeps throwing the error:
The parameters dictionary contains a null entry for parameter 'month' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Archives(Int32)'
in 'AppleWeb.Controllers.ArticlesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
Which is bogus because the URL is: http://localhost:64529/Articles/Archives/12
EDIT- Full routing for all to see:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.IgnoreRoute("tellerSurvey.htm/{*pathInfo}");routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Appleweb", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Contact", //Route name
"{controller}/{action}/{page}", //URL with parameters
new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional } // Paramter defaults
);
routes.MapRoute(
"FormDetails", //Route name
"{controller}/{action}/{formid}", // URL with parameters
new { controller = "Resources", action = "FormDetails", formid = 0}
);
routes.MapRoute(
"_calc",
"{controller}/{action}/{calcid}", // URL with parameters
new { controller = "Resources", action = "Calc", calcid = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Article", //Route name
"{controller}/{action}/{articleid}", // URL with parameters
new { controller = "Articles", action = "Article", id = 0 } // Parameter.defaults
);}
This is an MVC 3 project, so no routingconfig.cs.
Here is the problem:
The URL http://localhost:64529/Articles/Archives/12 matches the other routes. It will match the Default, Contact, etc routes.
Edit
Simplest solution
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Archives",
"{controller}/{action}/{month}",
new { controller = "Articles", action = "Archives" },
new { month = #"\d+"}
);
//short-circuit for all URLs where the month is not numeric
//Warning: the 404 will not be handled in <customErrors>
//Its handled in <httpErrors>
routes.IgnoreRoute("Articles/Archives/{month}");
//place all other routes here
Other possibilities
1) replace {controller} with the hard-coded controller name so that /Articles won't match the route. Sample:
routes.MapRoute(
"Contact",
"Appleweb/{action}/{page}",
new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional }
);
Only match URLs that start with /Appleweb
2) use constraint
routes.MapRoute(
"Archives", //Route name
"Appleweb/{action}/{page}",
new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional },
new { controller = "^(?!articles$).*$" } //don't match articles
);
or
routes.MapRoute(
"Archives", //Route name
"Appleweb/{action}/{page}",
new { controller = "Appleweb", action = "Contact", page = UrlParameter.Optional },
new { controller = "appleweb|resources" } //only allow appleweb and resources
);
3) make the URL of archive unique like http://XXXX/Archives/12
routes.MapRoute(
"Archives",
"Archives/{month}",
new { controller = "Articles", action = "Archives" },
new { month = #"\d+" }
);
Your route has not given a default value for the month and the action method has a non nullable parameter (int month).
Change your route map to:
routes.MapRoute(
"Archives",
"{controller}/{action}/{month}",
new { controller = "Articles", action = "Archives",
month = UrlParameter.Optional }
);
Or action method to accept nullable int for the month parameter:
public ActionResult Archives(int? month) //nullable int
{
ViewData["month"] = month;
return View(article);
}
Related
I'm trying to setup routing as follows.
Right now My URL looks like www.mysite.com/Products/index/123
My goal is to setup URL like www.mysite.com/123
Where: Products is my controller name , index is my action name and 123 is nullable id parameter.
This is my route :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"OnlyId",
"{id}",
new { controller = "Products", action = "index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
and this is my Action Method
public ActionResult index (WrappedViewModels model,int? id)
{
model.ProductViewModel = db.ProductViewModels.Find(id);
model.ProductImagesViewModels = db.ProductImagesViewModels.ToList();
if (id == null)
{
return HttpNotFound();
}
return View(model);
}
this is my model wrapper :
public class WrappedViewModels
{
public ProductViewModel ProductViewModel { get; set; }
public ProductImagesViewModel ProductImagesViewModel { get; set; }
public List<ProductImagesViewModel> ProductImagesViewModels { get; set;
}
Error is thrown on this URL : www.mysite.com/123
The question is:
Why my view returns this error and how to avoid this behavior?
Thanks in advance.
In RegisterRoutes you need to specify little bit more.
routes.MapRoute(
name: "OnlyId",
url: "{id}",
defaults: new { controller = "Products", action = "index" },
constraints: new{ id=".+"});
and then you need to specify the routing of each anchor tag as
#Html.RouteLink("123", routeName: "OnlyId", routeValues: new { controller = "Products", action = "index", id= "id" })
I think this will resolve you immediate.
If you're sure that id parameter is nullable integer value, place a route constraint with \d regex like this, so that it not affect other routes:
routes.MapRoute(
name: "OnlyId",
url: "{id}",
defaults: new { controller = "Products", action = "index" }, // note that this default doesn't include 'id' parameter
constraints: new { id = #"\d+" }
);
If you're not satisfied for standard parameter constraints, you can create a class which inheriting IRouteConstraint and apply that on your custom route as in this example:
// adapted from /a/11911917/
public class CustomRouteConstraint : IRouteConstraint
{
public CustomRouteConstraint(Regex regex)
{
this.Regex = regex;
}
public CustomRouteConstraint(string pattern) : this(new Regex("^(" + pattern + ")$", RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase))
{
}
public Regex Regex { get; set; }
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.IncomingRequest && parameterName == "id")
{
if (values["id"] == UrlParameter.Optional)
return true;
if (this.Regex.IsMatch(values["id"].ToString()))
return true;
// checking if 'id' parameter is exactly valid integer
int id;
if (int.TryParse(values["id"].ToString(), out id))
return true;
}
return false;
}
}
Then place custom route constraint on id-based route to let other routes work:
routes.MapRoute(
name: "OnlyId",
url: "{id}",
defaults: new { controller = "Products", action = "index", id = UrlParameter.Optional },
constraints: new CustomRouteConstraint(#"\d*")
);
I think you missed Routing order. So create first route definition which handles all available controllers and then define one which will handle the rest of the requests, say, one that handles the www.mysite.com/{id} kind of requests.
So swap the OnlyId and Default rules and No more changes required. I believe It should work fine now.
I need to define an MVC route for URL like this:
http://localhost/RealSuiteApps/RealHelp/-1/Detail/BRK18482020
where:
Detail - is controller name
default action Index should be executed
-1 is some client id
BRK18482020 is orderId
I need this to go to DetailController, Index action with orderId parameter.
I tried this:
routes.MapRoute(
name: "Detail",
url: "Detail/{id}",
defaults: new { clientid = "-1", controller = "Detail", action = "Index", id = UrlParameter.Optional }
);
but I get a message "Page Not Found". What am I missing here ??
Assuming DetailController action
public ActionResult Index(int clientId, string orderId) { ... }
Then route would be mapped as
routes.MapRoute(
name: "Detail",
url: "{cientId}/Detail/{orderId}",
defaults: new { clientid = "-1", controller = "Detail", action = "Index" }
);
Note that this should also be registered before any default routes.
I use this log in controller :
public ActionResult Index(LoginModel model)
{
if (model.usernam == "usernam" && model.password == "password")
{
return RedirectToAction("Index", "Home");
}
return View();
}
This RedirectToAction returns this exception: No route in the route table matches the supplied values.
In my Globa.asax I have this values which I think it may solve the problem but I don't know how
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}/{id1}/", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional, id1= UrlParameter.Optional} // Parameter defaults
);
}
I googled searched the web I found many suggestions, but nothing works.
Is there any solution for this??
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}/{id1}/", // URL with parameters
new { controller = "Home",
action = "Index",
id = UrlParameter.Optional,
id1 = UrlParameter.Optional
} // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
}
If you pay attention to the above code you were missing the default route without parameters.
I have the following action :
public class IntegrationController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ContentResult Feed(string feedKey)
{
...
}
}
I have tried to use this URL :
http://MyServer/Integration/Feed/MyTest
but feedKey is null? Does this have something to do with routes?
Edit 1 :
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Ad", action = "List", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"TreeEditing", // Route name
"{controller}/{action}/{name}/{id}", // URL with parameters
new { controller = "AdCategory", action = "Add", name = string.Empty, id = -1 }
);
Edit 2 :
routes.MapRoute(
"IntegrationFeed", // Route name
"{controller}/{action}/{name}/{feedKey}", // URL with parameters
new { controller = "Integration", action = "Feed", name = string.Empty, feedKey = "" }
);
Do you have a route defined for feedKey? Using the default routes, the following should work (change feedKey to id).
[AcceptVerbs(HttpVerbs.Get)]
public ContentResult Feed(string id)
{
// ...
}
EDIT: Sorry I explained it badly. Basically, in the below example, I want "this-is-handled-by-content-controller" to be the "id", so I can grab it in ContentController as an action parameter, but I want to access it via the root of the site, e.g mysite.com/this-is-not-passed-to-homecontroller.
I'm trying to create a root route that will go to a separate controller (instead of home).
I've followed the "RootController" example posted somewhere else that implements IRouteConstraint but it just doesn't seem to work and I've already wasted a couple of hours on this!
Basically, I have a LoginController, a HomeController, and a ContentController.
I want to be able to view HomeController/Index by going to http://mysite/. I want to be able to view LoginController/Index by going to http://mysite/Login. But.. I want the ContentController/Index to be called if any other result occurs, e.g: http:/mysite/this-is-handled-by-content-controller
Is there an elegant way to do this that works?
This was my last attempt.. I've cut/pasted/copied/scratched my head so many times its a bit messy:
routes.MapRoute(
"ContentPages",
"{action}",
new { Area = "", controller = "ContentPages", action = "View", id = UrlParameter.Optional },
new RootActionConstraint()
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { Area = "", controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
new string[] { "Website.Controllers" }
);
Any help is appreciated greatly!
chem
I would do something similar to this, though that might not be the best solution if you keep adding more controller in the future.
routes.MapRoute(
"HomePage",
"",
new { controller = "Home", action = "Index", id="" }
);
routes.MapRoute(
"Home",
"home/{action}/{id}",
new { controller = "Home", action = "Index", id="" }
);
routes.MapRoute(
"Login",
"Login/{action}/{id}",
new { controller = "Login", action = "Index", id="" }
);
//... if you have other controller, specify the name here
routes.MapRoute(
"Content",
"{*id}",
new { controller = "Content", action = "Index", id="" }
);
The first route is for your youwebsite.com/ that call your Home->Index. The second route is for other actions on your Home Controller (yourwebsite.com/home/ACTION).
The 3rd is for your LoginController (yourwebsite.com/login/ACTION).
And the last one is for your Content->Index (yourwebsite.com/anything-that-goes-here).
public ActionResult Index(string id)
{
// id is "anything-that-goes-here
}
Assuming you have ContentController.Index(string id) to handle routes matching the constraint, this should work:
routes.MapRoute(
"ContentPages",
"{id}",
new { Area = "", controller = "Content", action = "Index" },
new { id = new RootActionConstraint() }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}",
new { Area = "", controller = "Home", action = "Index", id = UrlParameter.Optional },
new string[] { "Website.Controllers" }
);