I have this in RouteConfig.cs file:
routes.MapRoute(
name: "PreSeleccion",
url: "{controller}/{action}/{month}/{id}",
defaults: new { controller = "Menu", action = "PreSeleccion" }
);
On the other hand, I have this in the Menu controller:
// GET: Menu/PreSeleccion/{month}/{id}
[HttpGet]
[AllowAnonymous]
public async Task<ActionResult> PreSeleccion(int month = 0, int id = 0)
{
}
When calling that action with this URL: /Menu/PreSeleccion/202301/80 and debug, I can see that month parameter is 0 and the id parameter is 202301.
How can I fix this?
Related
How do I map unmatched routes to the index action for that controller?
I'm using a client side router for routes like /Home/foo
routes.MapRoute(
name: "Test",
url: "{controller}/{*.}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
This currently results in a 404.
Your route that you used is correct, the problem is the orders of the routes that need to be added in write format:
for example if you have some routes like:
routes.MapRoute(
name: "PreTest",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Test",
url: "{controller}/{*.}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
So it is always matched with first route PreTest. Check your routes order. It is work like a dictionary that ordered. Check this for more information.
I would create an AuthorizeAttribute to handle your case. Then you can decorate your controller with that attribute.
Here's a small example to redirect your action base on a value in the route:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class RedirectAttribute:ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if(filterContext.Controller.ControllerContext.RouteData.Values.ContainsValue("Foo"))
{
//Redirect to the login for example
UrlHelper urlHelper = new UrlHelper(filterContext.HttpContext.Request.RequestContext);
string url = urlHelper.Action("actionName", "controllerName");
filterContext.Result = new RedirectResult(redirectUrl);
}
}
}
Here's how to use it in a controller:
[Redirect]
public class MyCustomController : AsyncController
{
public ActionResult Index()
{
return View();
}
public ActionResult Foo()
{
//It will redirect
return View();
}
}
I have Login action method in my home controller like this
[HttpGet]
public ActionResult Login()
{
return View();
}
I am having this Action method as start page of my application, however I want to re-write it like this
www.abc.com/MySite/security/login
I write this attribute after [HttpGet]
[Route("MySite/security/Login")]
Now the problem is,when I am running the application,its giving me error
The resource cannot be found.
This is my RoutConfig
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 = "Login" , id = UrlParameter.Optional }
);
}
How can I fix this issue,Also I am having same name method with HttpPost attribute,should I have to write Rout Attribute on it as well?
This should do the work:
[RoutePrefix("MySite/Security")]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpGet]
[HttpPost]
[Route("Login")]
public ActionResult Login()
{
return View("~/Views/Home/Index.cshtml");
}
}
EDITED:
There is one way, but I'm not sure if it's the best way. You need to create another controller called DefaultController like this:
public class DefaultController : Controller
{
//
// GET: /Default/
public ActionResult Index()
{
return RedirectToAction("Login","Home");
}
}
In your RouteConfig.cs, change the 'Default' route with this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Default", action = "Index", id = UrlParameter.Optional }
);
This should do the job. I'm still trying to find other better ways.
First, you should add custom route on the top of a default route, since you have 2 action methods with different HTTP protocols and want to make custom routing with same action name.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
// custom route
routes.MapRoute(
name: "Login",
url: "MySite/{controller}/{action}/{id}",
defaults: new { controller = "Security", action = "Login", id = UrlParameter.Optional }
);
// default route
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home" , action = "Index" , id = UrlParameter.Optional }
);
}
Note that your controller with Login method should be named SecurityController, then you can set attribute routing like this code:
// set all default prefix to /Security path
[RoutePrefix("Security")]
public class SecurityController : Controller
{
[Route("Login")]
public ActionResult Login()
{
return View();
}
}
Additionally, make sure you already registered the route in Global.asax file.
Any improvements & suggestions welcome.
I am having trouble implementing the routing in MVC 5. While debugging the expected url(e.g. http://localhost/Download/Blog/1cf15fe6033a489a998556fedeab20a2/Test/1cd15fe6033a489a998556fedeab20a2) causes the correct method on the Download controller to be called however the did and fid are always null. What am I doing wrong? I also tried removing the Download route and defining the routes in the controller with the following attributes:
[RoutePrefix("Download")] //on the controller
[Route("{action}/{did:guid}/Test/{fid:guid}")] //on the Blog Action
Here is what I have in my RouteConfig.cs:
routes.MapRoute(
name: "Download",
url: "Download",
defaults: new { controller = "Download", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}
);
here is my controller:
[Route("{action}/{did}/Test/{fid}")]
public class DownloadController : Controller
{
public ActionResult Index()
{
return Redirect(HandleBadResponse(webResponse));
}
[Route("{action}/{did}/Test/{fid}")]//nope
public ActionResult Blog(HttpRequestMessage request,string did,string fid)
{
string server = Request.ServerVariables["SERVER_NAME"];
string pathStr = #"\\mypath\1cf15fe6033a489a998556fedeab20a2.xls";
byte[] fileBytes = System.IO.File.ReadAllBytes(pathStr);
string fileName = "test.txt";
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}
I got the expected result by adding the following to my RouteConfig.cs I placed this route at the top of my RegisterRoutes method, I think you should go from most detailed route to the least detailed route:
routes.MapRoute(
name: "DownloadBlogAttachment",
url: "Download/Blog/{did}/fid/{fid}",
defaults: new { controller = "Download", action = "Blog"}
);
I removed the Route attributes in my controller as well.
i have project with Map Route (that's all):
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional }
);
and I have method in controller:
public ViewResult List(int id = 1)
{
...
}
and in List.cshtml:
#Html.ActionLink(i.ToString(), "List", "Product", new { id = i }, null)
but i want to change id to page, but not change it in RouteConfig.cs, i think that's some attribute which can config my route for action. I want this solution:
#Html.ActionLink(i.ToString(), "List", "Product", new { page = i }, null)
and
[maybe here I can add my specify route?]
public ViewResult List(int page = 1)
{
...
}
You can use attribute routing to override the convention.
First make sure attribute routing is enabled:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional }
);
}
}
Then add appropriate attribute to your controller method, for example:
[Route("YourControllerName/List/{page?}")]
public ViewResult List(int page = 1)
{
...
}
Question mark makes the page parameter optional.
If it's a default controller and action
[Route("")]
[Route("YourControllerName/List/{page?}")]
public ViewResult List(int page = 1)
{
...
}
More about attribute routing can be found here:
http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx
Do I have to route a special route for every action result in a controller, or do you do one route, and have to live by that standard thought the controller? I thought you could make a default route, and then a special route for any instance you wanted. I keep running into a problem where one of my routes will hit my action Results correctly, but then the others no longer work. This code is probably the wrong way, but hence why I am posting it here. PLease try to clarify this for me if you can. I understand that I am suppose to be able to do {controller}/{action}/{id} for example. So that should hit Settings/GetSite/{siteid} for the following
public ActionResult GetSite(int id);
Routes configuration:
routes.MapRoute(
"SettingsUpdateEnviorment",
"{controller}/{action}",
new { controller = "Settings", action = "UpdateProperties" },
new { httpMethod = new HttpMethodConstraint("POST") }
);
routes.MapRoute(
name: "ProfileRoute",
url: "Profiles/{userId}",
defaults: new
{
controller = "Profile",
action = "Index",
}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
"Settings", // Route name
"Settings/{id}", // URL with parameters
new { controller = "Settings", action = "Index" } // Parameter defaults
);
Controller Code:
public ActionResult Index(int id)
{
return View(model);
}
public ActionResult GetSite(int enviornmentID, string name)
{
return RedirectToAction("Index");
}
[HttpPost]
public ActionResult AddSite(int id)
{
return RedirectToAction("Index", new { id = id });
}
So, the URL works as expected for Settings/1 to hit the Index actionresult Index(int id). Then, when I try to do the ActionResult for GetSite(int enviornmentID, string name) using the following actionLink:
#Html.ActionLink(site.Name, "GetSite", "Settings", new { enviornmentID = Model.Enviorment.EnvironmentID, name = site.Name }, null)
It creates the URL correctly as follows: Settings/GetSite?enviornmentID=1&name=CaseyTesting2, but gives me an error stating that I am trying to send a null value to my Index(int id) actionResult. I thought that since I am using the action name and it's same params, that MVC will figure the route out? Why is this not functioning for me, or what I am doing wrong? Thanks!
I realized what I was doing thanks to this article http://www.itworld.com/development/379646/aspnet-mvc-5-brings-attribute-based-routing. I was mixing up the order, when I had everything else correct. Then I was missing the param names being identical, when everything else was correct. So I kept having minor issues when trying to find the problem out. I also switched to MVC5's attribute routing, and like it much more.
So this is my code that is now working:
RoutConfig
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "ProfileRoute",
url: "Profiles/{userId}",
defaults: new
{
controller = "Profile",
action = "Index",
}
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
The controller code
[Authorize]
[RoutePrefix("settings")]
[Route("{action=index}")]
public class SettingsController : ZenController
{
[Route("{id:int}")]
public ActionResult Index(int id)
{
return View(model);
}
[Route("GetSite/{sitename:alpha}")]
public ActionResult GetSite(string sitename)
{
return RedirectToAction("Index");
}
Thanks again everyone! Happy coding!