在ASP.NET MVC中实现简单的产品下拉列表

时间:2009-01-23 06:31:09

标签: asp.net-mvc

我可以在ASP.NET MVC中实现简单产品下拉列表的不同或最佳方法是什么,当用户从下拉列表中选择时,会将用户重定向到新产品?

我目前有主要的映射规则:

 routes.MapRoute(
              "Product",
              "Products/{sku}",
              new { controller = "Products", action = "ViewProduct", sku = "1001" }
           );

这允许我输入这样的网址来查看我的产品:

/Products/1002

我的页面上有一个下拉列表,代表产品列表,并允许您从列表中选择。 (sku参数与控制器的ViewProduct方法中的参数名称相同:

<% using (Html.BeginForm("ViewProduct", "Products"))
   { %>

    <%= Html.DropDownList("sku", ViewData.Model.ProductsList)%>
    <%= Html.SubmitButton() %>  <!-- just using a button now since its easier -->

<% } %>

此表单的目标是我在控制器中的“ViewProduct”命令(这是一个呈现产品信息页面的完整视图)。

问题是生成的HTML(当我查看/Products/1002的HTML时)看起来像这样:

<form action="/Products/1002" method="post">

    <select id="sku" name="sku">
        <option value="1003">Product 1003</option>
        <option value="1002">Product 1002</option>
        <option value="2001">Product 2001</option>
    </select>

<input type="submit" />
</form>

它已经基于当前 URL创建了动作链接(我猜它真的没有选择)。问题是当我点击“提交”后调用我的控制器时,它就会继续并再次获取产品1002 - 并且不会被表单中的'sku'参数覆盖。

现在,实际值在Request.Params["sku"]中可用,但显然是一个非常糟糕的做法,试图从那里获得它。

一个非常复杂的解决方案如下 - 创建一个不同的路由规则,该规则命中不同的控制器方法RedirectProduct

routes.MapRoute(
           "Product Redirect",
           "Products/RedirectProduct",
           new { controller = "Products", action = "RedirectProduct" }
        );

然后对我的表单的操作可以简单地是:

<% using (Html.BeginForm("RedirectProduct", "Products")) { %>

这会触及我的控制器方法,该方法可以访问'sku'(我想要的正确形式来自表格参数)。控制器方法只是重定向到/ Products / XXX。

public ActionResult RedirectProduct(string sku)
        {
            return new RedirectResult("/Products/" + sku);
        }

我根本不喜欢这个解决方案 - 但我想至少展示我到目前为止的所有内容。我不喜欢像这样添加额外的映射规则,并且当我真的只有一个时必须创建不同的动作名称。

我确信我有50种不同的方法可以做到这一点 - 因此我在stackoverflow上提出问题 - 试图找出最好的方法。不幸的是,此时我发现的MVC表单处理文档非常简单。

PS。我不是主要寻找JQuery解决方案(我想首先掌握'纯MVC'),但我欢迎一个。

3 个答案:

答案 0 :(得分:1)

问题出现是因为你的路线都使用{sku}而你的表格字段叫做sku。路线中的{sku}取代了sku表格字段(看起来似乎)。一个(相当实用的)解决方案可能是以不同的方式命名它们,因此您的控制器操作将类似于:

public void ActionResult ViewProduct(string routeSku, string sku)
{
    sku = sku ?? routeSku;
    // same as before
}

这会导致初始get请求中的“sku”参数为“null”(routeSku将是URL中的任何内容),当使用提交按钮时,routeSku将是相同的,因为您要回发到相同的URL但sku将是表单值。然后逻辑将从表单中选择sku值(如果已设置)。

答案 1 :(得分:0)

我认为JavaScript是您唯一的选择。表单标记只能提交到一个URL,所以如果你想避免RedirectProduct路由(我会同意,这很尴尬),你将不得不做javascript。这样的事情(使用jQuery)可能会起到作用:

<script type="text/javascript">
function doredirect() {
    window.location="http://www.mysite.com/Products/" + $('#sku').val
}
</script>
<% using (Html.BeginForm("ViewProduct", "Products"))
   { %>

    <%= Html.DropDownList("sku", ViewData.Model.ProductsList, new { onchange="doredirect" })%>
    <%-- Won't need this anymore: 'Html.SubmitButton()' --%>

<% } %>

(免责声明:我还没有完全测试过,但如果你遇到问题,我会尽力帮助你回答这个问题)

不幸的是,您失去了路由的好处,因为URL是在客户端上生成的。如果更改路线,则必须手动更新此代码。一种可能的解决方案是稍微欺骗路由系统并在服务器上生成“模板”URL,以传递给您的客户端代码。像这样:

<script type="text/javascript">
var urlTemplate = <%= Url.Action("ViewProduct", "Products", new { sku="__sku__" }) %>
function doredirect() {
    window.location= urlTemplate.replace(/__sku__/,$('#sku').val)
}
</script>

(与上述相同的免责声明:P)

服务器端代码应该生成如下的网址:http://mysite.com/Products/__sku__,然后javascript会将__sku__令牌替换为实际的SKU。

答案 2 :(得分:0)

他们为RC1解决了这个问题!他们正式将其归类为虫子。很酷(我想!)

•当表单发布到具有与路由参数匹配的参数名称的操作方法时,表单值现在会覆盖route参数。这解决了以下问题:尝试发布名为id的表单字段的表单不起作用,因为默认路由具有id参数。