- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想得越多,我就越相信可以编写一个使用这些 URL 定义的自定义路由:
{var1}/{var2}/{var3}
Const/{var1}/{var2}
Const1/{var1}/Const2/{var2}
{var1}/{var2}/Const
{*var1}/{var2}/{var3}
{var1}/{*var2}/{var3}
{var1}/{var2}/{*var3}
http://localhost/Show/Topic/SubTopic/SubSubTopic/123/This-is-an-example
{action}/{*topicTree}/{id}/{title}
GetRouteData()
应该像这样工作:
GetVirtuaPath()
方法。
最佳答案
最近问的比较急,一般都是自己解决问题。很抱歉,但这是我对我所询问的那种路线的看法。任何人发现它有任何问题:让我知道。
在 URL 中的任何位置使用全能段路由
/// <summary>
/// This route is used for cases where we want greedy route segments anywhere in the route URL definition
/// </summary>
public class GreedyRoute : Route
{
#region Properties
public new string Url { get; private set; }
private LinkedList<GreedyRouteSegment> urlSegments = new LinkedList<GreedyRouteSegment>();
private bool hasGreedySegment = false;
public int MinRequiredSegments { get; private set; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="VivaRoute"/> class, using the specified URL pattern and handler class.
/// </summary>
/// <param name="url">The URL pattern for the route.</param>
/// <param name="routeHandler">The object that processes requests for the route.</param>
public GreedyRoute(string url, IRouteHandler routeHandler)
: this(url, null, null, null, routeHandler)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VivaRoute"/> class, using the specified URL pattern, handler class, and default parameter values.
/// </summary>
/// <param name="url">The URL pattern for the route.</param>
/// <param name="defaults">The values to use if the URL does not contain all the parameters.</param>
/// <param name="routeHandler">The object that processes requests for the route.</param>
public GreedyRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
: this(url, defaults, null, null, routeHandler)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VivaRoute"/> class, using the specified URL pattern, handler class, default parameter values, and constraints.
/// </summary>
/// <param name="url">The URL pattern for the route.</param>
/// <param name="defaults">The values to use if the URL does not contain all the parameters.</param>
/// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param>
/// <param name="routeHandler">The object that processes requests for the route.</param>
public GreedyRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
: this(url, defaults, constraints, null, routeHandler)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VivaRoute"/> class, using the specified URL pattern, handler class, default parameter values, constraints, and custom values.
/// </summary>
/// <param name="url">The URL pattern for the route.</param>
/// <param name="defaults">The values to use if the URL does not contain all the parameters.</param>
/// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param>
/// <param name="dataTokens">Custom values that are passed to the route handler, but which are not used to determine whether the route matches a specific URL pattern. The route handler might need these values to process the request.</param>
/// <param name="routeHandler">The object that processes requests for the route.</param>
public GreedyRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
: base(url.Replace("*", ""), defaults, constraints, dataTokens, routeHandler)
{
this.Defaults = defaults ?? new RouteValueDictionary();
this.Constraints = constraints;
this.DataTokens = dataTokens;
this.RouteHandler = routeHandler;
this.Url = url;
this.MinRequiredSegments = 0;
// URL must be defined
if (string.IsNullOrEmpty(url))
{
throw new ArgumentException("Route URL must be defined.", "url");
}
// correct URL definition can have AT MOST ONE greedy segment
if (url.Split('*').Length > 2)
{
throw new ArgumentException("Route URL can have at most one greedy segment, but not more.", "url");
}
Regex rx = new Regex(@"^(?<isToken>{)?(?(isToken)(?<isGreedy>\*?))(?<name>[a-zA-Z0-9-_]+)(?(isToken)})$", RegexOptions.Compiled | RegexOptions.Singleline);
foreach (string segment in url.Split('/'))
{
// segment must not be empty
if (string.IsNullOrEmpty(segment))
{
throw new ArgumentException("Route URL is invalid. Sequence \"//\" is not allowed.", "url");
}
if (rx.IsMatch(segment))
{
Match m = rx.Match(segment);
GreedyRouteSegment s = new GreedyRouteSegment {
IsToken = m.Groups["isToken"].Value.Length.Equals(1),
IsGreedy = m.Groups["isGreedy"].Value.Length.Equals(1),
Name = m.Groups["name"].Value
};
this.urlSegments.AddLast(s);
this.hasGreedySegment |= s.IsGreedy;
continue;
}
throw new ArgumentException("Route URL is invalid.", "url");
}
// get minimum required segments for this route
LinkedListNode<GreedyRouteSegment> seg = this.urlSegments.Last;
int sIndex = this.urlSegments.Count;
while(seg != null && this.MinRequiredSegments.Equals(0))
{
if (!seg.Value.IsToken || !this.Defaults.ContainsKey(seg.Value.Name))
{
this.MinRequiredSegments = Math.Max(this.MinRequiredSegments, sIndex);
}
sIndex--;
seg = seg.Previous;
}
// check that segments after greedy segment don't define a default
if (this.hasGreedySegment)
{
LinkedListNode<GreedyRouteSegment> s = this.urlSegments.Last;
while (s != null && !s.Value.IsGreedy)
{
if (s.Value.IsToken && this.Defaults.ContainsKey(s.Value.Name))
{
throw new ArgumentException(string.Format("Defaults for route segment \"{0}\" is not allowed, because it's specified after greedy catch-all segment.", s.Value.Name), "defaults");
}
s = s.Previous;
}
}
}
#endregion
#region GetRouteData
/// <summary>
/// Returns information about the requested route.
/// </summary>
/// <param name="httpContext">An object that encapsulates information about the HTTP request.</param>
/// <returns>
/// An object that contains the values from the route definition.
/// </returns>
public override RouteData GetRouteData(HttpContextBase httpContext)
{
string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
RouteValueDictionary values = this.ParseRoute(virtualPath);
if (values == null)
{
return null;
}
RouteData result = new RouteData(this, this.RouteHandler);
if (!this.ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest))
{
return null;
}
// everything's fine, fill route data
foreach (KeyValuePair<string, object> value in values)
{
result.Values.Add(value.Key, value.Value);
}
if (this.DataTokens != null)
{
foreach (KeyValuePair<string, object> token in this.DataTokens)
{
result.DataTokens.Add(token.Key, token.Value);
}
}
return result;
}
#endregion
#region GetVirtualPath
/// <summary>
/// Returns information about the URL that is associated with the route.
/// </summary>
/// <param name="requestContext">An object that encapsulates information about the requested route.</param>
/// <param name="values">An object that contains the parameters for a route.</param>
/// <returns>
/// An object that contains information about the URL that is associated with the route.
/// </returns>
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
RouteUrl url = this.Bind(requestContext.RouteData.Values, values);
if (url == null)
{
return null;
}
if (!this.ProcessConstraints(requestContext.HttpContext, url.Values, RouteDirection.UrlGeneration))
{
return null;
}
VirtualPathData data = new VirtualPathData(this, url.Url);
if (this.DataTokens != null)
{
foreach (KeyValuePair<string, object> pair in this.DataTokens)
{
data.DataTokens[pair.Key] = pair.Value;
}
}
return data;
}
#endregion
#region Private methods
#region ProcessConstraints
/// <summary>
/// Processes constraints.
/// </summary>
/// <param name="httpContext">The HTTP context.</param>
/// <param name="values">Route values.</param>
/// <param name="direction">Route direction.</param>
/// <returns><c>true</c> if constraints are satisfied; otherwise, <c>false</c>.</returns>
private bool ProcessConstraints(HttpContextBase httpContext, RouteValueDictionary values, RouteDirection direction)
{
if (this.Constraints != null)
{
foreach (KeyValuePair<string, object> constraint in this.Constraints)
{
if (!this.ProcessConstraint(httpContext, constraint.Value, constraint.Key, values, direction))
{
return false;
}
}
}
return true;
}
#endregion
#region ParseRoute
/// <summary>
/// Parses the route into segment data as defined by this route.
/// </summary>
/// <param name="virtualPath">Virtual path.</param>
/// <returns>Returns <see cref="System.Web.Routing.RouteValueDictionary"/> dictionary of route values.</returns>
private RouteValueDictionary ParseRoute(string virtualPath)
{
Stack<string> parts = new Stack<string>(virtualPath.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries));
// number of request route parts must match route URL definition
if (parts.Count < this.MinRequiredSegments)
{
return null;
}
RouteValueDictionary result = new RouteValueDictionary();
// start parsing from the beginning
bool finished = false;
LinkedListNode<GreedyRouteSegment> currentSegment = this.urlSegments.First;
while (!finished && !currentSegment.Value.IsGreedy)
{
object p = parts.Pop();
if (currentSegment.Value.IsToken)
{
p = p ?? this.Defaults[currentSegment.Value.Name];
result.Add(currentSegment.Value.Name, p);
currentSegment = currentSegment.Next;
finished = currentSegment == null;
continue;
}
if (!currentSegment.Value.Equals(p))
{
return null;
}
}
// continue from the end if needed
parts = new Stack<string>(parts.Reverse());
currentSegment = this.urlSegments.Last;
while (!finished && !currentSegment.Value.IsGreedy)
{
object p = parts.Pop();
if (currentSegment.Value.IsToken)
{
p = p ?? this.Defaults[currentSegment.Value.Name];
result.Add(currentSegment.Value.Name, p);
currentSegment = currentSegment.Previous;
finished = currentSegment == null;
continue;
}
if (!currentSegment.Value.Equals(p))
{
return null;
}
}
// fill in the greedy catch-all segment
if (!finished)
{
object remaining = string.Join("/", parts.Reverse().ToArray()) ?? this.Defaults[currentSegment.Value.Name];
result.Add(currentSegment.Value.Name, remaining);
}
// add remaining default values
foreach (KeyValuePair<string, object> def in this.Defaults)
{
if (!result.ContainsKey(def.Key))
{
result.Add(def.Key, def.Value);
}
}
return result;
}
#endregion
#region Bind
/// <summary>
/// Binds the specified current values and values into a URL.
/// </summary>
/// <param name="currentValues">Current route data values.</param>
/// <param name="values">Additional route values that can be used to generate the URL.</param>
/// <returns>Returns a URL route string.</returns>
private RouteUrl Bind(RouteValueDictionary currentValues, RouteValueDictionary values)
{
currentValues = currentValues ?? new RouteValueDictionary();
values = values ?? new RouteValueDictionary();
HashSet<string> required = new HashSet<string>(this.urlSegments.Where(seg => seg.IsToken).ToList().ConvertAll(seg => seg.Name), StringComparer.OrdinalIgnoreCase);
RouteValueDictionary routeValues = new RouteValueDictionary();
object dataValue = null;
foreach (string token in new List<string>(required))
{
dataValue = values[token] ?? currentValues[token] ?? this.Defaults[token];
if (this.IsUsable(dataValue))
{
string val = dataValue as string;
if (val != null)
{
val = val.StartsWith("/") ? val.Substring(1) : val;
val = val.EndsWith("/") ? val.Substring(0, val.Length - 1) : val;
}
routeValues.Add(token, val ?? dataValue);
required.Remove(token);
}
}
// this route data is not related to this route
if (required.Count > 0)
{
return null;
}
// add all remaining values
foreach (KeyValuePair<string, object> pair1 in values)
{
if (this.IsUsable(pair1.Value) && !routeValues.ContainsKey(pair1.Key))
{
routeValues.Add(pair1.Key, pair1.Value);
}
}
// add remaining defaults
foreach (KeyValuePair<string, object> pair2 in this.Defaults)
{
if (this.IsUsable(pair2.Value) && !routeValues.ContainsKey(pair2.Key))
{
routeValues.Add(pair2.Key, pair2.Value);
}
}
// check that non-segment defaults are the same as those provided
RouteValueDictionary nonRouteDefaults = new RouteValueDictionary(this.Defaults);
foreach (GreedyRouteSegment seg in this.urlSegments.Where(ss => ss.IsToken))
{
nonRouteDefaults.Remove(seg.Name);
}
foreach (KeyValuePair<string, object> pair3 in nonRouteDefaults)
{
if (!routeValues.ContainsKey(pair3.Key) || !this.RoutePartsEqual(pair3.Value, routeValues[pair3.Key]))
{
// route data is not related to this route
return null;
}
}
StringBuilder sb = new StringBuilder();
RouteValueDictionary valuesToUse = new RouteValueDictionary(routeValues);
bool mustAdd = this.hasGreedySegment;
// build URL string
LinkedListNode<GreedyRouteSegment> s = this.urlSegments.Last;
object segmentValue = null;
while (s != null)
{
if (s.Value.IsToken)
{
segmentValue = valuesToUse[s.Value.Name];
mustAdd = mustAdd || !this.RoutePartsEqual(segmentValue, this.Defaults[s.Value.Name]);
valuesToUse.Remove(s.Value.Name);
}
else
{
segmentValue = s.Value.Name;
mustAdd = true;
}
if (mustAdd)
{
sb.Insert(0, sb.Length > 0 ? "/" : string.Empty);
sb.Insert(0, Uri.EscapeUriString(Convert.ToString(segmentValue, CultureInfo.InvariantCulture)));
}
s = s.Previous;
}
// add remaining values
if (valuesToUse.Count > 0)
{
bool first = true;
foreach (KeyValuePair<string, object> pair3 in valuesToUse)
{
// only add when different from defaults
if (!this.RoutePartsEqual(pair3.Value, this.Defaults[pair3.Key]))
{
sb.Append(first ? "?" : "&");
sb.Append(Uri.EscapeDataString(pair3.Key));
sb.Append("=");
sb.Append(Uri.EscapeDataString(Convert.ToString(pair3.Value, CultureInfo.InvariantCulture)));
first = false;
}
}
}
return new RouteUrl {
Url = sb.ToString(),
Values = routeValues
};
}
#endregion
#region IsUsable
/// <summary>
/// Determines whether an object actually is instantiated or has a value.
/// </summary>
/// <param name="value">Object value to check.</param>
/// <returns>
/// <c>true</c> if an object is instantiated or has a value; otherwise, <c>false</c>.
/// </returns>
private bool IsUsable(object value)
{
string val = value as string;
if (val != null)
{
return val.Length > 0;
}
return value != null;
}
#endregion
#region RoutePartsEqual
/// <summary>
/// Checks if two route parts are equal
/// </summary>
/// <param name="firstValue">The first value.</param>
/// <param name="secondValue">The second value.</param>
/// <returns><c>true</c> if both values are equal; otherwise, <c>false</c>.</returns>
private bool RoutePartsEqual(object firstValue, object secondValue)
{
string sFirst = firstValue as string;
string sSecond = secondValue as string;
if ((sFirst != null) && (sSecond != null))
{
return string.Equals(sFirst, sSecond, StringComparison.OrdinalIgnoreCase);
}
if ((sFirst != null) && (sSecond != null))
{
return sFirst.Equals(sSecond);
}
return (sFirst == sSecond);
}
#endregion
#endregion
}
/// <summary>
/// Represents a route segment
/// </summary>
public class RouteSegment
{
/// <summary>
/// Gets or sets segment path or token name.
/// </summary>
/// <value>Route segment path or token name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this segment is greedy.
/// </summary>
/// <value><c>true</c> if this segment is greedy; otherwise, <c>false</c>.</value>
public bool IsGreedy { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this segment is a token.
/// </summary>
/// <value><c>true</c> if this segment is a token; otherwise, <c>false</c>.</value>
public bool IsToken { get; set; }
}
/// <summary>
/// Represents a generated route url with route data
/// </summary>
public class RouteUrl
{
/// <summary>
/// Gets or sets the route URL.
/// </summary>
/// <value>Route URL.</value>
public string Url { get; set; }
/// <summary>
/// Gets or sets route values.
/// </summary>
/// <value>Route values.</value>
public RouteValueDictionary Values { get; set; }
}
关于asp.net-mvc - Asp.net MVC Route 类,支持 URL 中任何位置的全部参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2378222/
您好,如果没有身份验证,我尝试保护路由,但它不起作用 警告:您不应在同一个 route 使用路线组件和路线渲染;路线渲染将被忽略 App.js import React, { Fragment,
几乎我见过的每个示例,app.js 都使用 require 和路径 ./。我想知道为什么我们不能只使用 /。例如,为什么我们不能执行以下操作。 var express = require('expre
如果router.all()只匹配所有方法,是否可以用router.use()代替?router.use() 和 router.route() 之间有什么区别? 最佳答案 router.all:这意味
在我的 Symfony应用程序我想根据当前用户的文化选择 routing.yml; 'en' => routing.en.yml 'no' => routing.no.yml 等等。 关于如何做到这一
我正在使用 React Router v6 并为我的应用程序创建私有(private)路由。 在文件 PrivateRoute.js 中,我有代码 import React from 'react';
这个问题在这里已经有了答案: Error "Error: A is only ever to be used as the child of element" (14 个回答) Error: [P
我正在关注 Ember Quick Start guide (ember-cli v 2.11),并按照说明构建玩具应用程序。在“定义路线”部分,说明说要运行命令 ember generate rou
这个问题在这里已经有了答案: ReactJS: [Home] is not a component. All component children of must be a or (5 个答
这个问题在这里已经有了答案: ReactJS: [Home] is not a component. All component children of must be a or (5 个答
单击“开始测验”按钮时,我试图导航到“/quiz”。 但是,当我编译我的代码时,我在网站应用程序上收到以下错误:[Home] is not a component. All component ch
我有一点咸菜。我正在使用路由保护(实现 CanActivate 接口(interface))来检查用户是否被授予访问特定路由的权限: const routes: Routes = [ {
我正在尝试测试我的应用程序正在使用的引擎内部的 Controller 。规范不在引擎中,而是在应用程序本身中(我试图在引擎中进行测试,但也遇到了问题)。 我的引擎有以下 routes.rb: Revi
我是Remix的新手,我正在尝试使用V2路由方法实现特定的路由解决方案。。这是一个人为的例子,不是真实的东西,只是为了说明这一点。。我想要的URL方案是:。我从以下几条路线开始:。App/routes
我正在尝试从 rails 2.3.x(使用 subdomain_routes 插件)转换一些子域路由,如下所示: map.subdomain :biz do |biz| biz.resources
我将 Symfony 的 3.1 路由组件用作独立组件。 我想调试路由。 据此: http://symfony.com/doc/current/routing/debug.html 这是通过运行以下命
我是 Sparkjava 的新手,总体上喜欢它。但是,是否必须在 main 方法中定义新的路由/端点?对于任何重要的 Web 应用程序,这将导致一个非常长的 main 方法,或者我需要有多个 main
我刚刚使用node.js 和express.js 开发了一个原型(prototype)。在这里,我使用了 Express 路由来对后端进行 CRUD。 server.js 文件: app.get('/
我不明白 Angular 4 中路由的一些基本概念。 index.html: 文件结构: - app |- app.routings.ts |- collections |-- collection
我在反应路线和理解合成路线方面遇到了一些困难。我尝试了一些代码,但不幸的是,它不能像预期的那样工作。“/”路径运行得很好,但是,当我尝试访问“/Child”时,它似乎不起作用。我认为包装器路由}/>可
我正在尝试使用 cakephp 3 实现 REST api。 为了给我的问题提供一个易于重现的示例,我从全新安装 cakephp 3.1.11 开始。 在 config/routes.php 中,我添
我是一名优秀的程序员,十分优秀!