我正在处理的网站的设计目标是将浏览器中的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获得这种类型的一个或多个功能?
答案 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 RouteBase
或Route
。这允许您将任何URL映射到一组路由值,并将路由值映射回相同的URL ,这使您可以在ActionLink
或RouteLink
中使用它为视图和控制器构建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 }
);