c# - 使用 MVC.UrlHelper 从 MVC View 中解析 WebApi 操作 Url

标签 c# asp.net-mvc asp.net-mvc-4 asp.net-web-api asp.net-web-api-routing

我创建了一个帮助程序扩展,它允许我在 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&amp;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/

相关文章:

c# - DbContext 已被释放

asp.net-mvc - mvc4 + 编译错误信息 : CS1963: An expression tree may not contain a dynamic operation

asp.net - 将 MVC 站点部署到 IIS 会导致它找不到默认的共享局部 View

javascript - 在局部 View 上设置拖放区的正确方法是什么?

c# - 抽象属性的可访问性

c# - 使用 MediaCapture 从 CaptureElement 以自定义分辨率拍摄照片

c# - 从 VB 转换为 C#

c# - awesomium 中的网页外观

asp.net-mvc - 您如何使用 Razor 在网址中转义 '@' 符号

c# - 如何将文件中的 "0x1B"替换为空,即删除