ASP.NET MVC + WebForms - конфликт маршрутов - PullRequest
6 голосов
/ 01 марта 2012

Я создаю простое веб-приложение для отчетов для рендеринга отчетов с использованием ASP.NET MVC3 + WebForms.Сами отчеты представляются элементом управления ReportViewer ASP.NET WebForms, но я бы хотел использовать ASP.NET MVC для создания записи параметра.

Я бы хотел, чтобы все запросы следовали схеме маршрутизации по умолчанию '~ / {controller} / {action} / {parameters}', кроме запросов для ~/Report, которые должны идти в отчетрендеринг WebForm.Какой правильный способ сделать это?

Немного расширив ..

У меня есть два маршрута в Global.asax.cs - один и один по умолчанию для страницы веб-форм.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

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

    routes.MapPageRoute("report-rendering", "Report", "~/Render.aspx");
}

URL-адреса обрабатываются нормально, но проблема в том, что при поступлении запроса первый маршрут также съедает URL-адреса второго, т. Е. ~/Report?id=7 пытается вызвать метод Index в * 1014.* (которого не существует).

Если я изменю его так, чтобы маршрут «рендеринга отчета» предшествовал маршруту «По умолчанию», например:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapPageRoute("report-rendering", "Report", "~/Render.aspx");

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

Теперь вызовы Html.ActionLink () отображаются неверноURL, то есть

`@Html.ActionLink("Report list", "Index", "ReportList")`

Рендеринг

`http://localhost:49910/Report?action=Index&controller=ReportList`

Мой текущий обходной путь ставит маршрут «По умолчанию» первым, добавляя ограничение регулярного выражения для игнорирования запросов к контроллеру «Отчет», например, так:

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
    new { controller = @"(?!report$).*" }
);

Это не кажется чистым.Опять же, как правильно это сделать?

Кроме того, я еще не решил, как передать параметры в форму рендеринга: я мог бы использовать оба параметра запроса или POST их.Я предполагаю, что параметры запроса более гибкие.Какая лучшая практика здесь?

РЕДАКТИРОВАТЬ:

При поиске ответа @LeftyX, кажется, я нашел ответ.Цитируя П. Хаака из его главы «Маршрутизация» в Professional ASP.NET MVC 3 (Именованные маршруты, глава 9, стр. 233):

... Использованиеимена для всех ваших маршрутов и всегда используйте имя маршрута при генерации URL .Большую часть времени, позволяя Routing разобраться, какой маршрут вы хотите использовать для генерации URL, на самом деле оставляете его на волю случая, что не совсем подходит для одержимо-навязчивого разработчика, увлекающегося управлением.При создании URL вы, как правило, точно знаете, на какой маршрут хотите ссылаться, поэтому вы также можете указать его по имени.

В упомянутом разделе обсуждается ситуация, очень похожая на описанную мной.

Но поскольку Html.ActionLink() не перегружен параметром имени маршрута, означает ли это, что я не могу надежно использовать его где-либо во всем приложении, если есть такой маршрут?

1 Ответ

1 голос
/ 01 марта 2012

Это лучшее решение, которое я нашел.
Я зарегистрировал свой маршрут с помощью MapPageRoute (. Я поместил страницу своего отчета в папку с отчетами )

.
public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapPageRoute(
          "report-rendering",
          "Report/{id}",
          "~/Reports/Report.aspx"
         );

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

Я создал свою ссылку, используя RouteLink, чтобы вы могли указать используемый маршрут:

@Html.RouteLink("Report list", "report-rendering", new { id = 7 })

и я могу получить id на своей странице WebForm следующим образом:

protected void Page_Load(object sender, EventArgs e)
{
    var id = Page.RouteData.Values["id"] as string;
}

Надеюсь, это поможет.

UPDATE

Я создал метод расширения, чтобы сделать вашу жизнь проще:

public static class ExtensionMethods
{
    public static MvcHtmlString WebFormActionLink(this HtmlHelper htmlHelper, string linkText, string ruoteName, object routeValues)
    {
        var helper = new UrlHelper(htmlHelper.ViewContext.RequestContext);

        var anchor = new TagBuilder("a");
        anchor.Attributes["href"] = helper.RouteUrl(routeName, routeValues);
        anchor.SetInnerText(linkText);
        return MvcHtmlString.Create(anchor.ToString());
    }
}

Лучше всего было бы использовать ActionLink вместо WebFormActionLink , но у меня проблемы с подписями, и я не являюсь экспертом в этом.

...