Async/Await with Linq Extensions

We all have read and worked on Async/Await and that too many a times. I might not be describing something highly technical but would like to share my learning.

Today while working on one of my WPF application I encountered a strange, rather an unexpected, issue with async/await and Linq extensions where Async/Await didn’t worked with Linq extensions. Let us  try and understand the whole scenario in detail.

I am having a DataModel class in my Data Layer and by using the below asynchronous method I am  fetching data from database and populating a generic collection. It works on the basis of parameter project provided.

//DataModel.cs
public async Task<List<TClass>> PlotChart(string project)
{
	//Data Logic
}

In my View Model Dashboard.cs I am having another PlotChart  method which makes call to the PlotChart method of  DataModel.cs.  This View Model method applies some business logic and ultimately plots some charts on the dashboard.

//DashboardViewModel.cs 
private async Task PlotChart(MainWindow window, string project)
{
	var data = await _db.PlotChart(project);
	//Business Logic
}

In my Xaml i am using two boolean properties (IsBusyPie & IsBusyLine) to show/hide the progress bar and two string properties (BusyMessagePie & BusyMessageLine) two change the message at run time.

<xctk:BusyIndicator
IsBusy=”{Binding IsBusyPie}”
BusyContent=”{Binding BusyMessagePie}” >
<WrapPanel x:Name=”ProjectPanel”/>
</xctk:BusyIndicator>

<xctk:BusyIndicator
IsBusy=”{Binding IsBusyLine}”
BusyContent=”{Binding BusyMessageLine}” >
<WrapPanel x:Name=”BranchPanel”/>
</xctk:BusyIndicator>

There are three approaches which i tried to get the job done, which are described below and their pros and cons also.

Approach 1

Initially I tried calling my ViewModel PlotChart method in view model’s constructor itself using Array.ForEach linq extension.

//In Constructor of ViewModel
IsBusyPie = IsBusyLine = true;
Array.ForEach(projects, project => 
{
	PlotChart(window,project);	
});
IsBusyPie = IsBusyLine = false;

The issue with this approach was, two calls to the function plotchart was made by the Array.Foreach and the boolean values were assigned false. This made UI stuck and there was no progress bar.

Explanation: In this approach the array made asynchronous call and when it hits the await of PlotChart function, control returns. It does that twice (assuming the array has two values).The parent method comes out of that loop and sets

IsBusyPie = IsBusyLine = false;

And some time after when the result of the awaits is returned and it carries on inside the PlotCharts.

Approach 2

Then I changed my approach and I created another function named PlotChart and made calls to my asynchronous method using await keyword (As I could not use await in constructor i created another function). The issue still not resolved although I used await keyword with the calls.

//New Function
private async Task PlotChart(MainWindow window)
{
	IsBusyPie = IsBusyLine = true;
	Array.ForEach(projects, async project =>
		await PlotChart(window, project));
	IsBusyPie = IsBusyLine = false;
}

ExplanationList<T>.ForEach doesn’t play particularly well with async (neither does LINQ-to-objects, for the same reasons). Possibly the lambda is being seen by the compiler as an async void and the await does nothing.

Approach 3

After failing in the above two approaches i decided to iterate the array and make two conventional calls using foreach. And to my surprise it worked fine. My all progress bars showing properly, my UI is not stuck and my views gets updated simultaneously also.

//New Function 
private async Task PlotChart(MainWindow window)
{
	IsBusyPie = IsBusyLine = true;
	foreach (var project in projects)
	{
		await PlotChart(window, project);
	}
	IsBusyPie = IsBusyLine = false;
}

Explanation: This approach is a mix asynchronous and synchronous process. Here when the loop hits the first asynchronous method it awaits for its result and as soon as it gets the output, it updates the View and makes another asynchronous call to the method.

Conclusion: After working with different approaches, it suggests that you should use the foreach loop and await each call instead of using LINQ-to-objects.

 

Advertisements

How MVC maps HTTP request data to action method parameters and custom .NET objects

Introduction

ASP.NET MVC model binding allows you to map and bind HTTP request data with a model. Model binding makes it easy for you to work with form data because the request data (POST/GET) is automatically transferred into a data model you specify. ASP.NET MVC accomplishes this behind the scenes with the help of Default Binder.

In this article we will dicuss how MVC maps HTTP request data directly into action method parameters and custom .NET objects. We know this all is done by MVC automatically behind the scenes, but how? What’s the mechanism which is doing all this? Lets discuss it in detail with an example.

Lets assume we have a Employee Model like this:

public class Employee
{
public string FirstName { get; set; }
}

We have a form like this.

@using (Html.BeginForm())
{
@Html.TextBoxFor(m=>m.FirstName, new { @class = “form-control” })
@Html.TextBox(“name”, new { @class = “form-control” })
@Html.TextBox(“lastname”, new { @class = “form-control” })
}

And an Action like this:

public ActionResult Index(Employee employee, string name)

Image showing how form looks like:

form

On click of the submit button, we can see in the below watch window how the values are automatically passed to action method.

employee

  • The Employee Model automatically gets populated with value of “FirstName”
  • The string parameter named “name” also gets populated with the value of textbox from our UI
  • By using Request.Form[“lastname”] we can get the value of lastname also.

So, the question is how did we got all these values, even though we didn’t wrote a single line of code for that. So, here is the black magic.

Now before the Index action gets called, there are two important components that do some tricks behind the scenes:

  • ValueProviderDictionary
  • DefaultModelBinder

.The ValueProviderDictionary pulls out the values from the HTTP request and stores them as strings. The fetching itself is done in the following order:

  • Request.Form[“name”], if it exists
  • Else, RouteData.Values[“name”], if it exists
  • Else, Request.QueryString[“name”], if it exists
  • Else returns null

Now that the ValueProviderDictionary has extracted the necessary strings from the incoming request, the DefaultModelBinder class takes on the responsibility of converting these strings into appropriate .NET objects.

When the DefaultModelBinder is required to supply an instance of some custom .NET type, Reflection comes for the rescue. Using reflection, all the public properties exposed by the custom type receive values based on what the ValueProviderDictionary class provided. Do bear in mind that there’s some kind of recursion happening here and that’s how all properties and its sub-properties get set with values.

That was all the magic which MVC does behind the scenes and I hope this explanation helps somebody in clearing their doubts.