Передача нескольких параметров контроллеру в ASP.NET MVC; также генерировать запросы "на лету" в LINQ-to-SQL
Я работаю над базовой системой управления проблемами, чтобы изучить ASP.NET MVC. Я получил это и работал на довольно приличном уровне, но у меня возникла проблема.
У меня есть контроллер с именем Issue с представлением Open./Issue/Open перечисляет все открытые проблемы, которые в настоящее время регистрируются в системе. Я определил такой маршрут:
routes.MapRoute(
"OpenSort", // Route name
"Issue/Open/{sort}", // URL with parameters
new { controller = "Issue", action = "Open", sort = "TimeLogged" } // Parameter defaults
);
Пока это работает, используя следующий код в IssueController.cs:
public ActionResult Open(string sort)
{
var Issues = from i in db.Issues where i.Status == "Open" orderby i.TimeLogged ascending select i;
switch (sort)
{
case "ID":
Issues = from i in db.Issues where i.Status == "Open" orderby i.ID ascending select i;
break;
case "TimeLogged":
goto default;
case "Technician":
Issues = from i in db.Issues where i.Status == "Open" orderby i.Technician ascending select i;
break;
case "Customer":
Issues = from i in db.Issues where i.Status == "Open" orderby i.Customer ascending select i;
break;
case "Category":
Issues = from i in db.Issues where i.Status == "Open" orderby i.Category ascending select i;
break;
case "Priority":
Issues = from i in db.Issues where i.Status == "Open" orderby i.Priority ascending select i;
break;
case "Status":
Issues = from i in db.Issues where i.Status == "Open" orderby i.Status ascending select i;
break;
default:
break;
}
ViewData["Title"] = "Open Issues";
ViewData["SortID"] = sort.ToString();
return View(Issues.ToList());
}
Это прекрасно работает (хотя, интересно, есть ли лучший способ обработать мое определение запроса, чем переключатель?), но теперь я хочу иметь возможность сделать две вещи в представлении "Открытые проблемы":
- Сортировка по любому из заголовков - OK
- Фильтровать определенные заголовки (техник, клиент, категория, приоритет, статус) -
Я не могу понять, как передать два параметра контроллеру, чтобы я мог организовать свои запросы. Я также понял, что, если я не выясню, как создавать запросы на лету, мне понадобится (количество опций сортировки) * (количество параметров фильтра) в моем коммутаторе.
Арк, может ли кто-нибудь указать мне в правильном направлении? Ура!
Ответы
Ответ 1
- Удалить сортировку с маршрута. Просто используйте маршрут без параметра.
- Добавьте параметры строки запроса в запрос сортировки, фильтра и т.д. Таким образом, ваш запрос будет выглядеть так:
http://example.com/Issue/Open?sort=ID&filter=foo
public ActionResult Open(string sort, string filter)
Структура MVC будет заполнять аргументы из параметров строки запроса. Удостоверьтесь и используйте типы с нулевым значением (например, string) для любого из этих параметров параметров строки запроса, которые могут быть не заполнены.
Я действительно думаю, что это "более правильный" способ написать URL. Сам URL идентифицирует ресурс (открытые проблемы); параметры строки запроса настраивают способ отображения ресурса.
Что касается количества запросов, помните, что вам не нужно сразу создавать весь запрос. Вы можете использовать метод расширения .OrderBy для переопределения существующего IQueryable <T> , и аналогично с .Where.
var Issues = from i in db.Issues where i.Status == "Open" select i;
switch (sort)
{
case "ID":
Issues = Issues.OrderBy(i => i.ID);
break;
// [...]
default:
Issues = Issues.OrderBy(i => i.TimeLogged);
}
Ответ 2
Если вы ожидаете произвольного количества параметров, вы можете сделать что-то вроде этого.
public ActionResult Open(){
string[] keys = Request.QueryString.AllKeys;
Dictionary queryParams = new Dictionary();
foreach (string key in keys)
{
queryParams[key] = Request.QueryString[key];
}
string sort = queryParams["sort"];
...
Ответ 3
Это должен быть комментарий для ответа kimsks, но по какой-то причине комментирование требует, чтобы меня проверяли, поэтому я должен опубликовать его в неправильном месте.
Лучший способ обработки произвольного количества параметров строки запроса - использовать ActionFilter
так:
public class QueryStringFilterAttribute : ActionFilterAttribute
{
public string ParameterName { get; private set; }
public QueryStringFilterAttribute(string parameterName)
{
if(string.IsNullOrEmpty(parameterName))
throw new ArgumentException("ParameterName is required.");
ParameterName = parameterName;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var qs = new FormCollection(filterContext.HttpContext.Request.QueryString);
filterContext.ActionParameters[ParameterName] = qs;
base.OnActionExecuting(filterContext);
}
}
Теперь вы можете добавить атрибут к вашему действию так, как [QueryStringFilter("attributes")]
, и он будет передавать значения строки запроса как FormCollection
. Таким образом, ваше действие легче тестируется, поскольку оно больше не зависит от синглета Request
.
Ответ 4
Вместо переключателя вы можете использовать Dynamic Linq, который позволяет вам сказать:
Issues = Issues.OrderBy("Status");
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Ответ 5
Пожалуйста, проверьте сообщение ниже, которое описывает все процессы
http://www.c-sharpcorner.com/UploadFile/4b0136/editing-multiple-records-using-model-binding-in-mvc/