#asp.net-mvc-3
#asp.net-mvc-3
Вопрос:
Я создаю URL, используя метод:
Url.Action("action", "controller");
Мне также нравится передавать строку запроса для текущего запроса в этот url.
Что-то вроде следующего (но это не работает):
Url.Action("action", "controller", Request.QueryString);
Преобразование строки запроса в routevalues возможно со следующим расширением:
public static RouteValueDictionary ToRouteValues(this NameValueCollection queryString)
{
if (queryString.IsNull() || queryString.HasKeys() == false) return new RouteValueDictionary();
var routeValues = new RouteValueDictionary();
foreach (string key in queryString.AllKeys)
routeValues.Add(key, queryString[key]);
return routeValues;
}
С методом расширения работает следующее:
Url.Action("action", "controller", Request.QueryString.ToRouteValues());
Есть ли другой лучший способ?
Спасибо
Комментарии:
1. Это вызовет исключение, если строка запроса содержит два ключа / значения с одним и тем же ключом, что всегда возможно, поскольку кто-то может изменять строки запроса в своем браузере
2. Спасибо, этот вопрос — действительно полезный ответ! Что
querystring.IsNull()
однако? Это пользовательское расширение? Потому что я нигде этого не вижу.
Ответ №1:
Если вы хотите легко иметь возможность добавлять дополнительные параметры значения маршрута к вашему Url.Action, попробуйте этот метод расширения (основанный на переводе строки), который принимает анонимный объект и возвращает RouteValueCollection:
public static RouteValueDictionary ToRouteValues(this NameValueCollection col, Object obj)
{
var values = new RouteValueDictionary(obj);
if (col != null)
{
foreach (string key in col)
{
//values passed in object override those already in collection
if (key != null amp;amp; !values.ContainsKey(key)) values[key] = col[key];
}
}
return values;
}
Затем вы можете использовать это следующим образом:
Url.Action("action", "controller", Request.QueryString.ToRouteValues(new{ id=0 }));
Комментарии:
1. Первую строку можно сократить до просто
var values = new RouteValueDictionary(obj);
. ПосколькуRouteValueDictionary(object)
принимает nulls (создает экземпляр пустого словаря), троичный не является необходимым.2. Вы также можете сделать
obj
параметр необязательным вот так:ToRouteValues(this NameValueCollection col, Object obj = null)
. Тогда, если вы хотите отправить только querystring в качестве данных маршрута, вы можете использоватьToRouteValues()
без параметров.
Ответ №2:
Метод расширения кажется правильным, и это правильный путь.
Ответ №3:
Вот мое решение, основанное на ответе pwhe23. Я хотел сохранить параметры строки запроса через запросы POST (из-за Mvc.Grid) и использовать только одно действие для HTTP GET. Действия CRUD обрабатываются одной страницей и модальными диалогами внутри (для вставки / обновления / удаления).
Итак, вот мое расширение:
public static class MvcExtensions
{
public static RouteValueDictionary ToRouteValues(this NameValueCollection col, Object obj = null)
{
var values = obj != null ? new RouteValueDictionary(obj) : new RouteValueDictionary();
if (col == null) return values;
foreach (string key in col)
{
//values passed in object are already in collection
if (!values.ContainsKey(key)) values[key] = col[key];
}
return values;
}
}
Использование в контроллере (например, действие редактирования):
[HttpPost]
public ActionResult Edit(MyModel model)
{
// Some stuff
return RedirectToAction("Index", Request.QueryString.ToRouteValues());
}
Форма для редактирования, созданная в представлении (используется модальный диалог):
@using (Html.BeginForm("Edit", "SomeControllerName", Request.QueryString.ToRouteValues(), FormMethod.Post))
{
// Some stuff... e.g. dialog content
}