MVC Dynamic Routes

半世苍凉 提交于 2020-01-12 10:19:04

问题


I would like to create dynamic urls that route to controller actions with an Id value. I've created the following route using a catch-all parameter

routes.MapRoute(
            "RouteName",                                                 
            "{id}/{*Url}",
            new { controller = "Controller", action = "Action", id = "" }
        );

This works as expected and allows me to use the following Urls:

"http://website.com/1/fake/url/path" (1 being the id that gets passed to the action method)

Does anyone know a way to achieve it this way instead without creating my own http module?:

"http://website.com/fake/url/path/1"

Thanks - Mark


回答1:


That's a really difficult one, for me anyway.

Given the following route:

routes.MapRoute("Default", "{*token}", 
    new { controller = "Home", action = "Index", token = 0 });

Your controller and supporting classes would be something like this:

[HandleError]
public class HomeController : Controller
{
    public ActionResult Index([ModelBinder(typeof(IndexReqquestBinder))] IndexRequest request)
    {
        ViewData["Title"] = "Home Page";
        ViewData["Message"] = String.Format("We're looking at ID: {0}", request.ID);

        return View();
    }
}

public class IndexRequest
{
    public Int32 ID { get; set; }
    public IndexRequest(Int32 id)
    {
        this.ID = id;
    }
}

public class IndexReqquestBinder : IModelBinder
{
    public ModelBinderResult BindModel(ModelBindingContext bindingContext)
    {
        if ( null != bindingContext.RouteData.Values["token"] ) {
            foreach ( String v in bindingContext.RouteData.Values["token"].ToString().Split('/') ) {
                Int32 id = 0;
                if ( Int32.TryParse(v, out id) ) {
                    return new ModelBinderResult(new IndexRequest(id));
                }
            }

        }
        return new ModelBinderResult(new IndexRequest(0));
    }
}



回答2:


Routes redirection is based on route entry in the route table. It must be in systematic way. For instance if you have route as "customurl/id" after {controller}/{action}/{id}(default of mvc) when you will enter "customurl" in the url box it will take it as default route and no page found exception will occur. So if you wan to use custom route then first remove the default route. I do this like.

RouteCollection routes = RouteTable.Routes;
                    if (routes["rname"] != null)
                    {
                        RouteTable.Routes.Remove(routes["rname"]);
                    }
                         routes.Remove(routes["Default"]);                           
                        routes.MapRoute(
                            name: "newname",
                            url: url + "/{customId}",
                            defaults: new { controller = "Search", action = "Index", customId = UrlParameter.Optional }
                            );

                        //default route value
                        routes.MapRoute(
                            name: "Default",
                            url: "{controller}/{action}/{id}",
                            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                            );



回答3:


I would suggest overriding of DefaultControllerFactory

> public class CustomControllerFactory : DefaultControllerFactory
>   {
> public override IController
> CreateController(System.Web.Routing.RequestContext
> requestContext, string controllerName)
>         {
>             try
>             {
>                 return base.CreateController(requestContext,
> controllerName);
>             }
>             catch (Exception exception)
>             {
>                 // collect route data
>                 string id = (string)requestContext.RouteData.Values["id"];
>                 string action = (string)requestContext.RouteData.Values["action"];
>                 // set full path as routing "page" parameter
>                 VirtualPathData path = requestContext.RouteData.Route.GetVirtualPath(requestContext,
> requestContext.RouteData.Values);
>                 requestContext.RouteData.Values["id"]
> = path.VirtualPath; // or anything you need
>                 // use controller page by default
>                 controllerName = "MyController";
>                 // set basuc routing data
>                 requestContext.RouteData.Values["controller"]
> = controllerName;
>                 requestContext.RouteData.Values["action"]
> = "index";
>                 // call base method to create controller
>                 return base.CreateController(requestContext,
> controllerName);
>             }
>         }
>}

And than just register this as default controller factory in global.asax.cs file

protected void Application_Start()
        {
            ControllerBuilder.Current.SetControllerFactory(new MyNameSpace.CustomControllerFactory ());
            RegisterRoutes(RouteTable.Routes); // this already exists by default
        }


来源:https://stackoverflow.com/questions/296284/mvc-dynamic-routes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!