TheMar
TheMar

Reputation: 1964

C# Async and Await flow

I am trying to understand async and await flow . Started looking at code from
John Atten's blog about Owin and Katana . While trying to look at the execution steps I found few steps in the flow (Steps 9 and 16), which I am not able to understand as to why the execution will traverse.

code:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using Owin;
namespace KatanaConsole
{
    //use an alias for OWIN APPFunc
    using AppFunc= Func<IDictionary<string,object>,Task>;
    class Program
    {
        static void Main(string[] args)
        {

            var uri = "http://localhost:8080";

            using ( WebApp.Start<StartUp>(uri))
            {
                Console.WriteLine("Web Server started on port 2323");
                 Console.WriteLine("Server Started; Press enter to Quit");
                Console.ReadLine();
            }
        }
    }

    public class StartUp
    {
        public void Configuration(IAppBuilder appBuilder)
        {
        var firstMiddleware= new Func<AppFunc,AppFunc>(FirstMiddleware);
        var secondMiddleware = new Func<AppFunc, AppFunc>(SecondMiddleware);

        appBuilder.Use(firstMiddleware);
        appBuilder.Use(secondMiddleware);

        }


        public AppFunc FirstMiddleware(AppFunc next)
        {

            AppFunc appFunc = async environment =>
            {
                IOwinContext context = new OwinContext(environment);
                await context.Response.WriteAsync("<h1> Middleware:1 ->  Hello from X1</h1>");
                await next.Invoke(environment);
            };
            return appFunc;
        }

        public AppFunc SecondMiddleware(AppFunc next)
        {

            AppFunc appFunc = async (IDictionary<string, object> environment) =>
            {
                IOwinContext context = new OwinContext(environment);
                await context.Response.WriteAsync("<h1> Middleware:2 ->  Hello from X2</h1>");
                await next.Invoke(environment);
            };
            return appFunc;
        }
    }


}

The code flow when I try to access localhost:8080

Flow:

Enters ->First Middleware

  1. IOwinContext context = new OwinContext(environment);
  2. await context.Response.WriteAsync("<h1> Middleware:1 -> Hello from X1</h1>"); // Response Sent to browser
  3. await next.Invoke(environment);

Enters -> Second Middleware

  1. IOwinContext context = new OwinContext(environment);

  2. await context.Response.WriteAsync("<h1> Middleware:2 -> Hello from X2</h1>");// Response Sent to browser

  3. await next.Invoke(environment);

Enters (Back to Calling Method) -> First Middleware

  1. await next.Invoke(environment);

  2. Exits -> FirstMiddleWare

Re-Enters ->First Middleware

  1. IOwinContext context = new OwinContext(environment);

  2. await context.Response.WriteAsync("<h1> Middleware:1 -> Hello from X1</h1>"); // No Response Sent to browser

  3. await next.Invoke(environment);

Re-Enters -> Second Middleware

  1. IOwinContext context = new OwinContext(environment);

  2. await context.Response.WriteAsync("<h1> Middleware:2 -> Hello from X2</h1>");// No Response Sent to browser

  3. await next.Invoke(environment);

Re-Enters (Back To Calling Method) -> First Middleware

  1. await next.Invoke(environment);

  2. Exits -> FirstMiddleWare

Execution Stops My question is why does it traverse again Steps 9 and 16?

and add to it, even though Step 9 and 16 are traversed , response does not change. So I am guessing it is doing some post condition check there.

** Edit - 1 **

Added All steps traversed to make it more clear( added steps 9 to 16)

Upvotes: 4

Views: 747

Answers (1)

kalitsov
kalitsov

Reputation: 1639

Steps 9 to 16 are traversed because of an automatic second request you get from the browser for the favicon. If you pay attention to the context.Request.Path you will notice that the first round through the middleware is for "/" and the second for "/favicon.ico". Actually the behavior depends on the browser you are using to make the request. I've tested with the most resent version of a couple of browsers and with Webkit browsers (Chrome and Opera) plus IE i always get a request for the favicon. With FF i do get it just the first time and it's being cached. And with Edge - it's not been requested at all.

Upvotes: 1

Related Questions