在Razor视图中将Querystring转换为RouteValue

本文关键字:转换 RouteValue Querystring Razor 视图 | 更新日期: 2023-09-27 17:54:30

我被视图中一个非常基本的细节困住了。

我希望能够让用户在索引视图中过滤结果。

为此,我创建了一个下拉列表,它通过我的viewmodel填充:

@using (Html.BeginForm("Index", "Captains", FormMethod.Get)) { 
    <div class="row">
        <div class="dropdown">
            @Html.DropDownList("Name", new SelectList(Model.SomeProperty), new { id = "FilterList" })    
        </div>
    </div>
 @* ... *@
}

另外,我有一个小的jQuery片段,用于在更改事件时提交表单:

$('#FilterList').on('change', function () {
    var form = $(this).parents('form');
    form.submit();
});

我为此创建的路由如下所示:

routes.MapRoute(
        name: "IndexFilter",
        url: "{controller}/{action}/{Name}",
        defaults: new { Name = UrlParameter.Optional}
);

提交事件后,我被重定向到url /Index?Name=ChosenValue 这是完全正确的过滤。然而,我想摆脱查询字符串,并将路由转换为 /Index/ChosenValue

备注:"Name", "ChosenValue" &"SomeProperty"只是替换了实际的属性名。

在Razor视图中将Querystring转换为RouteValue

不提交表单,您可以将/Captains/Index/与下拉框的选定值连接起来,并使用window.location.href重定向到url,如下所示

$('#FilterList').on('change', function () {
    window.location.href = '/Captains/Index/' + $(this).val();
});

我想你是在寻找表单提交的错误路由行为。你希望看到的路由解析类型实际上只发生在服务器端,其中MVC路由知道所有可用的路由定义。但是在浏览器中发生的表单提交过程只知道表单输入及其值。它不知道"Name"是一个特殊的路由参数…它只是将所有表单值附加为querystring参数。

所以如果你想把浏览器发送到/Index/ChosenValue,但你不想在客户端从头开始构造URL,你需要在视图呈现时在服务器上构造URL。您可以采用以下方法:

<div class="row">
    <div class="dropdown">
        @Html.DropDownList("Name", new SelectList(Model.SomeProperty), 
            new { 
                id = "FilterList", 
                data_redirect_url = @Url.Action("Index", "Captains", new { Name = "DUMMY_PLACEHOLDER" }) 
            })    
    </div>
</div>

上面你用一个虚拟的"Name"值设置URL,你可以稍后替换,然后你将用选择和重定向在javascript中做替换:

$('#FilterList').on('change', function () {
    var redirectUrl = $(this).data('redirect-url');
    window.location.href =  redirectUrl.replace("DUMMY_PLACEHOLDER", $(this).val());
});

如果你想从url中删除查询字符串,因为它看起来很奇怪,那么改变你的FormMethod.Post

然而,为了真正回答你的问题,我已经成功地尝试了以下方法(注意:这可能被一些人认为是一个hack)

简而言之:当列表更改时,更新表单元素上的操作url,客户端。

$('#FilterList').on('change', function () {
   var form = $(this).parents('form');
   var originalActionUrl = form.attr("action");
   var newActionUrl = originalActionUrl  + "/" + $(this).val();
   form.attr("action", newActionUrl);
   console.log(form.attr("action"));    
   form.submit();
});

你需要修改你的控制器的签名来匹配你在路由配置中指定的任何可选参数值。在您的示例中,"Name"。