ASP.Net MVC Хранение параметров действий между постбэками - PullRequest
8 голосов
/ 23 сентября 2008

Скажем, у меня есть страница, которая отображает результаты поиска. Я ищу stackoverflow, и он возвращает 5000 результатов, 10 на страницу. Теперь я делаю это при создании ссылок на этой странице:

<%=Html.ActionLink("Page 1", "Search", new { query=ViewData["query"], page etc..%>
<%=Html.ActionLink("Page 2", "Search", new { query=ViewData["query"], page etc..%>
<%=Html.ActionLink("Page 3", "Search", new { query=ViewData["query"], page etc..%>
<%=Html.ActionLink("Next", "Search", new { query=ViewData["query"], page etc..%>

Мне это не нравится, я должен строить свои ссылки с тщательным рассмотрением того, что было опубликовано ранее и т. Д.

То, что я хотел бы сделать, это

<%=Html.BuildActionLinkUsingCurrentActionPostData
        ("Next", "Search", new { Page = 1});

где анонимный словарь переопределяет все, что в данный момент установлено предыдущим действием.

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

Я, наверное, упускаю что-то очевидное

Ответы [ 8 ]

12 голосов
/ 04 августа 2009

У меня была похожая проблема внутри HtmlHelper; Я хотел генерировать ссылки, которые ссылались на текущую страницу, с небольшой настройкой параметров (подумайте об увеличении номера страницы). Поэтому, если бы у меня был URL / Item /? Sort = Name & page = 0, я хотел бы иметь возможность создавать ссылки на ту же страницу, но просто изменить параметр страницы и автоматически включить параметр сортировки (т. Е. / Item /? Sort = Имя и страница = 1).

Мое решение заключалось в следующем (для использования в методе расширения HtmlHelper, но, поскольку вы можете получить доступ к одним и тем же данным практически в любом месте MVC, вы можете легко адаптировать их для своих целей):

private static RouteValueDictionary CreateRouteToCurrentPage(HtmlHelper html)
{
    RouteValueDictionary routeValues 
         = new RouteValueDictionary(html.ViewContext.RouteData.Values);

    NameValueCollection queryString 
         = html.ViewContext.HttpContext.Request.QueryString;

    foreach (string key in queryString.Cast<string>())
    {
        routeValues[key] = queryString[key];
    }

    return routeValues;
}

Что метод делает, так это берёт RouteValueDictionary для текущего запроса и создает его копию. Затем он добавляет каждый из параметров запроса, найденных в строке запроса, к этому маршруту. Это происходит потому, что по какой-то причине текущий запрос RouteValueDictionary не содержит их (можно было бы подумать, что это не так).

Затем вы можете взять результирующий словарь, изменить только его часть, например:

routeValues["page"] = 2;

, а затем передайте этот словарь готовым методам HtmlHelper, чтобы они генерировали вам URL / и т. Д.

1 голос
/ 17 октября 2009

Следующий вспомогательный метод делает именно это:

    public static string EnhancedActionLink(this HtmlHelper helper, string linkText, string actionName, string controllerName, bool keepQueryStrings)
    {
        ViewContext context = helper.ViewContext;
        IDictionary<string, object> htmlAttributes = null;
        RouteValueDictionary routeValues = null;
        string actionLink = string.Empty;
        if (keepQueryStrings && context.RequestContext.HttpContext.Request.QueryString.Keys.Count > 0)
        {
            routeValues = new RouteValueDictionary(context.RouteData.Values);
            foreach (string key in context.RequestContext.HttpContext.Request.QueryString.Keys)
            {
                routeValues[key] = context.RequestContext.HttpContext.Request.QueryString[key];
            }
        }            
        actionLink = helper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);
        return actionLink;
    }
1 голос
/ 23 сентября 2008

Я немного сомневаюсь, что вы на самом деле пытаетесь сделать здесь. Я думаю, что вы пытаетесь автоматизировать процесс создания списка ссылок с небольшими изменениями между ними. По-видимому, в вашем случае номер идентификатора «Page».

Один из способов сделать это, хотя, возможно, не самый лучший, таков (мой код использует базовый и надуманный список продуктов, а ViewPage и PartialViewPage используют строго типизированные модели):

На вашей странице просмотра вы бы добавили следующий код:

<div id="product_list">
        <% foreach (TestMVC.Product product in ViewData.Model)
           { %>
            <% Html.RenderPartial("ProductEntry", product); %>
        <% } %>
</div>

Ваш частичный вид, в моем случае «ProductEntry», будет выглядеть следующим образом:

<div class="product">
    <div class="product-name">
        <%= Html.ActionLink(ViewData.Model.ProductName, "Detail", new { id = ViewData.Model.id })%>
    </div> 
    <div class="product-desc">
        <%= ViewData.Model.ProductDescription %>
    </div>       
</div>

Все, что я делаю в этом частичном представлении, использует модель / данные представления, которые были переданы из родительского представления при вызове Html.RenderPartial

В родительском представлении вы можете изменить параметр объекта вашей модели перед вызовом Html.RenderPartial, чтобы задать интересующее вас конкретное значение.

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

1 голос
/ 23 сентября 2008

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

0 голосов
/ 16 июля 2012

Не совсем ответ, но стоит отметить: если вам нужна функциональность подкачки, используйте пакет PagedList Nuget (не нужно заново изобретать колесо). Следующая ссылка предоставляет действительно хороший пример того, как его использовать: ASP.NET Tutorial

Это особенно полезно для вас, потому что строки запросов сохраняются в URL при переключении между страницами.

0 голосов
/ 03 июля 2012

Вот расширение actionlink


  public static class ActionLinkExtension
    {
        public static MvcHtmlString ActionLinkWithQueryString(this HtmlHelper helper, string linkText, string action, string controller, object routeValues)
        {
            var context = helper.ViewContext;

            var currentRouteValues = new RouteValueDictionary(context.RouteData.Values);
            foreach (string key in context.HttpContext.Request.QueryString.Keys)
            {
                currentRouteValues[key] = context.HttpContext.Request.QueryString[key];
            }

            var newRouteValues = new RouteValueDictionary(routeValues);

            foreach (var route in newRouteValues)
            {
                if (!currentRouteValues.ContainsKey(route.Key))
                {
                    currentRouteValues.Add(route.Key, route.Value);
                }
                else
                {
                    currentRouteValues[route.Key] = route.Value;
                }
            }

            return helper.ActionLink(linkText, action, controller, currentRouteValues, null);
        }

    }

0 голосов
/ 14 июня 2011

После нескольких часов, проведенных в разных решениях, у меня сработало только одно: MVC ActionLink добавляет все (необязательные) параметры из текущего URL

0 голосов
/ 03 декабря 2010

посмотрите на это, это хороший пример: http://nerddinnerbook.s3.amazonaws.com/Part8.htm

...