我可以在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'),但我欢迎一个。
答案 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参数。