我创建了一个帮助程序扩展,它允许我在 MVC razor 中使用 UrlHelper
进行强类型表达式。这非常适合从 View 中解析我的 MVC Controller 的 URI。
<a href="@(Url.Action<HomeController>(c=>c.Index()))">Home</a>
<li>@(Html.ActionLink<AccountController>("Sign in", c => c.Signin(null)))</li>
<li>@(Html.ActionLink<AccountController>("Create an account", c => c.Signup(), htmlAttributes: null))</li>
@using (Html.BeginForm<ToolsController>(c => c.Track(null), FormMethod.Get, htmlAttributes: new { @class = "navbar-form", role = "search" })) {...}
我现在有一个 View ,我正在尝试使用 knockout 将一些数据发布到我的 web api 并且需要能够做这样的事情
var targetUrl = '@(Url.HttpRouteUrl<TestsApiController>(c => c.TestAction(null)))';
这样我就不必硬编码我的 url(魔术字符串)
我当前用于获取 Web API url 的扩展方法的实现定义如下。
private const string HttpRouteKey = "httproute";
public static string HttpRouteUrl<TController>(this UrlHelper urlHelper, Expression<Action<TController>> action)
where TController : System.Web.Http.ApiController {
RouteValueDictionary routeValues = InternalExpressionHelper.GetRouteValues(action);
if (!routeValues.ContainsKey(HttpRouteKey)) {
routeValues.Add(HttpRouteKey, true);
}
var scheme = urlHelper.RequestContext.HttpContext.Request.Url.Scheme;
var route = urlHelper.Action(null, null, rvd, scheme);
//I've also tried
//var route = urlHelper.HttpRouteUrl(null, rvd);
return route;
}
InternalExpressionHelper.GetRouteValues
检查表达式并生成将用于生成 url 的 RouteValueDictionary
。
问题是我的 route
总是返回 null
。以前关于 SO 和博客的问题表明,通过在字典中包含 httproute
将允许从 MVC.UrlHelper
路由集合中获取 WebApi Urls。
到目前为止,似乎没有一个接受的答案对我有用,因为我使用的是没有路由名称的属性路由。
最佳答案
当生成指向 Web API 路由的链接时,必须始终需要一个 RouteName
才能正常工作,我决定应用一种约定。
辅助扩展通过组合 Controller 名称和操作名称来确定 RouteName。
var routeName = string.Join("_", controllerName, actionName);
现在因为当从包含 Controller 名称和 Action 名称的表达式中提取信息时,它们也会显示在 url 中。不是很漂亮。
/api/tests/1/2?controller=TestsApi&action=Get
因此它们已从路由值中删除。
routeValues.Remove("controller");
routeValues.Remove("action");
更新扩展方法现在看起来像这样
private const string HttpRouteKey = "httproute";
public static string HttpRouteUrl<TController>(this UrlHelper urlHelper, Expression<Action<TController>> action)
where TController : System.Web.Http.Controllers.IHttpController {
var routeValues = InternalExpressionHelper.GetRouteValues(action);
if (!routeValues.ContainsKey(HttpRouteKey)) {
routeValues.Add(HttpRouteKey, true);
}
var controllerName = routeValues["controller"] as string;
routeValues.Remove("controller");
var actionName = routeValues["action"] as string;
routeValues.Remove("action");
var routeName = string.Join("_", controllerName, actionName);
var url = urlHelper.HttpRouteUrl(routeName, routeValues);
return url;
}
现在我只需要确保,如果我希望我的操作可用于从 MVC 或 Web API 生成的 url/链接,则必须应用遵循约定的 RouteName
“{controller}_{action}”
[RoutePrefix("api/tests")]
[AllowAnonymous]
public class TestsApiController : WebApiControllerBase {
[HttpGet]
[Route("{lat:double:range(-90,90)}/{lng:double:range(-180,180)}", Name = "TestsApi_Get")]
public object Get(double lat, double lng) {
return new { lat = lat, lng = lng };
}
}
到目前为止,当我测试它时大部分都有效
@section Scripts {
<script type="text/javascript">
var url = '@(Url.HttpRouteUrl<TestsApiController>(c => c.Get(1,2)))';
alert(url);
</script>
}
我得到了 /api/tests/1/2
,这是我想要的。
关于c# - 使用 MVC.UrlHelper 从 MVC View 中解析 WebApi 操作 Url,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36534447/