简体   繁体   中英

ASP.NET MVC query with optional field and value

What I'm trying to do is provide a generic search capability on a table. So the user is presented with all data in a table, they enter some text to filter on, and voila, the table is now filtered on all results that match that entry.

I have this working with a single field:

public ActionResult Index(string user_name)
{

    var dataContext = new PurchaseOrderDataContext();

    var orders = from o in dataContext.purchase_orders
                 where o.approved_by.display_name.StartsWith(user_name ?? "")
                 select o;

    if (Request.IsAjaxRequest())
    {
        return PartialView("list", orders);
    }
    else
    {
        return View(orders);
    }
}

But what I'm looking for is the ability for them to have a dropdown that allows them to pass in the field that they want to filter on. It would like something like this:

public ActionResult Index(string field, string query_value)
{

    var dataContext = new PurchaseOrderDataContext();

    var orders = from o in dataContext.purchase_orders
                 where o["field"].StartsWith(query_value ?? "")
                 select o;

    if (Request.IsAjaxRequest())
    {
        return PartialView("list", orders);
    }
    else
    {
        return View(orders);
    }
}

...Except that the o["field"] is just my silly guess at syntax (which doesn't work).

I guess I'm just confused because although I'm using this nice class-ified data model, I sometimes want to explicitly refer to the columns by name.

How would I go about doing this?

My apologies if this is obvious...

Edit: I think I'm going to leave this open for now to see if there's a neater, less hack-ish feeling solution than suggested below. Thanks!

The only simple (depends on your definition of "simple" I guess) way to do this would be to use the Dynamic Linq API. See here:

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

The way I would do this is with a switch statement:

var orders = dataContext.purchase_orders;

if(!string.IsNullOrEmpty(query_value))
{
    switch(field)
    {
        case "firstname":
            orders = orders.Where(x => x.FirstName.StartsWith(query_value));
            return;
        case "company":
            orders = orders.Where(x => x.Company.StartsWith(query_value));
            return;
        // etc.
    }
}

This also allows you to validate field .

The main reason why you can't just put in the field name as the property name of your class is because Linq builds an expression tree.

Now what you can do is split up how you're building your expression tree by doing.

var orders = from o in dataContext.purchase_orders
                 select o;

if (!string.IsNullOrEmpty(user_name)) {
     orders = orders.Where(x => x.StartsWith(user_name);
}

And just add more if statements.... ugh... Yeah it's definitely not pretty, and someone can probably make it look a lot better by making a IDictionary<string, Func<Expression, string>> instead of a bunch of if statements, but it still feels like a hack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM