Tag Archives: .Net

Applying configuration transforms outside Visual Studio

Recently I was putting a NuGet package together and one of the things the package needs to do is change the configuration file when added to a project.

NuGet 2.7 and forward supports the use of XDT transformation files in the form of .install.xdt and .uninstall.xdt that run during package install and uninstall respectively.

However, all the files that are part of a NuGet package composition are usually outside projects in Visual Studio, so I needed a way to test that these transformations actually worked on a live config file.

To achieve this I wrote a PowerShell script that references the Microsoft.Web.XmlTransform.dll assembly that executes the transformation, applies the transformation and writes to an out.xml file in the same location as the script. The path to the XmlTransform dll is hardcoded into the script, but it is the path on a default installation of Visual Studio 2015.


param
(
[parameter(Mandatory=$true)]
[string]
$Xml,
[parameter(Mandatory=$true)]
[string]
$Xdt
)
if (!(Test-Path -path $Xml -PathType Leaf))
{
throw "XML File not found. $Xml"
}
if (!(Test-Path -path $Xdt -PathType Leaf))
{
throw "XDT File not found. $Xdt"
}
Add-Type -LiteralPath "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\spzpqgng.yjx\Microsoft.Web.XmlTransform.dll"
$xmldoc = New-Object Microsoft.Web.XmlTransform.XmlTransformableDocument
$xmldoc.PreserveWhitespace = $true
$xmldoc.Load($Xml)
$transf = New-Object Microsoft.Web.XmlTransform.XmlTransformation($xdt)
if ($transf.Apply($xmldoc) -eq $false)
{
throw "Transformation failed."
}
$xmldoc.Save("$PSScriptRoot\out.xml")

Validation in WebForms with Data Annotations

Some very old projects get enough development time so that certain parts of them move forward, but too often this time isn’t enough for a full re-write to modern day technologies.

In most scenarios the persistence layer will move forward before the Web UI. This is because legacy WebForms projects relied on patterns like the Supervising Controller that don’t translate directly to modern implementations like ASP.NET’s MVC. Migrating projects from old legacy patterns to ASP.NET MVC usually starts with the persistence layer because presenters wrap and transform models into what the view needs instead of providing a way to directly bind these; changing the persistence layer into something that can be bound directly, refactoring the presenter first and paving the way to replacing presenters with controllers is usually the way to go.

In a scenario where a legacy persistence layer is left intact and a change from WebForms to ASP.NET MVC is done instead, it usually takes longer to execute due to the fact that Model wrappers need to be written that wrap around the old persistence layer and bind directly to the views, along with the usual view re-writing and refactoring presenters into controllers. These wrappers also add obscurity to the overall solution, so anyone maintaining the solution between the changes will have a hard time with it.

Doing ASP.NET WebForms validation with Data Annotations

ASP.NET WebForms does validation through a series of ASP.NET Validation Server Controls, what they have in common is that they all inherit from BaseValidator. The strategy is to start from this inheritance, expose two additional properties for the name of the property we want to validate and another for the type of the class where this property exists.

/// <summary>
/// Exposes the Property Name that we want to validate against.
/// </summary>
public string PropertyName { get; set; }
        
/// <summary>
/// Exposes the SourceType for Data Annotation lookup that we want to validate against.
/// </summary>
public string SourceType { get; set; }

The BaseValidator class has an abstract method EnsureIsValid that is the main override point for creating our own Validator. By getting the PropertyName and the SourceType you can use reflection and get the Data Annotations, then use these to check for Validation and to properly create and format the Error Message.

