ASP.NET MVC3 dynamic routing - asp.net

I'm having trouble finding the answer to this question anywhere.
I am in need of creating a form where the user can create a post and change the url to the post.
For example, if the default route is
http://www.domain.com/posts/[the-title-of-the-post]
The user can change this to
http://www.domain.com/[modified-title-of-the-post].
The [modified-title-of-the-post] can be anything the user would like to make it.
This means it is no longer tied to the title of the post and not only that, but the /posts/ is gone too.
I guess I should Also mention that this should be global, meaning the user should be able to change the url (as mentioned above) for other things on the sites like, /topics/ or /blog/
Any help would be greatly appreciated,
Thanks,
Hiva

You could create two routes in your global.asax. Something like this
routes.MapRoute("", "posts/{url}", new { controller = "Home", action = "Posts" });
routes.MapRoute("", "{url}", new { controller = "Home", action = "Posts" });
both of them point to HomeController and the action Posts
public ActionResult Posts(string url)
{
}
to handle every url you should consider to extend the RouteBase class
Something like that should do
public class CustomRouting : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
RouteData result = null;
string requestUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath;
//Handle the request
//Compile the RouteData with your data
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "MyController");
result.Values.Add("action", "MyAction");
result.Values.Add("id", MyId);
}
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//I only need to handle outbound so here is ok
return null;
}
}
The in your global.asax you register your custom route handler
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new CustomRouting());
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}

Related

MVC can't display certain actions

I am developing an ASP.NET MVC application. Content is divided into several areas:
Scheme - for shared functionality like errors
Pages - for displayed content
Data - for controllers, that returns JSON data
I don't have any controllers not assigned to areas.
I would like to access Pages controllers without typing area's name, and other to be accessed with their area names in route.
So I want to display action Users in Administration page under host/Administration/Users
And I want to display DatabaseTimeout Action from Error controller under host/Scheme/Error/DatabaseTimeout.
Analogously I want Create action from Codes controller from Data area under host/Data/Codes/Create.
Now, the problem: Pages area works as expected, Data area works as expected, Scheme area doesn't work as expected. When typing host/Scheme/Error/DatabaseTimeout application returns a 404.
Can anyone tell me what is wrong?
Here is part of application code:
Global.asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
}
DataAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Data_default",
"Data/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MyWebApplication.Areas.Data.Controllers" }
);
}
PagesAreaRegistration.cs:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Pages_default",
"{controller}/{action}/{id}",
new { controller="Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MyWebApplication.Areas.Pages.Controllers" }
);
}
SchemeAreaRegistration.cs:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Scheme_default",
"Scheme/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MyWebApplication.Areas.Scheme.Controllers" }
);
}
AdministrationController.cs from Pages area:
namespace MyWebApplication.Areas.Pages.Controllers
{
public class AdministrationController : Controller
{
// action methods...
}
}
CodesController.cs from Data area:
namespace MyWebApplication.Areas.GridData.Controllers
{
public class CountryCodesController : Controller
{
// action methods...
}
}
ErrorController.cs from Scheme area:
namespace MyWebApplication.Areas.Scheme.Controllers
{
public class ErrorController : Controller
{
// action methods...
}
}
EDIT:
Ok, now I am really confused.
So under Scheme area I have, among others:
- _Layout.cshtml file, wchich is master page for every showed page
- Menu.cshtml, which is view for Menu action and is rendered on _Layout
Menu view is rendered by:
#{Html.RenderAction("Index", "Menu", new { area="Scheme" });}
Menu is rendered fine, however...
In menu there is many action links, that directs into different pages, written like this:
#Html.ActionLink("Manage users", "Users", "Administration", new { area = "Pages" }, null)
And that gives route like this: host/Scheme/Administration/Users
Eventhough area was specified. I tried to change area parameter into area="", did't help.
Please help me, I am confused and I cant go further with my work. :(
When you type host/Scheme/Error/DatabaseTimeout probably application returns a 404 because you don't have a action DatabaseTimeout in ErrorController.cs in Scheme area:
namespace MyWebApplication.Areas.Scheme.Controllers
{
public class ErrorController : Controller
{
public ActionResult DatabaseTimeout()
{
return View();
}
}
}
You must create the view ,where you show the error at the user, in your project under Areas\Scheme\Views\Error\DatabaseTimeout.cshtml.
The other question --> i think that if you want create a link to action Index() in HomeController under Schemearea you must use this in the views:
#Html.ActionLink("Home", "Index", "Home", new { area = "Scheme" }, null)

How to format the URL of my ASP.NET MVC 5 website

I have a website and it's url appears on the browser llike this:
mysite.com/Produto/PaoDeMel
and for SEO reasons I'd like it to be like:
mysite.com/produto/pao-de-mel
but my actionname is PaoDeMel, and the framework doesn't let me use "-" on the name.
Is there a routing config or anything else to achieve my goal?
PS.: the solution suggested in How do I change the url in MVC 5? didn't work for me.
Thanks
You need to implement IRouteHandler and IHttpHandler interfaces (special attention on ProcessRequest method of IHttpHandler implementation):
public class MyRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MyHttpHandler();
}
}
public class MyHttpHandler : IHttpHandler
{
public bool IsReusable
{
get
{
return true;
}
}
public void ProcessRequest(HttpContext context)
{
// Take routes values to build a url string that can be handled by "Default" route
string url = "/" + context.Request.RequestContext.RouteData.Values["controller"].ToString().ToLower();
url += "/" + (context.Request.RequestContext.RouteData.Values["part1"] as string).Replace("-", "").ToLower() + (context.Request.RequestContext.RouteData.Values["part2"] as string).Replace("-", "").ToLower();
url += "/" + context.Request.RequestContext.RouteData.Values["id"];
context.Server.TransferRequest(url, true);
}
}
Next, add routes that handle default and custom routing:
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 },
constraints: new { action = #"[^\-]*" }
);
routes.Add("MyRoute",
new Route("{controller}/{part1}-{part2}/{id}",
new RouteValueDictionary { { "controller", "Home" }, { "action", "Index" }, { "id", "" } },
new MyRouteHandler() // Custom route handler
)
);
}
No matter how many hyphens have your url in action segment (mysite.com/produto/pao-de-mel, mysite.com/produto/pao-de-mel-a-b-c, etc.), this will be captured by the "MyRoute" route, and will be processed by MyRouteHandler that will transform the path into a url that can be handled by the "Default" route, achieving this, by transfering the request to be processed by normal flow of ASP.NET MVC Routing.

