Почему эта форма не вызывает моего действия контроллера в ASP.NET MVC? - PullRequest
2 голосов
/ 12 апреля 2009

Я пытаюсь создать клон TinyURL в ASP.NET MVC в качестве учебного проекта.

Прямо сейчас все, что я хочу, - это возможность отправлять новые URL-адреса на мой / Home / Create action через форму.

alt text

У меня все выражение LINQ полностью настроено, у меня настроена маршрутизация, и у меня настроено представление, но что-то не так с моими настройками.

Маршрутизация:

 routes.MapRoute(
            "Default",                                              // Route name
            "",                           // URL with parameters
            new { controller = "Home", action = "Index" }  // Parameter defaults
        );

 routes.MapRoute(
            "Redirect",
            "{hash}",
            new { controller = "Home", action = "RequestLink", hash = "" }
        );

Эти маршруты позволяют мне перейти на мой веб-сайт www.tinyurlclone.com/ и, если ничего не будет пройдено, я просто перейду к моему действию Home / Index (). Однако, если вы поставите что-нибудь после косой черты, он будет считать, что это хеш-ссылка, и попытается получить хеш.

Мой HomeController выглядит следующим образом:

[HandleError]  
public class HomeController : Controller  
{  
    TinyGetRepository repo = new TinyGetRepository();

    public ActionResult Index()
    {
        return View();
    }


    public ActionResult Create(String url)
    {
        String hash = repo.addLink(url);
        ViewData["LinkHash"] = hash;
        return View();
    }

    public ActionResult RequestLink(String hash)
    {
        String url = repo.getLink(hash);
        return Redirect(url);

    }
}

В моем классе репо есть все мои выражения LINQ для работы с базой данных, и мне не нужно их включать, потому что он не имеет отношения к этому вопросу.

Наконец, мое основное представление Home / Index () (используется для отправки URL) выглядит следующим образом:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
    <center>
            <span style="font-size: 14pt">TinyGet <em>(beta)</em></span><br />
            <span style="font-family: Tahoma">Reduce your long links to smaller ones to keep them more memorable....<br />
            </span>
            <% using(Html.BeginForm("Create", "Home")) %>
            <% { %>
            <%= Html.TextBox("url") %>
            <input type="submit" name="submitButton" value="Shorten Link!" />
            <% } %>

      </center>
    </div>
</body>
</html>

Однако моя форма просто не запускает никаких методов, когда я нажимаю на кнопку отправить.

Кроме того, если я просматриваю источник моего сгенерированного HTML, я вижу, что он не выполнил действие моей Формы правильно, он читает:

<form action="" method="post"><input id="url" name="url" type="text" value="" />
            <input type="submit" name="submitButton" value="Shorten Link!" />
            </form>

Почему помощник HTML ставит "" в качестве действия, когда он должен ~ помещать / Home / Create? Почему не вызывается метод действия my / Home / Create? Даже если я не использую Html-помощники и указываю тег <form> вручную, он выдает ошибки.

Что здесь не так?

Источник для проекта: здесь

Ответы [ 2 ]

3 голосов
/ 12 апреля 2009

Проблема в том, что у вас нет маршрута, который соответствует значениям маршрута (контроллер = Дом, действие = Создать).

У вас есть два маршрута, один - пустая строка (без параметров), которая соответствует Controller = "Home", Action = "Index". Другой - ваш хеш-маршрут, который соответствует Controller = "Home", Action = "RequestLink". Таким образом, когда ASP.Net Routing отправляется для создания URL-адреса из предоставленных вами значений маршрута, он не может найти ни одного (поскольку ни один из них не имеет параметров "{controller}" и "{action}").

Самым простым решением в этом случае является создание прямого маршрута к действию «Создать», чтобы вы все еще могли использовать свой маршрут «хеш». Поместите это в верхней части вашего метода RegisterRoutes. ПРИМЕЧАНИЕ: заказ имеет значение ! ASP.Net Routing проверяет каждый маршрут в добавленном порядке, пока не найдет совпадение.

routes.MapRoute(
        "Create",                                              // Route name
        "Create",                           // URL with parameters
        new { controller = "Home", action = "Create" }  // Parameter defaults
    );

Поскольку у вас есть этот маршрут «хеш», вы не можете использовать метод «{controller} / {action} / {id}» по умолчанию, поскольку значение «hash» будет считаться допустимым именем контроллера. Поэтому, если кто-то запросит: http://www.mysite.com/fjhas82, MVC будет искать контроллер с именем "fjhas82" и жаловаться, что не может его найти. К сожалению, это означает, что вы должны вручную добавлять новые маршруты для каждого нового действия контроллера (как я показал выше), что является проблемой.

Лучшее решение (на мой взгляд) состоит в использовании ограничений Regex: если ваши хеши имеют очень четко определенный формат (скажем, 5 букв, за которыми следуют 2 цифры, или «_», за которыми следуют любые буквенно-цифровые символы и т. Д.) .) или, если вы хотите навязать такой формат, вы можете использовать ограничения Regex, поддерживаемые маршрутизацией ASP.Net. Тогда вам понадобятся только эти два маршрута

routes.MapRoute(
        "Redirect",
        "{hash}",
        new { controller = "Home", action = "RequestLink" },
        new { hash = @"[a-zA-Z]{5}[0-9]{2}" } // Regex Constraints
    );

routes.MapRoute(
    "Default",                                              // Route name
    "{controller}/{action}/{id}",                           // URL with parameters
    new { controller = "Home", action = "Index" }  // Parameter defaults
);    

По этим маршрутам, если MVC видит имя контроллера, например: «Home», он проверит первый маршрут, обнаружит, что он не соответствует регулярному выражению, и перейдет к следующему. ПРИМЕЧАНИЕ: мой синтаксис регулярных выражений может быть немного ржавым, поэтому я бы использовал что-то вроде http://regexpal.com/, чтобы сначала протестировать Regex, чтобы убедиться, что он работает с вашими хэшами и именами контроллеров.

Надеюсь, это поможет, я знаю, что много писал, но MVC настолько гибок, что вы можете делать разные вещи!

0 голосов
/ 12 апреля 2009

У меня была похожая проблема из того, что я узнал, что маршрут идет по последнему маршруту

Таким образом, вместо него используется ваш хэш-маршрут, поэтому он помещает ""

В принципе, вы могли бы избавиться от этого хеш-маршрута и просто получить этот

 routes.MapRoute(            "Default",                                              // Route name            "{controller}/{action}/{hash}",                           // URL with parameters            new { controller = "Home", action = "Index", hash="" }  // Parameter defaults        );

Это могло бы выполнить то же самое, и когда хеш не предоставлен, это не имело бы значения

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