.NET Core Reloaded

OK, so here’s another post on .NET Core from a non-code perspective.

There has been recently lots of discussion about this all over the Internet!We are all well aware that .NET Core, which hasn’t been released yet (June 1st), has had some rough times. RC1 has been out for quite some time with a Go Live license, and RC2 just hit the streets a few weeks ago, substantially delayed according to the original schedule. The problem was, from RC1 to RC2 things have changed a lot, and are even going to change more with RTM.

We knew from day one that we wouldn’t have AppDomains, binary serialization, Remoting, sandboxing, Windows Forms, WPF, WCF and WWF, and most of us were cool about that. Also, having project.json instead of the old MSBuild seemed a step in the right direction – that is, the direction driven by Node.js and modern JavaScript technologies. Relying on Nuget for dependencies was also something that we were already doing, just not for the core assemblies. Having a smaller API surface than the one we were used to was harder to digest, but we could live with it.

But then it hit us: project.json is no more, and MSBuild is back, even if slightly crippled! Also, AppDomains will make a comeback, too… and so most of the “old” APIs, now hopefully sanitized for cross-platformity!

We recently had to put up with the horrible mess of KRE, DNU, DNX, DNVM just to end up with DOTNET. At some point we got a global service locator (something that the .NET Core team treats worse than the Devil itself) and them we lost it, as we did with property injection for ASP.NET MVC controllers (likewise), the ability to populate models from JSON or HTTP POSTs (also gone) and lots of namespace and type changes.

Let’s be clear: on the communication side, as well as in managing people’s expectations, Microsoft blew it. Even if in some aspects (IMO), they are going in the right direction, they got it all wrong. It seems that they haven’t given things enough thought, or have been experimenting with it for too long. Things don’t usually change so dramatically between RCs. How can software developers who have commercial products to release, are expected to deal with so many changes?

On the other hand, these were (are) RCs, meaning, pre-release versions, and nobody said that these would remain untouched. I don’t think these affect the global goal of .NET Core: having a modular, modern, cross-platform framework. I expect when it does come out, most problems will fade away. As we speak, it already runs in Linux Docker containers, and we can debug it from Visual Studio – and Visual Studio Code. I kind of like going back to MSBuild, because it is so much more powerful than project.json. Bringing back AppDomains only widens our horizons, not the opposite. And I really, really like the stuff they’ve been doing in ASP.NET MVC Core.

.NET Core will give us more flexibility, in the sense that we aren’t limited in using Windows as the deployment target. For myself, it’s going to be about the capability to deploy Linux VMs as Docker containers, but this time running .NET, and not just Node.js. I don’t see myself moving to full-time Linux or Mac development, but Visual Sudio Code and Project Rider do seem to make it possible. None of this was affected by all the shifts and changes that occurred in the .NET Core gestation. Only confidence in the Microsoft .NET Core team was affected, to some level.

So, in retrospective, I think Microsoft has learned a lesson. Give stuff more thought before announcing it or making it public (I know, I know, .NET Core is open source, so the repo is publicly visible), hear from the community before making changes and not after them, and stick to your decisions! Winking smile


ASP.NET Formatted String Control

Back to ASP.NET Web Forms land! SharePoint includes a handy control, FormattedString, that can be used to render the contents of its child controls as specified in a format string; pretty much what String.Format does. I wanted to do the same with plain old ASP.NET Web Forms, and here’s what I came up with:

[ParseChildren(false)]

[PersistChildren(true)]

[ControlBuilder(typeof(FormattedControlControlBuilder))]

public class FormattedControl : Control

{

    public String FormatString { get; set; }

 

    protected override void RenderChildren(HtmlTextWriter writer)

    {

        if (String.IsNullOrWhiteSpace(this.FormatString) == false)

        {

            var list = new List<String>();

            var builder = new StringBuilder();

            var sw = new StringWriter(builder);

            var hw = new HtmlTextWriter(sw);

 

            foreach (var control in this.Controls.OfType<Control>())

            {

                control.RenderControl(hw);

 

                list.Add(builder.ToString());

 

                builder.Clear();

            }

 

            writer.Write(this.FormatString, list.ToArray());

        }

        else

        {

            base.RenderChildren(writer);

        }

    }

}

 

public class FormattedControlControlBuilder : ControlBuilder

{

    public override Boolean AllowWhitespaceLiterals()

    {

        return false;

    }    

}

Key points are:

  • FormattedControl will not render as default, instead, it will capture the output of all of its child controls into a list and pass it as a parameter to the FormatString string, as {0}, {1}, etc;
  • ParseChildrenAttribute and PersisteChildrenAttribute are used to tell ASP.NET how to treat the controls declared inside FormattedControl;
  • The ControlBuilderAttribute is used to declare a custom control builder; this custom builder just tells ASP.NET to ignore whitespaces inside the control’s tag, otherwise, we would get a LiteralControl for each tab / space / return character present inside the FormattedControl’s tag, together with those controls explicitly declared.

An example:

<my:FormattedControl runat="server" FormatString="{1}, {0}!">

    <asp:Literal runat="server" Text="World"/>

    <asp:Literal runat="server" Text="Hello"/>

</my:FormattedControl>

Of course, you should only use FormattedControl with controls that return string literals, otherwise, you will probably get a lot of garbage in the output.