Mvc4 Querystring parameter is not working

In Asp.net MVC4 I have created below URL showing 404 error with IIS8.0
http://{ParentURL}/Areas/Admin/Menu/Index?actoin=Add
Please help me on it.
You URL http://{ParentURL}/Areas/Admin/Menu/Index?mode=Add goes to:
Area: Admin
Controller: Menu
Action + View: Index
Parameter: mode
So in MenuController.cs (under Admin area) you should have this:
public ActionResult Index(string mode)
{
//code
return View();
}
UPDATE:
Change your URL to: http://{ParentURL}/Admin/Menu/Index?mode=Add
The parameters of your Action must have the same name as in your route declaration.
Also another mistake is to use Areas in your URL, you can remove it or change your default route.
Controller:
public ActionResult Index(string mode)
{
return View(ViewMenuModel);
}
View:
var JsSuccessAction = '#Url.Content("~/Admin/Menu/Index?mode=Add")';
Route:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute( "Admin_default", "Admin/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } );
}
You need to set a route in route config :
context.MapRoute(
"Areas",
"Areas/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
add this to your root config and try .. will work

Map Routing MVC3

Maybe my question is very easy to respond, but I am new in MVC3.
I have these possible routes in my MVC3 Web project:
/brands/brandID
/brands/{action}/{parameters}
where brands is my controller and brandID is a specific parameter that receives my Index action. Also, my brands controller has more actions and I need to define in the Global.asax the correct map routes to make it work.
There's an example in the Custom Routing (modified for your case).
Global.asax:
routes.MapRoute(
"BrandDetails",
"Brands/{brandID}",
new { controller = "Brands", action = "Details" },
new { brandID = #"\d+" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
BrandsController:
public ActionResult Index()
{
return View();
}
public ActionResult Details(int brandID)
{
return this.View(brandID);
}

ASP.NET MVC - Routes

I'm working on an MVC application and I have and admin area... So what I need is:
When user makes request to admin (for example "/Admin/Post/Add") I need to map this to controller AdminPost and action Add... is it possible?
If your controller is named AdminPostController and you want it to map to '/Admin/Post/Add' then you can use:
routes.MapRoute("Admin", // Route name
"Admin/Post/{action}/{id}", // URL with parameters
new { controller = "AdminPost", action = "Add", id = "" } // Parameter defaults
);
Note the use of the parameter defaults.
If your controller is named AdminController and you just wanted to separate the request method then use the default:
routes.MapRoute("Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
Which will map '/Admin/Add/' to the controller:
public class AdminController : Controller {
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(int id) {
//...
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Add(int id) {
//...
}
}
Note the use of [AcceptVerbs] to identify which method to invoke for POST requests and GET requests.
See Scott Gu's blog for more details

Resources