C# 使用ASP.NET Web API创建基于路由的模板化HREF
在Web API控制器中向资源表示添加链接非常容易。使用控制器的C# 使用ASP.NET Web API创建基于路由的模板化HREF,c#,asp.net-web-api2,url-template,C#,Asp.net Web Api2,Url Template,在Web API控制器中向资源表示添加链接非常容易。使用控制器的Url属性(属于UrlHelper类),您可以使用路由名称构建链接的href,如下所示: var href = Url.Link("RouteName", new { id = 123 }); var href = this.GetTemplatedHref("DefaultApi", "product"); href的值是根据路线配置计算的-在本例中类似于http://example.org/api/products/123。
Url
属性(属于UrlHelper
类),您可以使用路由名称构建链接的href,如下所示:
var href = Url.Link("RouteName", new { id = 123 });
var href = this.GetTemplatedHref("DefaultApi", "product");
href
的值是根据路线配置计算的-在本例中类似于http://example.org/api/products/123
。这很好,因为我可以调整路由配置,而无需更新生成HREF的所有位置。发出的所有链接都符合新配置
但是,这项技术或任何类似的基于路由的技术能否用于创建模板化的HREF?例如,要使用HAL的templated
link属性创建从某个资源到任意产品的链接:
"_links": {
"self": {
"href": "http://example.org/api/productfinder"
},
"product": {
"href": "http://example.org/api/products/{productId}",
"templated": true
}
}
(我没有一个叫做productfinder的资源——只是这个问题的一个人为的例子)
我尝试将routeValues
参数设置为模板的字符串,例如
var href = Url.Link("RouteName", new { id = "{productId}" });
这将生成一个URL编码字符串:http://example.org/api/products/%7BproductId%7D
。我可以使用.Replace
,但这种方法由于另一个原因而失败。如果路由配置具有类型约束,例如{id:int}
,则href变为null
我尝试将null传递给routeValues
,希望随后可以添加模板部分Link()
返回null,因此href
最终只是模板部分。另外,对于像api/{this}/something/{that}{?q}
所以我被卡住了。我可以使用路由生成模板化的HREF吗?如果是这样,怎么做?好吧,我花了一段时间,但我有一些有效的方法。诀窍是从配置的路由表中查找
RouteTemplate
。每个控制器都有一个对配置的引用。从那以后,一切都很容易
我为ApiController
创建了一个扩展类。实际上,我可能会将ApiController子类化,但想法是一样的。另外,我可以返回Uri
对象,而不是使用.ToString()
public static class ApiControllerExtensions
{
public static string GetTemplatedHref(this ApiController controller, string routeName, string controllerName = "")
{
var routeTemplate = controller.Configuration.Routes[routeName].RouteTemplate;
var baseUri = new Uri(controller.Request.RequestUri.GetLeftPart(UriPartial.Authority));
var templatedHref = new Uri(baseUri, routeTemplate).ToString();
return string.IsNullOrEmpty(controllerName) ?
templatedHref :
templatedHref.Replace("{controller}", controllerName.ToLower());
}
}
现在,当我在控制器的方法中需要一个模板href时,我可以这样做:
var href = this.GetTemplatedHref("RouteName");
这适用于管线属性。它也适用于预先配置的路由,例如:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
因此,我可以提供控制器名称并获得模板href,如下所示:
var href = Url.Link("RouteName", new { id = 123 });
var href = this.GetTemplatedHref("DefaultApi", "product");
在实践中,我将再次进行修改和调整,例如添加绝对/相对等选项。但使用管线名称获取模板的核心问题现在已经解决