Vallabha
Vallabha

Reputation: 1621

Calling controller Action method using lambda expressions

I am trying to call a controller action method inside the lambda expression like below.

Here dtImporteddata is my DataTable

public class DepartmentController : Controller
{
      public ActionResult Create(FormCollection collection, int ParentDepartmentID)
    {
       return view();
    }
}


   dtImporteddata.Rows.Cast<DataRow>().Select(r => new DepartmentController().Create(new FormCollection{ 
                {"ParentDepartmentID","57"},
                {"DepartmentPrefix",r["Prefix"].ToString()},
                {"DepartmentID","0"},
                {"IsSpecialDepartment",null},
                {"Description",r["Description"].ToString()},
                {"Name",r["Name"].ToString()},
                {"LocationIDs.$.PackedValue","4;;;"}
             }, 0)).ToList();

if i write like above the Create() method is getting called perfectly but if i remove ToList() then the Create() is not getting called.

Upvotes: 2

Views: 838

Answers (3)

elolos
elolos

Reputation: 4450

I would suggest abstracting the create functionality in a reusable component, that both the controller and your lambda can use. For example, you could create a class that has a method with the following signature:

public void CreateDepartment(Department newDepartment)

The Department class could probably expose the same fields as the FormCollection.

You could the use the new method directly in LINQ like so:

dtImporteddata.Rows.Cast<DataRow>().ToList()
              .ForEach(r => CreateDepartment(
                                new Department {
                                                   Name = r.Name,
                                                   ....//rest of the properties
                                                }));

In this way, you would also be able to call the same method within the Create action.

Upvotes: 2

awj
awj

Reputation: 7959

LINQ methods can be split into two camps: those which always return a result (eg, FirstOrDefault) and those which project a different form of what's being given to them. You can think of these projection methods as performing filtering operations.

See what is a projection in LINQ, as in .Select()

Anyway, to answer your question, LINQ doesn't always perform the operation that you might think it's performing. In many cases LINQ uses subsequent operations to add filtering (or modify the projection) and only when you resolve the method call to a result are the calls executed.

I suspect that this is the case here. Without the ToList call you're only building the set of instructions, and only when you call ToList are these instructions resolved to a result.

If you're not actually bothered about the functionality offered by a List<DataRow> and you simply want an enumerable result, consider using ToArray as it has less overhead than ToList.

Upvotes: 2

Patrick Hofman
Patrick Hofman

Reputation: 157118

The problem is that the Select method actually doesn't do that much. It starts doing something when you iterate over its result.

That said, the ToList method does iterate over the iterator returned from Select, hence it executes your lambda expression.

I guess you want to pick up the result and do something with it, if so, assign it to a variable and iterate over it:

foreach(var row in dtImporteddata.Rows.Cast<DataRow>().Select(...))
{
    // do something with row
}

Upvotes: 2

Related Questions