Подтвердить что ты не робот

Передача нескольких параметров контроллеру в 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
  • Фильтровать определенные заголовки (техник, клиент, категория, приоритет, статус) -

Я не могу понять, как передать два параметра контроллеру, чтобы я мог организовать свои запросы. Я также понял, что, если я не выясню, как создавать запросы на лету, мне понадобится (количество опций сортировки) * (количество параметров фильтра) в моем коммутаторе.

Арк, может ли кто-нибудь указать мне в правильном направлении? Ура!
4b9b3361

Ответ 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.