/// <summary>
/// Performs the real Validation process, sets the isValid flag on the
/// BaseValidator class.
/// </summary>
/// <returns>If the property if Valid or Not.</returns>
protected override bool EvaluateIsValid()
{
    var objectType = Type.GetType(SourceType, true, true);
    var property = objectType.GetProperty(PropertyName);

    var control = base.FindControl(ControlToValidate) as TextBox;

    if(control == null)
        throw new InvalidOperationException("This implementation can only be used to validate Textbox controls, attempting to validate something else will fail!");

    foreach (var attr in property.GetCustomAttributes(typeof (ValidationAttribute), true)
                                    .OfType<ValidationAttribute>()
                                    .Where(attr => !attr.IsValid(control.Text)))
    {
        // This implementation will break on the first attribute fail and will only return the first error found.
        // I kept the foreach and the where clause to allow for easier transition into an implementation that
        // tracks and displays all the errors found and not just the first one!
        var displayNameAttr = property.GetCustomAttributes(typeof (DisplayNameAttribute), true)
                                        .OfType<DisplayNameAttribute>()
                                        .FirstOrDefault();

        var displayName = displayNameAttr == null ? property.Name : displayNameAttr.DisplayName;
        ErrorMessage = attr.FormatErrorMessage(displayName);
        return false; 
    }

    return true;
}

This is a very naive implementation, it will only work with the TextBox control, explicitly throwing otherwise:

var control = base.FindControl(ControlToValidate) as TextBox;

if(control == null)
    throw new InvalidOperationException("This implementation can only be used to validate Textbox controls, attempting to validate something else will fail!");

And it doesn’t do any proper logging and trapping of the reflection bits in the code, if there’s any problem setting the SourceType and PropertyName, like for example a typo, it just blows up without any exception handling:

var objectType = Type.GetType(SourceType, true, true);
var property = objectType.GetProperty(PropertyName);

Usage examples

To use the DataAnnotationValidator simply add it where you want the validation text to appear like for example:

<asp:Label ID="CardFirstNameTextLabel" runat="server" CssClass="FormLabel" AssociatedControlID="CardFirstNameText">First Name</asp:Label>
<asp:TextBox ID="CardFirstNameText" runat="server" AutoCompleteType="firstname" />

<val:DataAnnotationValidator ID="FirstNameValidator" runat="server"
    ControlToValidate="CardFirstNameText" Text="**" PropertyName="FirstName" SourceType="InnerWorkings.Model.CardDetails, InnerWorkings.Model" />

<span class="Notes">(as it appears on the card)</span>

You can also use the built in ASP.NET ValidationSummary control to display the validation errors summary:

<asp:ValidationSummary runat="server" ID="vSumAll" DisplayMode="BulletList" CssClass="validation-errors" HeaderText="<span>Oops! Please fix the following errors:</span>" />

The full source Code for the DataAnnotationValidator

namespace ValidationWithDataAnnotations
{
    using System;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Web.UI.WebControls;

    /// <summary>
    /// Reasonable wrapper for performing Validation using Data Annotations.
    /// With the inclusion of EntityFramework in the solution, all model elements are properly
    /// Data Annotated, so the logical path is to perform UI validation using the same set
    /// of annotations used by EF.
    /// The Validator still requires the setting of PropertyName and SourceType, this is
    /// where this class could be improved, as both these things can be looked up instead of
    /// just set.
    /// </summary>
    public class DataAnnotationValidator : BaseValidator
    {
        /// <summary>
        /// Exposes the Property Name that we want to validate against.
        /// </summary>
        public string PropertyName { get; set; }
        
        /// <summary>
        /// Exposes the SourceType for Data Annotation lookup that we want to validate against.
        /// </summary>
        public string SourceType { get; set; }

        /// <summary>
        /// Performs the real Validation process, sets the isValid flag on the
        /// BaseValidator class.
        /// </summary>
        /// <returns>If the property if Valid or Not.</returns>
        protected override bool EvaluateIsValid()
        {
            var objectType = Type.GetType(SourceType, true, true);
            var property = objectType.GetProperty(PropertyName);

            var control = base.FindControl(ControlToValidate) as TextBox;

            if(control == null)
                throw new InvalidOperationException("This implementation can only be used to validate Textbox controls, attempting to validate something else will fail!");

            foreach (var attr in property.GetCustomAttributes(typeof (ValidationAttribute), true)
                                         .OfType<ValidationAttribute>()
                                         .Where(attr => !attr.IsValid(control.Text)))
            {
                // This implementation will break on the first attribute fail and will only return the first error found.
                // I kept the foreach and the where clause to allow for easier transition into an implementation that
                // tracks and displays all the errors found and not just the first one!
                var displayNameAttr = property.GetCustomAttributes(typeof (DisplayNameAttribute), true)
                                              .OfType<DisplayNameAttribute>()
                                              .FirstOrDefault();

                var displayName = displayNameAttr == null ? property.Name : displayNameAttr.DisplayName;
                ErrorMessage = attr.FormatErrorMessage(displayName);
                return false; 
            }

            return true;
        }
    }
}

