Some serverside functions take a while to complete, this can cause IIS thread starvation, which is addressed by MVC's AsyncController. Great! :-)
However, from a user's perspective nothing changes. They still have to wait x seconds for the page to respond and are are usually stuck on a white page that looks like the server isnt doing anything :-(
That's where AsyncSections come in! Imagine if you could seperate your view into sections which contain the results of your long running functions. Now you can! These are seperated from normal document rendering to allow the page to load first, then load in the results when they are ready.
Check out the comparison demo to see AsyncSections in action.
Whenever you are doing something on the server that takes a few seconds but you dont want to make the user wait before allowing them to use the site. For example...
- Processing an imported spreadsheet
- Waiting for 3rd party APIs to respond
- Doing some processing on all records in the database
- Generating documents
- Bulk functions like emailing all users or creating notification records
- Updating the database schema of the site using an EF 4.3 data migration :-)
- Use your imagination
In theory, any page that accesses the database could use an AsyncSection, especially if it runs multiple different queries that display their results in different areas of the page, like a KPI dashboard
AsyncSections are standard MVC sections which are suffixed with "Async" but they dont get rendered to the page in the standard way.
There is a new AsyncSectionController which contains the new AsyncView() and AsyncSection() methods. These combined with the new RenderBodyAsync() helper will split the page into multiple render stages.
- MasterPage is rendered up to the call to RenderBodyAsync()
- The body is rendered excluding anything in an AsyncSection
- A number of AsyncSections are rendered
- The last half of the MasterPage is rendered after the call to RenderBodyAsync()
In the example above, you will see that the element in the Task1Async section will be rendered after the example footer
Good point! AsyncSections will nativly only get rendered just after your RenderBodyAsync() call. In order to load content into specific parts of the page you will need to employ some kind of javascript based solution (or css if your design permits). For this reason I have also created a small helper library calles jsTransform which may get its own repo one day if it gets enough use. You can see this in action in the Multiple Tasks Demo
jsTransform checks the page for new elements every 100ms until the document is ready. If the element has one of the transform attributes (transform-append, transform-replace or transform-removeClass) then it will act on the element and remove the attributes.
In the example above you can see that there is an unordered list with an id of consoleList and the AsyncSection contains a list item that has a transform-append attribute with a value of consoleList. This will take the list item and append it to the unordered list as soon as the list item arrives on the page.
Because AsyncSections arrive after the page has first rendrered, they will appear to blink at the bottom of the page until jsTransform moves them to their desired position in the DOM. To get arround this, I have added a hidden class to the list item that gets removed once the item element is transformed. There are many different ways to solve this problem, but this is a quick way to get you started.
The jsTransform library is currently quite small and only contains 3 attributes, but it will grow over time as people need more from it. Or alternatively, you can use any javascript library you like, its up to you!
AsyncSections is a research project that contains a lot of reflection on the internals of MVC4 and should not really be used in a production environment. The idea was to show what was possible with a few small tweaks of the Rendering system and with a bit of luck, get something similar added to a roadmap for MVC5+
For this reason, this project will probably only ever have a pre release NuGet package
Please show your support for this project by sharing it with others and letting the MVC team know you would like a feature like this in the future. Fingers crossed :-)
If you got this far, thank you for taking the time to read this document