Injecting services into entities
Entities with async construction
- Created entity is NOT immediately usable.
- Entity code now generally needs safety code to throw if not fully initialised
Musing from a developer.
I built this a while ago; others may find it handy.
It's a small library focussing primarily on syntax sugar for C#
kwd.CoreUtil v1.1.0: Git / Nuget
The main code is a set of extensions to make working with FileInfo and DirectoryInfo more natural.
In addition there are some other utilities for strings and file streams.
Originally the design was to restrict this to ONLY depend on standard .NET Core packages.
But more recently I stumbled onto System.IO.Abstractions; since the package is lite, and provides significant benefit; I've take it as a dependency
I've finally got Team City to run on Azure with the built-in database. But I was having terrible trouble getting my unit tests (MSTest) to run.
The error: 'Could not load file or assembly Autofac ...'
Every thing looked fine. Local build / test worked like a dream. NuGet packages loaded. CI build log showed Autofac was nu-get downloaded, and build success... I even fell back to RDP to build-box and run tests; again, success.
I used a simple short-hand to tell team city where the test assembly was: src/core.tests/**/*.tests.dll. This was (unexpected, by me at least) picking up both
The fix is simple, just use a more exact setting in Team City src/core.tests/bin/Debug/*.tests.dll
Recently I needed to create a link to edit a content item in Orchard. Orchard uses a url like http://mysite/Home/Admin/Contents/Edit/123, where the id corresponds to the content item id.
My first thought was to hand-craft the url, replacing the content id as needed. But I found a better way: use the item's meta-data. Firstly inject the orchard IContentManager as usual, then call IContentManager.GetItemMetadata() The returned ContentItemMetadata contains MVC route's, for my particular case, EditorRouteValues had all the data I needed.
In my exploration of Orchard, I am continually finding myself having to dive into the code to work out how to do things. So here is 'how' I finally stumbled on the meta data solution.
Firstly I knew the Content Control Wrapper performed some 'magic' which added a link to a content item's edit.
Alas so-far I have no special trick for getting from a feature to the code that implements it. But eventually I found Orchard.Core/Contents/ControlWrapper.cs which implements the feature as a IShapeTableProvider. In here we see Content is wrapped with a Content_ControlWrapper shape.
Since nothing particularly enlightening is happening, I went to the view for the shape: Orchard.Core/Views/Content.ControlWrapper.cshtml. In the view the Html.ItemEditLinkWithReturnUrl() caught my eye.
This ItemEditLinkWithReturnUrl() is an extension, tracked down to Orchard.Framework/Mvc/Html/ContentItemExtensions.cs
Navigating to find the core ItemEditLink helper, bingo, I found how the content item meta-data is used for route values.
While working on a module for Orchard CMS I ran into some problems trying to glue async (Task) based code with (classic) synchronous code.
Here's the set-up:TheMoveDb uses Tasks, so I don't have to wait around for across-the-wire calls. MovieInfo uses Tasks, and integrates with orchard services. AdminController uses normal Action methods.
Being a TDD developer, all the pieces looked fine. But as soon as I put it together... splat.
It all starts with a deadlock (doesn't it always!). A quick google gets to Stephen Cleary (via SO) Don't Block on Async Code and Async and Await Armed with this I now at-least understand the problem.
Alas, at least in Orchard 1.6, async controllers are a no-go. It took a fair bit of searching, I finally found an SO article describing the problem. So (for now) I've settled on a sync / async solution.
Putting it all together:There was one last gotcha; anything after the await in MovieInfo service executes on its own thread. So no access to orchard services (such as WorkContext etc). To get around this I just had to take care to no need the 'orchard friendly' thread context after the await.
Injecting services into entities It been bugging me for a while now that to use services in a entity can be a bit of pain. It usually starts...