Creating a Notification button in WPF

Recently, I had to create a button that besides doing it’s normal job, would also show the amount of tasks that the User had to do inside that button.

To do this I decided to mimic the Notification button of popular Mobile Operating Systems do these days

ios_notifywp_notify

The end result was this:

notify

The full download of the solution can be found here

1.Button Framework

The button inherits from the WPF base button class, and is declared in a custom user control library, so the button style, that is not looked at in this post, is declared in the Generic.xaml file.

It implements a set of dependency properties to control the pooling for new Notifications, and the actual red circle showing the number is a WPF Adorner, so that it can overlap content on the visual tree and abstract the developer from the implications on the layout while using it.

To keep a clean WPF structure I implemented a fake delegate on a ViewModel that mimics our functionality of pooling a Web Service, this ViewModel is attached to the MainWindow, but in the real world we would have something like a menu bar and a menu bar ViewModel and these things would be implemented in those places.

The button usage is as follow:

<StackPanel VerticalAlignment="Center" Orientation="Vertical">
    <lib:NotificationButton Width="40"
                            Height="40"
                            NotifyFunc="{Binding NotifyDelegate}"
                            Poll="{Binding ElementName=PollCheck,
                                            Path=IsChecked}"
                            PollInterval="5">

        <TextBlock HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    FontSize="20"
                    FontWeight="Bold">
            R
        </TextBlock>

    </lib:NotificationButton>

    <CheckBox Name="PollCheck" IsChecked="True" />
</StackPanel>

2. Dependency Properties

The button exposes the following functionality:

  • NotifyFunc – The delegate of type Func<int> that gives you the Notification Number
  • Poll – True or False, tells the button whether to poll or not. Useful for scenarios where for example the button is hidden or collapsed and you want to stop polling.
  • PollInterval – In seconds, allows to configure the interval of the polling.

The implementation looks something like this:

#region Dependency Properties
#region PollInterval
public static readonly DependencyProperty PollIntervalProperty = DependencyProperty.Register(
    "PollInterval",
    typeof(Int32),
    typeof(NotificationButton),
    new UIPropertyMetadata(60) // default value for this DP
    );

public int PollInterval
{
    get { return (int)GetValue(PollIntervalProperty); }
    set { SetValue(PollIntervalProperty, value); }
}
#endregion

#region Poll
public static readonly DependencyProperty PollingProperty = DependencyProperty.Register(
    "Poll",
    typeof(Boolean),
    typeof(NotificationButton),
    new UIPropertyMetadata(true, OnPollChanged) // default value for this DP
    );

public bool Poll
{
    get { return (bool)GetValue(PollingProperty); }
    set { SetValue(PollingProperty, value); }
}

public void StartPolling()
{
    _timer.Change(PollInterval * 1000, PollInterval * 1000);
}

public void StopPolling()
{
    _timer.Change(Timeout.Infinite, Timeout.Infinite);
}

private static void OnPollChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var nb = (NotificationButton)d;

    if ((bool)e.NewValue) nb.StartPolling();
    else nb.StopPolling();
}
#endregion

#region NotificationFunc
public static readonly DependencyProperty NotifyFuncProperty = DependencyProperty.Register(
    "NotifyFunc",
    typeof(Func<int>),
    typeof(NotificationButton)
    );

public Func<int> NotifyFunc
{
    get { return (Func<int>)GetValue(NotifyFuncProperty); }
    set { SetValue(NotifyFuncProperty, value); }
}
#endregion
#endregion

3.The Adorner

The Adorner is implemented on the same file as the button, because it is not shared by other controls, however you could isolate it on a different file to make it easier to reuse it.

The only specific thing is that I use the drawing context to draw direct primitives instead of instantiating WPF controls:

