MVC路由可重复的模式?

时间:2015-09-22 20:17:12

标签: asp.net-mvc asp.net-core asp.net-core-mvc url-routing asp.net-mvc-routing

我正在处理的网站的设计目标是将浏览器中的URL保持在用户可以复制它的状态,并且可以从其他浏览器/用户/机器使用链接返回到现场网址被复制了。 (实际更改将通过AJAX进行,但URL将更改以反映它们的位置。)

示例:如果您在客户页面上查看客户123,并且在订单#456上提取了详细信息,并且在此订单的第6行中提供了详细信息,那么您的网址可能只是/ customer / 123/456 / 6

挑战来自第二个功能:用户可以添加UI列(类似于在选项卡视图中添加新选项卡,或在MDI应用程序中添加新文档)每列都可以轻松生成可路由的URL,但我需要url反映一个或多个列。 (E.G.用户在两个并排的列中同时包含/ customer / 123/456/6和/ customer / 333/55/2)

在一个完美的世界中,我希望上面的场景中的url是/ customer / 123/456/6 / customer / 333/55/2,但我不知道MVC路由是否可以处理重复模式,或者,如果是这样,它是如何完成的。

这可以通过路由完成吗?如果没有办法从Url获​​得这种类型的一个或多个功能?

2 个答案:

答案 0 :(得分:3)

您可以创建自定义路由处理程序(see my previous answer),也可以从public class CustomerInvoiceLineAttribute : CustomModelBinderAttribute { public override IModelBinder GetBinder() { return new CustomerInvoiceLineModelBinder(); } } public class CustomerInvoiceLineModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var path = (string)bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue; var data = path.Split(new[] { "/customer/" }, StringSplitOptions.RemoveEmptyEntries); return data.Select(d => { var rawInfo = d.Split('/'); return new CustomerInvoiceLine { CustomerId = int.Parse(rawInfo[0]), InvoiceId = int.Parse(rawInfo[1]), Line = int.Parse(rawInfo[2]) }; }); } } NightOwl888 suggested派生。另一种方法是简单地使用模型绑定器和模型绑定器属性。

routes.MapRoute(
    name: "CustomerViewer",
    url: "customer/{*customerInfo}",
    defaults: new { controller = "Customer", action = "Index" });

您可以通过指定星型路线数据来定义路线。这意味着route参数将包含操作后的所有内容

public ActionResult Index([CustomerInvoiceLine] IEnumerable<CustomerInvoiceLine> customerInfo)
{
    return View();
}

然后在您的控制器中,使用上面定义的自定义模型绑定器将参数与星型路径参数绑定:

Publisher.Application firstPubApp = new Publisher.Application(); //open a new publisher instance
Publisher.Document sourcePublication = firstPubApp.Open("sourcefile.pub"); //open your publisher document

Publisher.Application otherPubApp = new Publisher.Application();
Publisher.Document targetPublication = otherPubApp.Open("targetfile.pub");
targetPublication.Pages.Add(1, 1); //add one page after page 1

foreach (Publisher.Shape shape in sourcePublication.Pages[1].Shapes) //loop through all pages on page 1
{
    shape.Copy(); //copy the shape
    otherPubApp.ActiveDocument.Pages[2].Shapes.Paste(); //paste it in the other document
}

您需要在解析期间添加验证,也可能需要安全性,以便客户无法阅读其他客户的发票。

还要知道该网址有maximum length of 2000 characters

答案 1 :(得分:1)

您可以使用内置路由执行此操作,只要您不希望任何模式重复或具有与其他可选参数不在URL的同一段中出现的可选参数。< / p>

factoring out all of the permutations可以使用带有可选参数的路由,但是如果你问我,为此目的使用查询字符串要简单得多。

  

注意:根据定义,URL必须是唯一的。因此,您必须手动确保您的网址没有任何冲突。最简单的方法是将页面与路径(路径)匹配,并将此额外信息添加为查询字符串值。这样你就不必担心意外地制作完全相同的路线。

     

但是,如果您坚持为此目的使用路由,则应该将URL放在具有唯一约束的字段中的数据库中,以确保它们是唯一的。

对于最高级的路由自定义,subclass RouteBaseRoute。这允许您将任何URL映射到一组路由值,并将路由值映射回相同的URL ,这使您可以在ActionLinkRouteLink中使用它为视图和控制器构建URL。

public class CustomPageRoute : RouteBase
{
    // This matches the incoming URL and translates it into RouteData
    // (typically a set of key value pairs in the RouteData.Values dictionary)
    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        RouteData result = null;

        // Trim the leading slash
        var path = httpContext.Request.Path.Substring(1);

        if (/* the path matches your route logic */)
        {
            result = new RouteData(this, new MvcRouteHandler());

            result.Values["controller"] = "MyController";
            result.Values["action"] = "MyAction";

            // Any other route values to match your action...
        }

        // IMPORTANT: Always return null if there is no match.
        // This tells .NET routing to check the next route that is registered.
        return result;
    }

    // This builds the URL for ActionLink and RouteLink
    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        VirtualPathData result = null;

        if (/* all of the expected route values match the request (the values parameter) */)
        {
            result = new VirtualPathData(this, page.VirtualPath);
        }

        // IMPORTANT: Always return null if there is no match.
        // This tells .NET routing to check the next route that is registered.
        return result;
    }
}

用法

routes.Add(
    name: "CustomPage", 
    item: new CustomPageRoute());

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