在ASP中传递多个参数给控制器。净MVC;此外,在LINQ-to-SQL中动态生成查询

时间:2022-01-03 15:49:00

I'm working on a basic Issue Management System in order to learn ASP.NET MVC. I've gotten it up and running to a fairly decent level but I've run into a problem.

为了学习ASP,我正在研究一个基本的问题管理系统。净MVC。我已经准备好了并且运行到一个相当不错的水平,但是我遇到了一个问题。

I have a controller named Issue with a view called Open. /Issue/Open lists all of the open issues currently logged on the system. I've defined a route like so:

我有一个名为Issue的控制器,视图名为Open。/Issue/Open列出当前登录到系统的所有开放问题。我这样定义一条路线:

    routes.MapRoute( 
        "OpenSort",                                                         // Route name
        "Issue/Open/{sort}",                                                // URL with parameters
        new { controller = "Issue", action = "Open", sort = "TimeLogged" }  // Parameter defaults
    );

This is working fine so far, using the following code in 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());
}

This is working fine (although, I wonder if there is a better way to handle my definition of the query than a switch?) but now I want to be able to do two things on the Open Issues view:

这工作得很好(尽管我想知道是否有更好的方法来处理我的查询定义,而不是切换?)

  1. Sort by any of the headings - OK
  2. 按任何标题排序-好的
  3. Filter on certain headings (Technician, Customer, Category, Priority, Status) - ??
  4. 过滤某些标题(技术人员、客户、类别、优先级、状态)- ?

I can't figure out how to pass two parameters to the Controller so I can organise my queries. I've also just realised that unless I figure out how to generate my queries on the fly I am going to need (number of sort options) * (number of filter options) in my switch.

我不知道如何将两个参数传递给控制器,这样我就可以组织我的查询了。我也刚刚意识到,除非我知道如何在我的交换机上生成我的查询,我将需要(排序选项的数量)*(过滤选项的数量)。

Argh, can anyone point me in the right direction? Cheers!

谁能告诉我正确的方向吗?干杯!

5 个解决方案

#1


33  

  1. Remove sort from the route. Just use a route without a parameter.
  2. 从路由中删除排序。只需使用没有参数的路由。
  3. Add query string parameters to the query for the sort, filter, etc. So your query will look like:
  4. 将查询字符串参数添加到排序、筛选器等查询中,因此您的查询将如下所示:

http://example.com/Issue/Open?sort=ID&filter=foo

http://example.com/Issue/Open?sort=ID&filter=foo

public ActionResult Open(string sort, string filter)

The MVC framework will fill in the arguments from the query string parameters. Make sure and use nullable types (like string) for any of these query string parameter arguments which might not be filled in.

MVC框架将填充来自查询字符串参数的参数。确保并使用可空类型(如字符串)来处理这些查询字符串参数,这些参数可能没有被填充。

I actually think this is a "more correct" way to write the URL. The URL itself identifies the resource (open issues); the query string parameters customize how to display the resource.

我认为这是写URL的一种“更正确”的方式。URL本身标识资源(开放问题);查询字符串参数自定义如何显示资源。

As far as the number of queries go, remember that you do not have to build the entire query at once. You can use the .OrderBy extension method to re-order an existing IQueryable<T>, and similarly with .Where.

至于查询的数量,请记住,您不必同时构建整个查询。您可以使用. orderby扩展方法来重新排序现有的IQueryable ,类似于. 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


10  

If you expect arbitary number of parameters, you could do something like this.

如果你期望参数的任意数量,你可以这样做。


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


8  

This should be a comment to kimsks answer, but for some reason commenting requires me to be vetted, so I have to post it in the wrong place.

这应该是对kimsks回答的评论,但是出于某种原因,评论要求我接受审查,所以我必须把它贴在错误的地方。

A better way to handle an arbitrary number of query string parameters is to use an ActionFilter like so:

处理任意数量查询字符串参数的更好方法是使用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);
    }
}

Now you can add the an attribute to your action like so [QueryStringFilter("attributes")] and it will pass in the query string values as a FormCollection. This way your action is more easily tested, as it no longer depends on the Request singleton.

现在,您可以将an属性添加到您的操作中,如so [QueryStringFilter(“attributes”)],它将把查询字符串值作为FormCollection传入。这样,您的操作就更容易测试了,因为它不再依赖于单例请求。

#4


1  

Instead of the switch, you could use Dynamic Linq which lets you say:

你可以使用动态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

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

#5


0  

Please check the post below which describes all the processes http://www.c-sharpcorner.com/UploadFile/4b0136/editing-multiple-records-using-model-binding-in-mvc/

请查看下面描述所有进程的文章http://www.c-sharpcorner .com/uploadfile/4b0136 /编辑-多录-使用-模型-绑定-in-mvc/

#1


33  

  1. Remove sort from the route. Just use a route without a parameter.
  2. 从路由中删除排序。只需使用没有参数的路由。
  3. Add query string parameters to the query for the sort, filter, etc. So your query will look like:
  4. 将查询字符串参数添加到排序、筛选器等查询中,因此您的查询将如下所示:

http://example.com/Issue/Open?sort=ID&filter=foo

http://example.com/Issue/Open?sort=ID&filter=foo

public ActionResult Open(string sort, string filter)

The MVC framework will fill in the arguments from the query string parameters. Make sure and use nullable types (like string) for any of these query string parameter arguments which might not be filled in.

MVC框架将填充来自查询字符串参数的参数。确保并使用可空类型(如字符串)来处理这些查询字符串参数,这些参数可能没有被填充。

I actually think this is a "more correct" way to write the URL. The URL itself identifies the resource (open issues); the query string parameters customize how to display the resource.

我认为这是写URL的一种“更正确”的方式。URL本身标识资源(开放问题);查询字符串参数自定义如何显示资源。

As far as the number of queries go, remember that you do not have to build the entire query at once. You can use the .OrderBy extension method to re-order an existing IQueryable<T>, and similarly with .Where.

至于查询的数量,请记住,您不必同时构建整个查询。您可以使用. orderby扩展方法来重新排序现有的IQueryable ,类似于. 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


10  

If you expect arbitary number of parameters, you could do something like this.

如果你期望参数的任意数量,你可以这样做。


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


8  

This should be a comment to kimsks answer, but for some reason commenting requires me to be vetted, so I have to post it in the wrong place.

这应该是对kimsks回答的评论,但是出于某种原因,评论要求我接受审查,所以我必须把它贴在错误的地方。

A better way to handle an arbitrary number of query string parameters is to use an ActionFilter like so:

处理任意数量查询字符串参数的更好方法是使用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);
    }
}

Now you can add the an attribute to your action like so [QueryStringFilter("attributes")] and it will pass in the query string values as a FormCollection. This way your action is more easily tested, as it no longer depends on the Request singleton.

现在,您可以将an属性添加到您的操作中,如so [QueryStringFilter(“attributes”)],它将把查询字符串值作为FormCollection传入。这样,您的操作就更容易测试了,因为它不再依赖于单例请求。

#4


1  

Instead of the switch, you could use Dynamic Linq which lets you say:

你可以使用动态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

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

#5


0  

Please check the post below which describes all the processes http://www.c-sharpcorner.com/UploadFile/4b0136/editing-multiple-records-using-model-binding-in-mvc/

请查看下面描述所有进程的文章http://www.c-sharpcorner .com/uploadfile/4b0136 /编辑-多录-使用-模型-绑定-in-mvc/