Реализация простого раскрывающегося списка продуктов в ASP.NET MVC - PullRequest
1 голос
/ 23 января 2009

Какими различными или лучшими способами я могу реализовать простой раскрывающийся список продуктов в ASP.NET MVC, который перенаправляет пользователя на новый продукт, когда они выбирают из раскрывающегося списка?

В настоящее время у меня есть основное правило сопоставления:

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

Это позволяет мне ввести URL-адрес, подобный этому, чтобы просмотреть мой продукт:

/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-код (при просмотре HTML-кода для /Products/1002) выглядит следующим образом:

<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 ]

1 голос
/ 23 января 2009

Проблема возникает потому, что и ваш Маршрут использует {sku}, а поле формы называется sku. {Sku} из маршрута заменяет поле формы sku (казалось бы). (Довольно прагматичное) решение может заключаться в том, чтобы они назывались по-разному, поэтому действие вашего контроллера будет выглядеть примерно так:

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

Это приведет к тому, что параметр "sku" будет нулевым в начальном запросе get (routeSku будет тем, что есть в URL), при использовании кнопки отправки routeSku будет таким же, так как вы отправляете обратно в тот же URL, но sku будет значением формы. Затем логика выберет значение sku из формы, если оно было установлено.

0 голосов
/ 28 января 2009

Они исправили это для RC1! Они официально классифицировали это как ошибку. Круто (думаю!)

• Когда форма отправляет сообщение методу действия, имя которого соответствует параметру маршрута, значение формы теперь переопределяет параметр маршрута. Это устраняет проблему, из-за которой форма, которая пыталась опубликовать поле формы с именем id, не работала, поскольку маршрут по умолчанию имеет параметр id.

0 голосов
/ 23 января 2009

Я думаю, что 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)

Код на стороне сервера должен сгенерировать URL-адрес, например: http://mysite.com/Products/__sku__, затем JavaScript заменяет маркер __sku__ на действительный SKU.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...