/// <summary>
/// The Notification adorner.
/// On Render implements direct drawing context calls.
/// </summary>
public class NotificationAdorder : Adorner
{
    public NotificationAdorder(UIElement adornedElement)
        : base(adornedElement)
    {
        DataContextChanged += NotificationAdorderDataContextChanged;
    }

    private void NotificationAdorderDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        InvalidateVisual();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        if (DataContext == null) return; // Break if we don't have the Adorner databound

        var adornedElementRect = new Rect(AdornedElement.DesiredSize);
        var typeFace = new Typeface(new FontFamily("Courier New"), FontStyles.Normal, FontWeights.ExtraBold,
                                    FontStretches.Condensed);

        var text = new FormattedText(
            DataContext.ToString(),
            CultureInfo.GetCultureInfo("en-us"),
            FlowDirection.RightToLeft,
            typeFace,
            16, Brushes.White
            );

        var pointOfOrigin = new Point
                                {
                                    X = adornedElementRect.BottomRight.X,
                                    Y = adornedElementRect.BottomRight.Y - text.Height * 0.7
                                };

        var elipseCenter = new Point
                                {
                                    X = pointOfOrigin.X - text.Width / 2,
                                    Y = pointOfOrigin.Y + text.Height / 2
                                };

        var elipseBrush = new SolidColorBrush
                                {
                                    Color = Colors.DarkRed,
                                    Opacity = 0.8
                                };

        drawingContext.DrawEllipse(
            elipseBrush,
            new Pen(Brushes.White, 2),
            elipseCenter,
            text.Width * 0.9,
            text.Height * 0.5
            );

        drawingContext.DrawText(text, pointOfOrigin);
    }
}

The adorner is attached to the button on the Loaded delegate

var adornerLayler = AdornerLayer.GetAdornerLayer(this);
_adorner = new NotificationAdorder(this) {DataContext = null};
adornerLayler.Add(_adorner);

Of note is also the fact that we need to capture the datacontext changed even, so that we can call the InvalidateVisual to force WPF to redraw the Adorner.

4.Other Parts of interest

It is important to never block the WPF UI thread of calls to Web Services, to accomplish this I used a bit of TPL code to first get some dependency properties in the UI thread, then call the Web Service in a separate thread, and finally rebind the data in the UI thread:

/// <summary>
/// Delegates the fake Web Service call onto a different thread, while retaining the UI Thread to update the UI
/// </summary>
/// <param name="state"></param>
private void CheckContent(object state = null)
{
    int? delegateReturn = 0;
    Func<int> func = null;

    Task.Factory.StartNew(() =>
                                {
                                    func = NotifyFunc;
                                }
        , new CancellationToken(), TaskCreationOptions.None, _uiContext)
        .ContinueWith(t =>
                            {
                                delegateReturn = func();
                                if (delegateReturn < 1) delegateReturn = null; // Normalize to not show if not at least 1
                            }
        )
        .ContinueWith(t =>
                        {
                            _adorner.DataContext = delegateReturn;
                        }
        , new CancellationToken(), TaskContinuationOptions.None, _uiContext);
}

To control the pooling I used a System.Threading.Timer that is created on the Loaded delegate:

_timer = new Timer(CheckContent, null, Timeout.Infinite, Timeout.Infinite);
if (Poll) _timer.Change(PollInterval * 1000, PollInterval * 1000);

And controlled by these 2 utility methods:

public void StartPolling()
{
    _timer.Change(PollInterval * 1000, PollInterval * 1000);
}

public void StopPolling()
{
    _timer.Change(Timeout.Infinite, Timeout.Infinite);
}

5.The ViewModel

It is a very simple ViewModel, that basically declared and implements the Function delegate:

/// <summary>
/// The view model, with a fake implementation that calls a 1 sec sleep to make sure the UI is never blocked.
/// </summary>
public class NotificationViewModel
{
    public NotificationViewModel()
    {
        NotifyDelegate = NotificationImplementation;
    }

    public Func<int> NotifyDelegate { get; set; }

    private static int NotificationImplementation()
    {
        var r = new Random();
        Thread.Sleep(1000);
        return r.Next(1, 99);
    }
}